1 Scope [intro.scope]

This document specifies requirements for implementations of the C++ programming language.
The first such requirement is that an implementation implements the language, so this document also defines C++.
Other requirements and relaxations of the first requirement appear at various places within this document.
C++ is a general purpose programming language based on the C programming language as described in ISO/IEC 9899:2018.
C++ provides many facilities beyond those provided by C, including additional data types, classes, templates, exceptions, namespaces, operator overloading, function name overloading, references, free store management operators, and additional library facilities.

2 Normative references [intro.refs]

The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document.
For dated references, only the edition cited applies.
For undated references, the latest edition of the referenced document (including any amendments) applies.
  • ISO/IEC 2382, Information technology — Vocabulary
  • ISO 8601-1:2019, Date and time — Representations for information interchange — Part 1: Basic rules
  • ISO/IEC 9899:2018, Information technology — Programming languages — C
  • ISO/IEC/IEEE 9945:2009, Information Technology — Portable Operating System Interface (POSIX®)1 Base Specifications, Issue 7
  • ISO/IEC/IEEE 9945:2009/Cor 1:2013, Information Technology — Portable Operating System Interface (POSIX®) Base Specifications, Issue 7 — Technical Corrigendum 1
  • ISO/IEC/IEEE 9945:2009/Cor 2:2017, Information Technology — Portable Operating System Interface (POSIX®) Base Specifications, Issue 7 — Technical Corrigendum 2
  • ISO/IEC 60559:2020, Information technology — Microprocessor Systems — Floating-Point arithmetic
  • ISO 80000-2:2019, Quantities and units — Part 2: Mathematics
  • Ecma International, ECMAScript2 Language Specification, Standard Ecma-262, third edition, 1999.
  • The Unicode Consortium.
    The Unicode Standard.
1)1)
POSIX® is a registered trademark of the Institute of Electrical and Electronic Engineers, Inc.
This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of this product.
2)2)
ECMAScript® is a registered trademark of Ecma International.
This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of this product.

3 Terms and definitions [intro.defs]

For the purposes of this document, the terms and definitions given in ISO/IEC 2382, ISO 80000-2:2019, and the following apply.
ISO and IEC maintain terminology databases for use in standardization at the following addresses:

3.1[defns.access]access

⟨execution-time action⟩ read or modify the value of an object
[Note 1: 
Only glvalues of scalar type can be used to access objects.
Reads of scalar objects are described in [conv.lval] and modifications of scalar objects are described in [expr.ass], [expr.post.incr], and [expr.pre.incr].
Attempts to read or modify an object of class type typically invoke a constructor or assignment operator; such invocations do not themselves constitute accesses, although they may involve accesses of scalar subobjects.
— end note]

3.2[defns.argument]argument

⟨function call expression⟩ expression in the comma-separated list bounded by the parentheses

3.3[defns.argument.macro]argument

⟨function-like macro⟩ sequence of preprocessing tokens in the comma-separated list bounded by the parentheses

3.4[defns.argument.throw]argument

⟨throw expression⟩ operand of throw

3.5[defns.argument.templ]argument

⟨template instantiation⟩ constant-expression, type-id, or id-expression in the comma-separated list bounded by the angle brackets

3.6[defns.block]block

⟨execution⟩ wait for some condition (other than for the implementation to execute the execution steps of the thread of execution) to be satisfied before continuing execution past the blocking operation

3.7[defns.block.stmt]block

⟨statement⟩ compound statement

3.8[defns.c.lib]C standard library

library described in ISO/IEC 9899:2018, Clause 7
[Note 1: 
With the qualifications noted in [support] through [exec] and in [diff.library], the C standard library is a subset of the C++ standard library.
— end note]

3.9[defns.character]character

⟨library⟩ object which, when treated sequentially, can represent text
[Note 1: 
The term does not mean only char, char8_t, char16_t, char32_t, and wchar_t objects ([basic.fundamental]), but any value that can be represented by a type that provides the definitions specified in [strings], [localization], [input.output], or [re].
— end note]

3.10[defns.character.container]character container type

⟨library⟩ class or a type used to represent a character ([defns.character])
[Note 1: 
It is used for one of the template parameters of char_traits and the class templates which use that, such as the string, iostream, and regular expression class templates.
— end note]

3.11[defns.regex.collating.element]collating element

sequence of one or more characters ([defns.character]) within the current locale that collate as if they were a single character

3.12[defns.component]component

⟨library⟩ group of library entities directly related as members, parameters ([defns.parameter]), or return types
[Note 1: 
For example, the class template basic_string and the non-member function templates that operate on strings are referred to as the string component.
— end note]

3.13[defns.cond.supp]conditionally-supported

program construct that an implementation is not required to support
[Note 1: 
Each implementation documents all conditionally-supported constructs that it does not support.
— end note]

3.14[defns.const.eval]constant evaluation

evaluation that is performed as part of evaluating an expression as a core constant expression ([expr.const])

3.15[defns.const.subexpr]constant subexpression

expression whose evaluation as subexpression of a conditional-expression CE would not prevent CE from being a core constant expression

3.16[defns.deadlock]deadlock

⟨library⟩ situation wherein one or more threads are unable to continue execution because each is blocked ([defns.block]) waiting for one or more of the others to satisfy some condition

3.17[defns.default.behavior.impl]default behavior

⟨library implementation⟩ specific behavior provided by the implementation, within the scope of the required behavior ([defns.required.behavior])

3.18[defns.diagnostic]diagnostic message

message belonging to an implementation-defined subset of the implementation's output messages

3.19[defns.dynamic.type]dynamic type

⟨glvalue⟩ type of the most derived object to which the glvalue refers
[Example 1: 
If a pointer p whose static type is “pointer to class B” is pointing to an object of class D, derived from B, the dynamic type of the expression *p is “D.
References are treated similarly.
— end example]

3.20[defns.dynamic.type.prvalue]dynamic type

⟨prvalue⟩ static type ([defns.static.type]) of the prvalue expression

3.21[defns.erroneous]erroneous behavior

well-defined behavior that the implementation is recommended to diagnose
[Note 1: 
Erroneous behavior is always the consequence of incorrect program code.
Implementations are allowed, but not required, to diagnose it ([intro.compliance.general]).
Evaluation of a constant expression ([expr.const]) never exhibits behavior specified as erroneous in [intro] through [cpp].
— end note]

3.22[defns.expression.equivalent]expression-equivalent

⟨library⟩ expressions that all have the same effects, either are all potentially-throwing or are all not potentially-throwing, and either are all constant subexpressions ([defns.const.subexpr]) or are all not constant subexpressions
[Example 1: 
For a value x of type int and a function f that accepts integer arguments, the expressions f(x + 2), f(2 + x), and f(1 + x + 1) are expression-equivalent.
— end example]

3.23[defns.regex.finite.state.machine]finite state machine

⟨regular expression⟩ unspecified data structure that is used to represent a regular expression ([defns.regex.regular.expression]), and which permits efficient matches against the regular expression to be obtained

3.24[defns.regex.format.specifier]format specifier

⟨regular expression⟩ sequence of one or more characters ([defns.character]) that is expected to be replaced with some part of a regular expression ([defns.regex.regular.expression]) match

3.25[defns.handler]handler function

⟨library⟩ non-reserved function whose definition may be provided by a C++ program
[Note 1: 
A C++ program may designate a handler function at various points in its execution by supplying a pointer to the function when calling any of the library functions that install handler functions (see [support]).
— end note]

3.26[defns.ill.formed]ill-formed program

program that is not well-formed

3.27[defns.impl.defined]implementation-defined behavior

behavior, for a well-formed program ([defns.well.formed]) construct and correct data, that depends on the implementation and that each implementation documents

3.28[defns.order.ptr]implementation-defined strict total order over pointers

⟨library⟩ implementation-defined strict total ordering over all pointer values such that the ordering is consistent with the partial order imposed by the built-in operators <, >, <=, >=, and <=>

3.29[defns.impl.limits]implementation limit

restriction imposed upon programs by the implementation

3.30[defns.locale.specific]locale-specific behavior

behavior that depends on local conventions of nationality, culture, and language that each implementation documents

3.31[defns.regex.matched]matched

⟨regular expression⟩ condition when a sequence of zero or more characters ([defns.character]) correspond to a sequence of characters defined by the pattern

3.32[defns.modifier]modifier function

⟨library⟩ class member function other than a constructor, assignment operator, or destructor that alters the state of an object of the class

3.33[defns.move.assign]move assignment

⟨library⟩ assignment of an rvalue of some object type to a modifiable lvalue of the same type

3.34[defns.move.constr]move construction

⟨library⟩ direct-initialization of an object of some type with an rvalue of the same type

3.35[defns.nonconst.libcall]non-constant library call

invocation of a library function that, as part of evaluating any expression E, prevents E from being a core constant expression

3.36[defns.ntcts]NTCTS

⟨library⟩ sequence of values that have character ([defns.character]) type that precede the terminating null character type value charT()

3.37[defns.observer]observer function

⟨library⟩ class member function that accesses the state of an object of the class but does not alter that state
[Note 1: 
Observer functions are specified as const member functions.
— end note]

3.38[defns.parameter]parameter

⟨function or catch clause⟩ object or reference declared as part of a function declaration or definition or in the catch clause of an exception handler that acquires a value on entry to the function or handler

3.39[defns.parameter.macro]parameter

⟨function-like macro⟩ identifier from the comma-separated list bounded by the parentheses immediately following the macro name

3.40[defns.parameter.templ]parameter

⟨template⟩ member of a template-parameter-list

3.41[defns.regex.primary.equivalence.class]primary equivalence class

⟨regular expression⟩ set of one or more characters ([defns.character]) which share the same primary sort key: that is the sort key weighting that depends only upon character shape, and not accents, case, or locale-specific tailorings

3.42[defns.prog.def.spec]program-defined specialization

⟨library⟩ explicit template specialization or partial specialization that is not part of the C++ standard library and not defined by the implementation

3.43[defns.prog.def.type]program-defined type

⟨library⟩ non-closure class type or enumeration type that is not part of the C++ standard library and not defined by the implementation, or a closure type of a non-implementation-provided lambda expression, or an instantiation of a program-defined specialization ([defns.prog.def.spec])
[Note 1: 
Types defined by the implementation include extensions ([intro.compliance]) and internal types used by the library.
— end note]

3.44[defns.projection]projection

⟨library⟩ transformation that an algorithm applies before inspecting the values of elements
[Example 1: 
std::pair<int, std::string_view> pairs[] = {{2, "foo"}, {1, "bar"}, {0, "baz"}}; std::ranges::sort(pairs, std::ranges::less{}, [](auto const& p) { return p.first; }); sorts the pairs in increasing order of their first members: {{0, "baz"}, {1, "bar"}, {2, "foo"}}
— end example]

3.45[defns.referenceable]referenceable type

type that is either an object type, a function type that does not have cv-qualifiers or a ref-qualifier, or a reference type
[Note 1: 
The term describes a type to which a reference can be created, including reference types.
— end note]

3.46[defns.regex.regular.expression]regular expression

pattern that selects specific strings from a set of character ([defns.character]) strings

3.47[defns.replacement]replacement function

⟨library⟩ non-reserved function whose definition is provided by a C++ program
[Note 1: 
Only one definition for such a function is in effect for the duration of the program's execution, as the result of creating the program ([lex.phases]) and resolving the definitions of all translation units ([basic.link]).
— end note]

3.48[defns.required.behavior]required behavior

⟨library⟩ description of replacement function ([defns.replacement]) and handler function ([defns.handler]) semantics applicable to both the behavior provided by the implementation and the behavior of any such function definition in the program
[Note 1: 
If such a function defined in a C++ program fails to meet the required behavior when it executes, the behavior is undefined.
— end note]

3.49[defns.reserved.function]reserved function

⟨library⟩ function, specified as part of the C++ standard library, that is defined by the implementation
[Note 1: 
If a C++ program provides a definition for any reserved function, the results are undefined.
— end note]

3.50[defns.undefined.runtime]runtime-undefined behavior

behavior that is undefined except when it occurs during constant evaluation
[Note 1: 
During constant evaluation,
  • it is implementation-defined whether runtime-undefined behavior results in the expression being deemed non-constant (as specified in [expr.const]) and
  • runtime-undefined behavior has no other effect.
— end note]

3.51[defns.signature]signature

⟨function⟩ name, parameter-type-list, and enclosing namespace
[Note 1: 
Signatures are used as a basis for name mangling and linking.
— end note]

3.52[defns.signature.friend]signature

⟨non-template friend function with trailing requires-clause⟩ name, parameter-type-list, enclosing class, and trailing requires-clause

3.53[defns.signature.templ]signature

⟨function template⟩ name, parameter-type-list, enclosing namespace, return type, signature ([defns.signature.template.head]) of the template-head, and trailing requires-clause (if any)

3.54[defns.signature.templ.friend]signature

⟨friend function template with constraint involving enclosing template parameters⟩ name, parameter-type-list, return type, enclosing class, signature ([defns.signature.template.head]) of the template-head, and trailing requires-clause (if any)

3.55[defns.signature.spec]signature

⟨function template specialization⟩ signature ([defns.signature.templ]) of the template of which it is a specialization and its template arguments ([defns.argument.templ]) (whether explicitly specified or deduced)

3.56[defns.signature.member]signature

⟨class member function⟩ name, parameter-type-list, class of which the function is a member, cv-qualifiers (if any), ref-qualifier (if any), and trailing requires-clause (if any)

3.57[defns.signature.member.templ]signature

⟨class member function template⟩ name, parameter-type-list, class of which the function is a member, cv-qualifiers (if any), ref-qualifier (if any), return type (if any), signature ([defns.signature.template.head]) of the template-head, and trailing requires-clause (if any)

3.58[defns.signature.member.spec]signature

⟨class member function template specialization⟩ signature ([defns.signature.member.templ]) of the member function template of which it is a specialization and its template arguments (whether explicitly specified or deduced)

3.59[defns.signature.template.head]signature

template-head⟩ template parameter ([defns.parameter.templ]) list, excluding template parameter names and default arguments ([defns.argument.templ]), and requires-clause (if any)

3.60[defns.stable]stable algorithm

⟨library⟩ algorithm that preserves, as appropriate to the particular algorithm, the order of elements
[Note 1: 
Requirements for stable algorithms are given in [algorithm.stable].
— end note]

3.61[defns.static.type]static type

type of an expression resulting from analysis of the program without considering execution semantics
[Note 1: 
The static type of an expression depends only on the form of the program in which the expression appears, and does not change while the program is executing.
— end note]

3.62[defns.regex.subexpression]sub-expression

⟨regular expression⟩ subset of a regular expression ([defns.regex.regular.expression]) that has been marked by parentheses

3.63[defns.traits]traits class

⟨library⟩ class that encapsulates a set of types and functions necessary for class templates and function templates to manipulate objects of types for which they are instantiated

3.64[defns.unblock]unblock

satisfy a condition that one or more blocked ([defns.block]) threads of execution are waiting for

3.65[defns.undefined]undefined behavior

behavior for which this document imposes no requirements
[Note 1: 
Undefined behavior may be expected when this document omits any explicit definition of behavior or when a program uses an incorrect construct or invalid data.
Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message ([defns.diagnostic])), to terminating a translation or execution (with the issuance of a diagnostic message).
Many incorrect program constructs do not engender undefined behavior; they are required to be diagnosed.
Evaluation of a constant expression ([expr.const]) never exhibits behavior explicitly specified as undefined in [intro] through [cpp].
— end note]

3.66[defns.unspecified]unspecified behavior

behavior, for a well-formed program ([defns.well.formed]) construct and correct data, that depends on the implementation
[Note 1: 
The implementation is not required to document which behavior occurs.
The range of possible behaviors is usually delineated by this document.
— end note]

3.67[defns.valid]valid but unspecified state

⟨library⟩ value of an object that is not specified except that the object's invariants are met and operations on the object behave as specified for its type
[Example 1: 
If an object x of type std​::​vector<int> is in a valid but unspecified state, x.empty() can be called unconditionally, and x.front() can be called only if x.empty() returns false.
— end example]

3.68[defns.well.formed]well-formed program

C++ program constructed according to the syntax and semantic rules

4 General principles [intro]

4.1 Implementation compliance [intro.compliance]

4.1.1 General [intro.compliance.general]

The set of diagnosable rules consists of all syntactic and semantic rules in this document except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior”.
Although this document states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs.
Such requirements have the following meaning:
  • If a program contains no violations of the rules in [lex] through [exec] as well as those specified in [depr], a conforming implementation shall accept and correctly execute3 that program, except when the implementation's limitations (see below) are exceeded.
  • If a program contains a violation of a rule for which no diagnostic is required, this document places no requirement on implementations with respect to that program.
  • Otherwise, if a program contains
    • a violation of any diagnosable rule,
    • a preprocessing translation unit with a #warning preprocessing directive ([cpp.error]), or
    • an occurrence of a construct described in this document as “conditionally-supported” when the implementation does not support that construct,
    a conforming implementation shall issue at least one diagnostic message.
[Note 1: 
During template argument deduction and substitution, certain constructs that in other contexts require a diagnostic are treated differently; see [temp.deduct].
— end note]
Furthermore, a conforming implementation shall not accept
For classes and class templates, the library Clauses specify partial definitions.
Private members are not specified, but each implementation shall supply them to complete the definitions according to the description in the library Clauses.
For functions, function templates, objects, and values, the library Clauses specify declarations.
Implementations shall supply definitions consistent with the descriptions in the library Clauses.
A C++ translation unit ([lex.phases]) obtains access to the names defined in the library by including the appropriate standard library header or importing the appropriate standard library named header unit ([using.headers]).
The templates, classes, functions, and objects in the library have external linkage.
The implementation provides definitions for standard library entities, as necessary, while combining translation units to form a complete C++ program ([lex.phases]).
Two kinds of implementations are defined: a hosted implementation and a freestanding implementation.
A freestanding implementation is one in which execution may take place without the benefit of an operating system.
A hosted implementation supports all the facilities described in this document, while a freestanding implementation supports the entire C++ language described in [lex] through [cpp] and the subset of the library facilities described in [compliance].
An implementation is encouraged to document its limitations in the size or complexity of the programs it can successfully process, if possible and where known.
[implimits] lists some quantities that can be subject to limitations and a potential minimum supported value for each quantity.
A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program.
Implementations are required to diagnose programs that use such extensions that are ill-formed according to this document.
Having done so, however, they can compile and execute such programs.
Each implementation shall include documentation that identifies all conditionally-supported constructs that it does not support and defines all locale-specific characteristics.4
3)3)
“Correct execution” can include undefined behavior and erroneous behavior, depending on the data being processed; see [intro.defs] and [intro.execution].
4)4)
This documentation also defines implementation-defined behavior; see [intro.abstract].

4.1.2 Abstract machine [intro.abstract]

The semantic descriptions in this document define a parameterized nondeterministic abstract machine.
This document places no requirement on the structure of conforming implementations.
In particular, they need not copy or emulate the structure of the abstract machine.
Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.5
Certain aspects and operations of the abstract machine are described in this document as implementation-defined behavior (for example, sizeof(int)).
These constitute the parameters of the abstract machine.
Each implementation shall include documentation describing its characteristics and behavior in these respects.6
Such documentation shall define the instance of the abstract machine that corresponds to that implementation (referred to as the “corresponding instance” below).
Certain other aspects and operations of the abstract machine are described in this document as unspecified behavior (for example, order of evaluation of arguments in a function call ([expr.call])).
Where possible, this document defines a set of allowable behaviors.
These define the nondeterministic aspects of the abstract machine.
An instance of the abstract machine can thus have more than one possible execution for a given program and a given input.
Certain other operations are described in this document as undefined behavior (for example, the effect of attempting to modify a const object).
[Note 1: 
This document imposes no requirements on the behavior of programs that contain undefined behavior.
— end note]
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input.
However, if any such execution contains an undefined operation, this document places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).
If the execution contains an operation specified as having erroneous behavior, the implementation is permitted to issue a diagnostic and is permitted to terminate the execution at an unspecified time after that operation.
Recommended practice: An implementation should issue a diagnostic when such an operation is executed.
[Note 2: 
An implementation can issue a diagnostic if it can determine that erroneous behavior is reachable under an implementation-specific set of assumptions about the program behavior, which can result in false positives.
— end note]
The least requirements on a conforming implementation are:
  • Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
  • At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced.
  • The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input.
    What constitutes an interactive device is implementation-defined.
These collectively are referred to as the observable behavior of the program.
[Note 3: 
More stringent correspondences between abstract and actual semantics can be defined by each implementation.
— end note]
5)5)
This provision is sometimes called the “as-if” rule, because an implementation is free to disregard any requirement of this document as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program.
For instance, an actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no side effects affecting the observable behavior of the program are produced.
6)6)
This documentation also includes conditionally-supported constructs and locale-specific behavior.

4.2 Structure of this document [intro.structure]

[lex] through [cpp] describe the C++ programming language.
That description includes detailed syntactic specifications in a form described in [syntax].
For convenience, [gram] repeats all such syntactic specifications.
[support] through [exec] and [depr] (the library clauses) describe the C++ standard library.
That description includes detailed descriptions of the entities and macros that constitute the library, in a form described in [library].
[implimits] recommends lower bounds on the capacity of conforming implementations.
[diff] summarizes the evolution of C++ since its first published description, and explains in detail the differences between C++ and C.
Certain features of C++ exist solely for compatibility purposes; [depr] describes those features.

4.3 Syntax notation [syntax]

In the syntax notation used in this document, syntactic categories are indicated by italic, sans-serif type, and literal words and characters in constant width type.
Alternatives are listed on separate lines except in a few cases where a long set of alternatives is marked by the phrase “one of”.
If the text of an alternative is too long to fit on a line, the text is continued on subsequent lines indented from the first one.
An optional terminal or non-terminal symbol is indicated by the subscript “”, so
{ expression }
indicates an optional expression enclosed in braces.
Names for syntactic categories have generally been chosen according to the following rules:
  • X-name is a use of an identifier in a context that determines its meaning (e.g., class-name, typedef-name).
  • X-id is an identifier with no context-dependent meaning (e.g., qualified-id).
  • X-seq is one or more X's without intervening delimiters (e.g., declaration-seq is a sequence of declarations).
  • X-list is one or more X's separated by intervening commas (e.g., identifier-list is a sequence of identifiers separated by commas).

5 Lexical conventions [lex]

5.1 Separate translation [lex.separate]

The text of the program is kept in units called source files in this document.
A source file together with all the headers and source files included via the preprocessing directive #include, less any source lines skipped by any of the conditional inclusion ([cpp.cond]) preprocessing directives, as modified by the implementation-defined behavior of any conditionally-supported-directives ([cpp.pre]) and pragmas ([cpp.pragma]), if any, is called a preprocessing translation unit.
[Note 1: 
A C++ program need not all be translated at the same time.
— end note]
[Note 2: 
Previously translated translation units and instantiation units can be preserved individually or in libraries.
The separate translation units of a program communicate ([basic.link]) by (for example) calls to functions whose identifiers have external or module linkage, manipulation of objects whose identifiers have external or module linkage, or manipulation of data files.
Translation units can be separately translated and then later linked to produce an executable program.
— end note]

5.2 Phases of translation [lex.phases]

The precedence among the syntax rules of translation is specified by the following phases.7
1.
An implementation shall support input files that are a sequence of UTF-8 code units (UTF-8 files).
It may also support an implementation-defined set of other kinds of input files, and, if so, the kind of an input file is determined in an implementation-defined manner that includes a means of designating input files as UTF-8 files, independent of their content.
[Note 1: 
In other words, recognizing the U+feff byte order mark is not sufficient.
— end note]
If an input file is determined to be a UTF-8 file, then it shall be a well-formed UTF-8 code unit sequence and it is decoded to produce a sequence of Unicode8 scalar values.
A sequence of translation character set elements ([lex.charset]) is then formed by mapping each Unicode scalar value to the corresponding translation character set element.
In the resulting sequence, each pair of characters in the input sequence consisting of U+000d carriage return followed by U+000a line feed, as well as each U+000d carriage return not immediately followed by a U+000a line feed, is replaced by a single new-line character.
For any other kind of input file supported by the implementation, characters are mapped, in an implementation-defined manner, to a sequence of translation character set elements, representing end-of-line indicators as new-line characters.
2.
If the first translation character is U+feff byte order mark, it is deleted.
Each sequence of a backslash character (\) immediately followed by zero or more whitespace characters other than new-line followed by a new-line character is deleted, splicing physical source lines to form logical source lines.
Only the last backslash on any physical source line shall be eligible for being part of such a splice.
[Note 2: 
Line splicing can form a universal-character-name ([lex.charset]).
— end note]
A source file that is not empty and that (after splicing) does not end in a new-line character shall be processed as if an additional new-line character were appended to the file.
3.
The source file is decomposed into preprocessing tokens ([lex.pptoken]) and sequences of whitespace characters (including comments).
A source file shall not end in a partial preprocessing token or in a partial comment.9
Each comment ([lex.comment]) is replaced by one space character.
New-line characters are retained.
Whether each nonempty sequence of whitespace characters other than new-line is retained or replaced by one space character is unspecified.
As characters from the source file are consumed to form the next preprocessing token (i.e., not being consumed as part of a comment or other forms of whitespace), except when matching a c-char-sequence, s-char-sequence, r-char-sequence, h-char-sequence, or q-char-sequence, universal-character-names are recognized ([lex.universal.char]) and replaced by the designated element of the translation character set ([lex.charset]).
The process of dividing a source file's characters into preprocessing tokens is context-dependent.
[Example 1: 
See the handling of < within a #include preprocessing directive ([cpp.include]).
— end example]
4.
The source file is analyzed as a preprocessing-file ([cpp.pre]).
Preprocessing directives ([cpp]) are executed, macro invocations are expanded ([cpp.replace]), and _Pragma unary operator expressions are executed ([cpp.pragma.op]).
A #include preprocessing directive ([cpp.include]) causes the named header or source file to be processed from phase 1 through phase 4, recursively.
All preprocessing directives are then deleted.
5.
For a sequence of two or more adjacent string-literal tokens, a common encoding-prefix is determined as specified in [lex.string].
Each such string-literal token is then considered to have that common encoding-prefix.
6.
Adjacent string-literal tokens are concatenated ([lex.string]).
7.
Each preprocessing token is converted into a token ([lex.token]).
Whitespace characters separating tokens are no longer significant.
The resulting tokens constitute a translation unit and are syntactically and semantically analyzed as a translation-unit ([basic.link]) and translated.
[Note 3: 
The process of analyzing and translating the tokens can occasionally result in one token being replaced by a sequence of other tokens ([temp.names]).
— end note]
It is implementation-defined whether the sources for module units and header units on which the current translation unit has an interface dependency ([module.unit], [module.import]) are required to be available.
[Note 4: 
Source files, translation units and translated translation units need not necessarily be stored as files, nor need there be any one-to-one correspondence between these entities and any external representation.
The description is conceptual only, and does not specify any particular implementation.
— end note]
8.
Translated translation units and instantiation units are combined as follows:
[Note 5: 
Some or all of these can be supplied from a library.
— end note]
Each translated translation unit is examined to produce a list of required instantiations.
[Note 6: 
This can include instantiations which have been explicitly requested ([temp.explicit]).
— end note]
The definitions of the required templates are located.
It is implementation-defined whether the source of the translation units containing these definitions is required to be available.
[Note 7: 
An implementation can choose to encode sufficient information into the translated translation unit so as to ensure the source is not required here.
— end note]
All the required instantiations are performed to produce instantiation units.
[Note 8: 
These are similar to translated translation units, but contain no references to uninstantiated templates and no template definitions.
— end note]
The program is ill-formed if any instantiation fails.
9.
All external entity references are resolved.
Library components are linked to satisfy external references to entities not defined in the current translation.
All such translator output is collected into a program image which contains information needed for execution in its execution environment.
7)7)
Implementations behave as if these separate phases occur, although in practice different phases can be folded together.
8)8)
Unicode® is a registered trademark of Unicode, Inc.
This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of this product.
9)9)
A partial preprocessing token would arise from a source file ending in the first portion of a multi-character token that requires a terminating sequence of characters, such as a header-name that is missing the closing " or >.
A partial comment would arise from a source file ending with an unclosed /* comment.

5.3 Characters [lex.char]

5.3.1 Character sets [lex.charset]

The translation character set consists of the following elements:
  • each abstract character assigned a code point in the Unicode codespace as specified in the Unicode Standard, and
  • a distinct character for each Unicode scalar value not assigned to an abstract character.
[Note 1: 
Unicode code points are integers in the range [0, 10FFFF] (hexadecimal).
A surrogate code point is a value in the range [D800, DFFF] (hexadecimal).
A Unicode scalar value is any code point that is not a surrogate code point.
— end note]
The basic character set is a subset of the translation character set, consisting of 99 characters as specified in Table 1.
[Note 2: 
Unicode short names are given only as a means to identifying the character; the numerical value has no other meaning in this context.
— end note]
Table 1 — Basic character set [tab:lex.charset.basic]
character
glyph
U+0009
character tabulation
U+000b
line tabulation
U+000c
form feed
U+0020
space
U+000a
line feed
new-line
U+0021
exclamation mark
!
U+0022
quotation mark
"
U+0023
number sign
#
U+0024
dollar sign
$
U+0025
percent sign
%
U+0026
ampersand
&
U+0027
apostrophe
'
U+0028
left parenthesis
(
U+0029
right parenthesis
)
U+002a
asterisk
*
U+002b
plus sign
+
U+002c
comma
,
U+002d
hyphen-minus
-
U+002e
full stop
.
U+002f
solidus
/
U+0030 ..
U+0039
digit zero .. nine
0 1 2 3 4 5 6 7 8 9
U+003a
colon
:
U+003b
semicolon
;
U+003c
less-than sign
<
U+003d
equals sign
=
U+003e
greater-than sign
>
U+003f
question mark
?
U+0040
commercial at
@
U+0041 ..
U+005a
latin capital letter a .. z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
U+005b
left square bracket
[
U+005c
reverse solidus
\
U+005d
right square bracket
]
U+005e
circumflex accent
^
U+005f
low line
_
U+0060
grave accent
`
U+0061 ..
U+007a
latin small letter a .. z
a b c d e f g h i j k l m
n o p q r s t u v w x y z
U+007b
left curly bracket
{
U+007c
vertical line
|
U+007d
right curly bracket
}
U+007e
tilde
~
The basic literal character set consists of all characters of the basic character set, plus the control characters specified in Table 2.
Table 2 — Additional control characters in the basic literal character set [tab:lex.charset.literal]
character
U+0000
null
U+0007
alert
U+0008
backspace
U+000d
carriage return
A code unit is an integer value of character type ([basic.fundamental]).
Characters in a character-literal other than a multicharacter or non-encodable character literal or in a string-literal are encoded as a sequence of one or more code units, as determined by the encoding-prefix ([lex.ccon], [lex.string]); this is termed the respective literal encoding.
The ordinary literal encoding is the encoding applied to an ordinary character or string literal.
The wide literal encoding is the encoding applied to a wide character or string literal.
A literal encoding or a locale-specific encoding of one of the execution character sets ([character.seq]) encodes each element of the basic literal character set as a single code unit with non-negative value, distinct from the code unit for any other such element.
[Note 3: 
A character not in the basic literal character set can be encoded with more than one code unit; 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 0.
No other element of the translation character set is encoded with a code unit of value 0.
The code unit value of each decimal digit character after the digit 0 (U+0030) shall be one greater than the value of the previous.
The ordinary and wide literal encodings are otherwise implementation-defined.
For a UTF-8, UTF-16, or UTF-32 literal, the implementation shall encode the Unicode scalar value corresponding to each character of the translation character set as specified in the Unicode Standard for the respective Unicode encoding form.

5.3.2 Universal character names [lex.universal.char]

n-char:
any member of the translation character set except the U+007d right curly bracket or new-line character
The universal-character-name construct provides a way to name any element in the translation character set using just the basic character set.
If a universal-character-name outside the c-char-sequence, s-char-sequence, or r-char-sequence of a character-literal or string-literal (in either case, including within a user-defined-literal) corresponds to a control character or to a character in the basic character set, the program is ill-formed.
[Note 1: 
A sequence of characters resembling a universal-character-name in an r-char-sequence ([lex.string]) does not form a universal-character-name.
— end note]
A universal-character-name of the form \u hex-quad, \U hex-quad hex-quad, or \u{simple-hexadecimal-digit-sequence} designates the character in the translation character set whose Unicode scalar value is the hexadecimal number represented by the sequence of hexadecimal-digits in the universal-character-name.
The program is ill-formed if that number is not a Unicode scalar value.
A universal-character-name that is a named-universal-character designates the corresponding character in the Unicode Standard (chapter 4.8 Name) if the n-char-sequence is equal to its character name or to one of its character name aliases of type “control”, “correction”, or “alternate”; otherwise, the program is ill-formed.
[Note 2: 
These aliases are listed in the Unicode Character Database's NameAliases.txt.
None of these names or aliases have leading or trailing spaces.
— end note]

5.4 Comments [lex.comment]

The characters /* start a comment, which terminates with the characters */.
These comments do not nest.
The characters // start a comment, which terminates immediately before the next new-line character.
If there is a form-feed or a vertical-tab character in such a comment, only whitespace characters shall appear between it and the new-line that terminates the comment; no diagnostic is required.
[Note 1: 
The comment characters //, /*, and */ have no special meaning within a // comment and are treated just like other characters.
Similarly, the comment characters // and /* have no special meaning within a /* comment.
— end note]

5.5 Preprocessing tokens [lex.pptoken]

A preprocessing token is the minimal lexical element of the language in translation phases 3 through 6.
In this document, glyphs are used to identify elements of the basic character set ([lex.charset]).
The categories of preprocessing token are: header names, placeholder tokens produced by preprocessing import and module directives (import-keyword, module-keyword, and export-keyword), identifiers, preprocessing numbers, character literals (including user-defined character 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 matches the last category, the program is ill-formed.
If any character not in the basic character set matches the last category, the program is ill-formed.
Preprocessing tokens can be separated by whitespace; this consists of comments ([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 [cpp], in certain circumstances during translation phase 4, whitespace (or the absence thereof) serves as more than preprocessing token separation.
Whitespace can appear within a preprocessing token only as part of a header name or between the quotation characters in a character literal or string literal.
Each preprocessing token that is converted to a token ([lex.token]) shall have the lexical form of a keyword, an identifier, a literal, or an operator or punctuator.
The import-keyword is produced by processing an import directive ([cpp.import]), the module-keyword is produced by preprocessing a module directive ([cpp.module]), and the export-keyword is produced by preprocessing either of the previous two directives.
[Note 1: 
None has any observable spelling.
— end note]
If the input stream has been parsed into preprocessing tokens up to a given character:
  • If the next character begins a sequence of characters that could be the prefix and initial double quote of a raw string literal, such as R", the next preprocessing token shall be a raw string literal.
    Between the initial and final double quote characters of the raw string, any transformations performed in phase 2 (line splicing) are reverted; this reversion shall apply before any d-char, r-char, or delimiting parenthesis is identified.
    The raw string literal is defined as the shortest sequence of characters that matches the raw-string pattern
  • Otherwise, if the next three characters are <​::​ and the subsequent character is neither : nor >, the < is treated as a preprocessing token by itself and not as the first character of the alternative token <:.
  • Otherwise, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail, except that a header-name ([lex.header]) is only formed
[Example 1: #define R "x" const char* s = R"y"; // ill-formed raw string, not "x" "y" — end example]
[Example 2: 
The program fragment 0xe+foo is parsed as a preprocessing number token (one that is not a valid integer-literal or floating-point-literal token), even though a parse as three preprocessing tokens 0xe, +, and foo can produce a valid expression (for example, if foo is a macro defined as 1).
Similarly, the program fragment 1E1 is parsed as a preprocessing number (one that is a valid floating-point-literal token), whether or not E is a macro name.
— end example]
[Example 3: 
The program fragment x+++++y is parsed as x ++ ++ + y, which, if x and y have integral types, violates a constraint on increment operators, even though the parse x ++ + ++ y can yield a correct expression.
— end example]

5.6 Header names [lex.header]

h-char:
any member of the translation character set except new-line and U+003e greater-than sign
q-char:
any member of the translation character set except new-line and U+0022 quotation mark
The sequences in both forms of header-names are mapped in an implementation-defined manner to headers or to external source file names as specified in [cpp.include].
[Note 1: 
Header name preprocessing tokens appear only within a #include preprocessing directive, a __has_include preprocessing expression, or after certain occurrences of an import token (see [lex.pptoken]).
— end note]
The appearance of either of the characters ' or \ or of either of the character sequences /* or // in a q-char-sequence or an h-char-sequence is conditionally-supported with implementation-defined semantics, as is the appearance of the character " in an h-char-sequence.
[Note 2: 
Thus, a sequence of characters that resembles an escape sequence can result in an error, be interpreted as the character corresponding to the escape sequence, or have a completely different meaning, depending on the implementation.
— end note]

5.7 Preprocessing numbers [lex.ppnumber]

Preprocessing number tokens lexically include all integer-literal tokens ([lex.icon]) and all floating-point-literal tokens ([lex.fcon]).
A preprocessing number does not have a type or a value; it acquires both after a successful conversion to an integer-literal token or a floating-point-literal token.

5.8 Operators and punctuators [lex.operators]

The lexical representation of C++ programs includes a number of preprocessing tokens that are used in the syntax of the preprocessor or are converted into tokens for operators and punctuators:
preprocessing-operator: one of
# ## %: %:%:
operator-or-punctuator: one of
{ } [ ] ( )
<: :> <% %> ; : ...
? :: . .* -> ->* ~
! + - * / % ^ & |
= += -= *= /= %= ^= &= |=
== != < > <= >= <=> && ||
<< >> <<= >>= ++ -- ,
and or xor not bitand bitor compl
and_eq or_eq xor_eq not_eq
Each operator-or-punctuator is converted to a single token in translation phase 7 ([lex.phases]).

5.9 Alternative tokens [lex.digraph]

Alternative token representations are provided for some operators and punctuators.10
In all respects of the language, each alternative token behaves the same, respectively, as its primary token, except for its spelling.11
The set of alternative tokens is defined in Table 3.
Table 3 — Alternative tokens [tab:lex.digraph]
Alternative
Primary
Alternative
Primary
Alternative
Primary
<%
{
and
&&
and_eq
&=
%>
}
bitor
|
or_eq
|=
<:
[
or
||
xor_eq
^=
:>
]
xor
^
not
!
%:
#
compl
~
not_eq
!=
%:%:
##
bitand
&
10)10)
These include “digraphs” and additional reserved words.
The term “digraph” (token consisting of two characters) is not perfectly descriptive, since one of the alternative preprocessing-tokens is %:%: and of course several primary tokens contain two characters.
Nonetheless, those alternative tokens that aren't lexical keywords are colloquially known as “digraphs”.
11)11)
Thus the “stringized” values ([cpp.stringize]) of [ and <: will be different, maintaining the source spelling, but the tokens can otherwise be freely interchanged.

5.10 Tokens [lex.token]

There are five kinds of tokens: identifiers, keywords, literals,12 operators, and other separators.
Blanks, horizontal and vertical tabs, newlines, formfeeds, and comments (collectively, “whitespace”), as described below, are ignored except as they serve to separate tokens.
[Note 1: 
Whitespace can separate otherwise adjacent identifiers, keywords, numeric literals, and alternative tokens containing alphabetic characters.
— end note]
12)12)
Literals include strings and character and numeric literals.

5.11 Identifiers [lex.name]

identifier-start:
nondigit
an element of the translation character set with the Unicode property XID_Start
identifier-continue:
digit
nondigit
an element of the translation character set with the Unicode property XID_Continue
nondigit: one of
a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z _
digit: one of
0 1 2 3 4 5 6 7 8 9
[Note 1: 
The character properties XID_Start and XID_Continue are described by UAX #44 of the Unicode Standard.13
— end note]
The program is ill-formed if an identifier does not conform to Normalization Form C as specified in the Unicode Standard.
[Note 2: 
Identifiers are case-sensitive.
— end note]
[Note 3: 
[uaxid] compares the requirements of UAX #31 of the Unicode Standard with the C++ rules for identifiers.
— end note]
[Note 4: 
In translation phase 4, identifier also includes those preprocessing-tokens ([lex.pptoken]) differentiated as keywords ([lex.key]) in the later translation phase 7 ([lex.token]).
— end note]
The identifiers in Table 4 have a special meaning when appearing in a certain context.
When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production.
Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier.
Table 4 — Identifiers with special meaning [tab:lex.name.special]
final
import
module
override
In addition, some identifiers appearing as a token or preprocessing-token are reserved for use by C++ implementations and shall not be used otherwise; no diagnostic is required.
  • Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter, other than those specified in this document (for example, __cplusplus ([cpp.predefined])), is reserved to the implementation for any use.
  • Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
13)13)
On systems in which linkers cannot accept extended characters, an encoding of the universal-character-name can be used in forming valid external identifiers.
For example, some otherwise unused character or sequence of characters can be used to encode the \u in a universal-character-name.
Extended characters can produce a long external identifier, but C++ does not place a translation limit on significant characters for external identifiers.

5.12 Keywords [lex.key]

keyword:
any identifier listed in Table 5
import-keyword
module-keyword
export-keyword
The identifiers shown in Table 5 are reserved for use as keywords (that is, they are unconditionally treated as keywords in phase 7) except in an attribute-token ([dcl.attr.grammar]).
[Note 1: 
The register keyword is unused but is reserved for future use.
— end note]
Table 5 — Keywords [tab:lex.key]
alignas
constinit
false
public
true
alignof
const_cast
float
register
try
asm
continue
for
reinterpret_cast
typedef
auto
co_await
friend
requires
typeid
bool
co_return
goto
return
typename
break
co_yield
if
short
union
case
decltype
inline
signed
unsigned
catch
default
int
sizeof
using
char
delete
long
static
virtual
char8_t
do
mutable
static_assert
void
char16_t
double
namespace
static_cast
volatile
char32_t
dynamic_cast
new
struct
wchar_t
class
else
noexcept
switch
while
concept
enum
nullptr
template
const
explicit
operator
this
consteval
export
private
thread_local
constexpr
extern
protected
throw
Furthermore, the alternative representations shown in Table 6 for certain operators and punctuators ([lex.digraph]) are reserved and shall not be used otherwise.
Table 6 — Alternative representations [tab:lex.key.digraph]
and
and_eq
bitand
bitor
compl
not
not_eq
or
or_eq
xor
xor_eq

5.13 Literals [lex.literal]

5.13.1 Kinds of literals [lex.literal.kinds]

There are several kinds of literals.14
14)14)
The term “literal” generally designates, in this document, those tokens that are called “constants” in C.

5.13.2 Integer literals [lex.icon]

binary-digit: one of
0 1
octal-digit: one of
0 1 2 3 4 5 6 7
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
hexadecimal-prefix: one of
0x 0X
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
unsigned-suffix: one of
u U
long-suffix: one of
l L
long-long-suffix: one of
ll LL
size-suffix: one of
z Z
In an integer-literal, the sequence of binary-digits, octal-digits, digits, or hexadecimal-digits is interpreted as a base N integer as shown in table Table 7; the lexically first digit of the sequence of digits is the most significant.
[Note 1: 
The prefix and any optional separating single quotes are ignored when determining the value.
— end note]
The hexadecimal-digits a through f and A through F have decimal values ten through fifteen.
[Example 1: 
The number twelve can be written 12, 014, 0XC, or 0b1100.
The integer-literals 1048576, 1'048'576, 0X100000, 0x10'0000, and 0'004'000'000 all have the same value.
— end example]
The type of an integer-literal is the first type in the list in Table 8 corresponding to its optional integer-suffix in which its value can be represented.
Table 8 — Types of integer-literals[tab:lex.icon.type]
none
int
int
long int
unsigned int
long long int
long int
unsigned long int
long long int
unsigned long long int
u or U
unsigned int
unsigned int
unsigned long int
unsigned long int
unsigned long long int
unsigned long long int
l or L
long int
long int
long long int
unsigned long int
long long int
unsigned long long int
Both u or U
unsigned long int
unsigned long int
and l or L
unsigned long long int
unsigned long long int
ll or LL
long long int
long long int
unsigned long long int
Both u or U
unsigned long long int
unsigned long long int
and ll or LL
z or Z
the signed integer type corresponding
the signed integer type
  to std​::​size_t ([support.types.layout])
  corresponding to std​::​size_t
std​::​size_t
Both u or U
std​::​size_t
std​::​size_t
and z or Z
Except for integer-literals containing a size-suffix, if the value of an integer-literal cannot be represented by any type in its list and an extended integer type ([basic.fundamental]) can represent its value, it may have that extended integer type.
If all of the types in the list for the integer-literal are signed, the extended integer type is signed.
If all of the types in the list for the integer-literal are unsigned, the extended integer type is unsigned.
If the list contains both signed and unsigned types, the extended integer type may be signed or unsigned.
If an integer-literal cannot be represented by any of the allowed types, the program is ill-formed.
[Note 2: 
An integer-literal with a z or Z suffix is ill-formed if it cannot be represented by std​::​size_t.
— end note]

5.13.3 Character literals [lex.ccon]

encoding-prefix: one of
u8  u  U  L
basic-c-char:
any member of the translation character set except the U+0027 apostrophe,
   U+005c reverse solidus, or new-line character
simple-escape-sequence-char: one of
' " ? \ a b f n r t v
conditional-escape-sequence-char:
any member of the basic character set that is not an octal-digit, a simple-escape-sequence-char, or the characters N, o, u, U, or x
A multicharacter literal is a character-literal whose c-char-sequence consists of more than one c-char.
A multicharacter literal shall not have an encoding-prefix.
If a multicharacter literal contains a c-char that is not encodable as a single code unit in the ordinary literal encoding, the program is ill-formed.
Multicharacter literals are conditionally-supported.
The kind of a character-literal, its type, and its associated character encoding ([lex.charset]) are determined by its encoding-prefix and its c-char-sequence as defined by Table 9.
Table 9 — Character literals [tab:lex.ccon.literal]
Encoding
Kind
Type
Associated char-
Example
prefix
acter encoding
none
char
ordinary literal
'v'
multicharacter literal
int
encoding
'abcd'
L
wchar_t
wide literal
L'w'
encoding
u8
char8_t
UTF-8
u8'x'
u
char16_t
UTF-16
u'y'
U
char32_t
UTF-32
U'z'
In translation phase 4, the value of a character-literal is determined using the range of representable values of the character-literal's type in translation phase 7.
A multicharacter literal has an implementation-defined value.
The value of any other kind of character-literal is determined as follows:
The character specified by a simple-escape-sequence is specified in Table 10.
[Note 1: 
Using an escape sequence for a question mark is supported for compatibility with C++ 2014 and C.
— end note]
Table 10 — Simple escape sequences [tab:lex.ccon.esc]
character
U+000a
line feed
\n
U+0009
character tabulation
\t
U+000b
line tabulation
\v
U+0008
backspace
\b
U+000d
carriage return
\r
U+000c
form feed
\f
U+0007
alert
\a
U+005c
reverse solidus
\\
U+003f
question mark
\?
U+0027
apostrophe
\'
U+0022
quotation mark
\"

5.13.4 Floating-point literals [lex.fcon]

sign: one of
+ -
floating-point-suffix: one of
f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16
The type of a floating-point-literal ([basic.fundamental], [basic.extended.fp]) is determined by its floating-point-suffix as specified in Table 11.
[Note 1: 
The floating-point suffixes f16, f32, f64, f128, bf16, F16, F32, F64, F128, and BF16 are conditionally-supported.
— end note]
Table 11 — Types of floating-point-literals[tab:lex.fcon.type]
type
none
double
f or F
float
l or L
long double
f16 or F16
std::float16_t
f32 or F32
std::float32_t
f64 or F64
std::float64_t
f128 or F128
std::float128_t
bf16 or BF16
std::bfloat16_t
In the significand, the sequence of digits or hexadecimal-digits and optional period are interpreted as a base N real number s, where N is 10 for a decimal-floating-point-literal and 16 for a hexadecimal-floating-point-literal.
[Note 2: 
Any optional separating single quotes are ignored when determining the value.
— end note]
If an exponent-part or binary-exponent-part is present, the exponent e of the floating-point-literal is the result of interpreting the sequence of an optional sign and the digits as a base 10 integer.
Otherwise, the exponent e is 0.
The scaled value of the literal is for a decimal-floating-point-literal and for a hexadecimal-floating-point-literal.
[Example 1: 
The floating-point-literals 49.625 and 0xC.68p+2 have the same value.
The floating-point-literals 1.602'176'565e-19 and 1.602176565e-19 have the same value.
— end example]
If the scaled value is not in the range of representable values for its type, the program is ill-formed.
Otherwise, the value of a floating-point-literal is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner.

5.13.5 String literals [lex.string]

basic-s-char:
any member of the translation character set except the U+0022 quotation mark,
   U+005c reverse solidus, or new-line character
r-char:
any member of the translation character set, except a U+0029 right parenthesis followed by
   the initial d-char-sequence (which may be empty) followed by a U+0022 quotation mark
d-char-sequence:
d-chard-char-sequence
d-char:
any member of the basic character set except:
   U+0020 space, U+0028 left parenthesis, U+0029 right parenthesis, U+005c reverse solidus,
   U+0009 character tabulation, U+000b line tabulation, U+000c form feed, and new-line
The kind of a string-literal, its type, and its associated character encoding ([lex.charset]) are determined by its encoding prefix and sequence of s-chars or r-chars as defined by Table 12 where n is the number of encoded code units as described below.
Table 12 — String literals [tab:lex.string.literal]
Enco-
Kind
Type
Associated
Examples
ding
character
prefix
encoding
none
array of n
const char
ordinary literal encoding
"ordinary string"
R"(ordinary raw string)"
L
array of n
const wchar_t
wide literal
encoding
L"wide string"
LR"w(wide raw string)w"
u8
array of n
const char8_t
UTF-8
u8"UTF-8 string"
u8R"x(UTF-8 raw string)x"
u
array of n
const char16_t
UTF-16
u"UTF-16 string"
uR"y(UTF-16 raw string)y"
U
array of n
const char32_t
UTF-32
U"UTF-32 string"
UR"z(UTF-32 raw string)z"
A string-literal that has an R in the prefix is a raw string literal.
The d-char-sequence serves as a delimiter.
The terminating d-char-sequence of a raw-string is the same sequence of characters as the initial d-char-sequence.
A d-char-sequence shall consist of at most 16 characters.
[Note 1: 
The characters '(' and ')' can appear in a raw-string.
Thus, R"delimiter((a|b))delimiter" is equivalent to "(a|b)".
— end note]
[Note 2: 
A source-file new-line in a raw string literal results in a new-line in the resulting execution string literal.
Assuming no whitespace at the beginning of lines in the following example, the assert will succeed: const char* p = R"(a\ b c)"; assert(std::strcmp(p, "a\\\nb\nc") == 0);
— end note]
[Example 1: 
The raw string R"a( )\ a" )a" is equivalent to "\n)\\\na\"\n".
The raw string R"(x = "\"y\"")" is equivalent to "x = \"\\\"y\\\"\"".
— end example]
Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals.
The string-literals in any sequence of adjacent string-literals shall have at most one unique encoding-prefix among them.
The common encoding-prefix of the sequence is that encoding-prefix, if any.
[Note 3: 
A string-literal's rawness has no effect on the determination of the common encoding-prefix.
— end note]
In translation phase 6 ([lex.phases]), adjacent string-literals are concatenated.
The lexical structure and grouping of the contents of the individual string-literals is retained.
[Example 2: 
"\xA" "B" represents the code unit '\xA' and the character 'B' after concatenation (and not the single code unit '\xAB').
Similarly, R"(\u00)" "41" represents six characters, starting with a backslash and ending with the digit 1 (and not the single character 'A' specified by a universal-character-name).
Table 13 has some examples of valid concatenations.
— end example]
Table 13 — String literal concatenations [tab:lex.string.concat]
Source
Means
Source
Means
Source
Means
u"a"
u"b"
u"ab"
U"a"
U"b"
U"ab"
L"a"
L"b"
L"ab"
u"a"
"b"
u"ab"
U"a"
"b"
U"ab"
L"a"
"b"
L"ab"
"a"
u"b"
u"ab"
"a"
U"b"
U"ab"
"a"
L"b"
L"ab"
Evaluating a string-literal results in a string literal object with static storage duration ([basic.stc]).
[Note 4: 
String literal objects are potentially non-unique ([intro.object]).
Whether successive evaluations of a string-literal yield the same or a different object is unspecified.
— end note]
[Note 5: 
The effect of attempting to modify a string literal object is undefined.
— end note]
String literal objects are initialized with the sequence of code unit values corresponding to the string-literal's sequence of s-chars (originally from non-raw string literals) and r-chars (originally from raw string literals), plus a terminating U+0000 null character, in order as follows:
  • The sequence of characters denoted by each contiguous sequence of basic-s-chars, r-chars, simple-escape-sequences ([lex.ccon]), and universal-character-names ([lex.charset]) is encoded to a code unit sequence using the string-literal's associated character encoding.
    If a character lacks representation in the associated character encoding, then the program is ill-formed.
    [Note 6: 
    No character lacks representation in any Unicode encoding form.
    — end note]
    When encoding a stateful character encoding, implementations should encode the first such sequence beginning with the initial encoding state and encode subsequent sequences beginning with the final encoding state of the prior sequence.
    [Note 7: 
    The encoded code unit sequence can differ from the sequence of code units that would be obtained by encoding each character independently.
    — end note]
  • Each numeric-escape-sequence ([lex.ccon]) contributes a single code unit with a value as follows:
    When encoding a stateful character encoding, these sequences should have no effect on encoding state.
  • Each conditional-escape-sequence ([lex.ccon]) contributes an implementation-defined code unit sequence.
    When encoding a stateful character encoding, it is implementation-defined what effect these sequences have on encoding state.

5.13.6 Unevaluated strings [lex.string.uneval]

Each universal-character-name and each simple-escape-sequence in an unevaluated-string is replaced by the member of the translation character set it denotes.
An unevaluated-string is never evaluated and its interpretation depends on the context in which it appears.

5.13.7 Boolean literals [lex.bool]

boolean-literal:
false
true
The Boolean literals are the keywords false and true.
Such literals have type bool.

5.13.8 Pointer literals [lex.nullptr]

The pointer literal is the keyword nullptr.
It has type std​::​nullptr_t.
[Note 1: 
std​::​nullptr_t is a distinct type that is neither a pointer type nor a pointer-to-member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value.
— end note]

5.13.9 User-defined literals [lex.ext]

If a token matches both user-defined-literal and another literal kind, it is treated as the latter.
[Example 1: 
123_km is a user-defined-literal, but 12LL is an integer-literal.
— end example]
The syntactic non-terminal preceding the ud-suffix in a user-defined-literal is taken to be the longest sequence of characters that could match that non-terminal.
A user-defined-literal is treated as a call to a literal operator or literal operator template ([over.literal]).
To determine the form of this call for a given user-defined-literal L with ud-suffix X, first let S be the set of declarations found by unqualified lookup for the literal-operator-id whose literal suffix identifier is X ([basic.lookup.unqual]).
S shall not be empty.
If L is a user-defined-integer-literal, let n be the literal without its ud-suffix.
If S contains a literal operator with parameter type unsigned long long, the literal L is treated as a call of the form operator ""X(nULL)
Otherwise, S shall contain a raw literal operator or a numeric literal operator template ([over.literal]) but not both.
If S contains a raw literal operator, the literal L is treated as a call of the form operator ""X("n")
Otherwise (S contains a numeric literal operator template), L is treated as a call of the form operator ""X<'', '', ... ''>() where n is the source character sequence .
[Note 1: 
The sequence can only contain characters from the basic character set.
— end note]
If L is a user-defined-floating-point-literal, let f be the literal without its ud-suffix.
If S contains a literal operator with parameter type long double, the literal L is treated as a call of the form operator ""X(fL)
Otherwise, S shall contain a raw literal operator or a numeric literal operator template ([over.literal]) but not both.
If S contains a raw literal operator, the literal L is treated as a call of the form operator ""X("f")
Otherwise (S contains a numeric literal operator template), L is treated as a call of the form operator ""X<'', '', ... ''>() where f is the source character sequence .
[Note 2: 
The sequence can only contain characters from the basic character set.
— end note]
If L is a user-defined-string-literal, let str be the literal without its ud-suffix and let len be the number of code units in str (i.e., its length excluding the terminating null character).
If S contains a literal operator template with a non-type template parameter for which str is a well-formed template-argument, the literal L is treated as a call of the form operator ""X<str>()
Otherwise, the literal L is treated as a call of the form operator ""X(str, len)
If L is a user-defined-character-literal, let ch be the literal without its ud-suffix.
S shall contain a literal operator whose only parameter has the type of ch and the literal L is treated as a call of the form operator ""X(ch)
[Example 2: long double operator ""_w(long double); std::string operator ""_w(const char16_t*, std::size_t); unsigned operator ""_w(const char*); int main() { 1.2_w; // calls operator ""_w(1.2L) u"one"_w; // calls operator ""_w(u"one", 3) 12_w; // calls operator ""_w("12") "two"_w; // error: no applicable literal operator } — end example]
In translation phase 6 ([lex.phases]), adjacent string-literals are concatenated and user-defined-string-literals are considered string-literals for that purpose.
During concatenation, ud-suffixes are removed and ignored and the concatenation process occurs as described in [lex.string].
At the end of phase 6, if a string-literal is the result of a concatenation involving at least one user-defined-string-literal, all the participating user-defined-string-literals shall have the same ud-suffix and that suffix is applied to the result of the concatenation.
[Example 3: int main() { L"A" "B" "C"_x; // OK, same as L"ABC"_x "P"_x "Q" "R"_y; // error: two different ud-suffixes } — end example]

6 Basics [basic]

6.1 Preamble [basic.pre]

[Note 1: 
This Clause presents the basic concepts of the C++ language.
It explains the difference between an object and a name and how they relate to the value categories for expressions.
It introduces the concepts of a declaration and a definition and presents C++'s notion of type, scope, linkage, and storage duration.
The mechanisms for starting and terminating a program are discussed.
Finally, this Clause presents the fundamental types of the language and lists the ways of constructing compound types from these.
— end note]
[Note 2: 
This Clause does not cover concepts that affect only a single part of the language.
Such concepts are discussed in the relevant Clauses.
— end note]
An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
[Note 3: 
The interpretation of a for-range-declaration produces one or more of the above ([stmt.ranged]).
— end note]
An entity E is denoted by the name (if any) that is introduced by a declaration of E or by a typedef-name introduced by a declaration specifying E.
A variable is introduced by the declaration of a reference other than a non-static data member or of an object.
The variable's name, if any, denotes the reference or object.
A local entity is a variable with automatic storage duration, a structured binding whose corresponding variable is such an entity, or the *this object ([expr.prim.this]).
[Note 4: 
Some names denote types or templates.
In general, whenever a name is encountered it is necessary to look it up ([basic.lookup]) to determine whether that name denotes one of these entities before continuing to parse the program that contains it.
— end note]
Two names are the same if
A name used in more than one translation unit can potentially refer to the same entity in these translation units depending on the linkage of the name specified in each translation unit.

6.2 Declarations and definitions [basic.def]

A declaration may (re)introduce one or more names and/or entities into a translation unit.
If so, the declaration specifies the interpretation and semantic properties of these names.
A declaration of an entity or typedef-name X is a redeclaration of X if another declaration of X is reachable from it ([module.reach]).
A declaration may also have effects including:
Each entity declared by a declaration is also defined by that declaration unless:
A declaration is said to be a definition of each entity that it defines.
[Example 1: 
All but one of the following are definitions: int a; // defines a extern const int c = 1; // defines c int f(int x) { return x+a; } // defines f and defines x struct S { int a; int b; }; // defines S, S​::​a, and S​::​b struct X { // defines X int x; // defines non-static data member x static int y; // declares static data member y X(): x(0) { } // defines a constructor of X }; int X::y = 1; // defines X​::​y enum { up, down }; // defines up and down namespace N { int d; } // defines N and N​::​d namespace N1 = N; // defines N1 X anX; // defines anX whereas these are just declarations: extern int a; // declares a extern const int c; // declares c int f(int); // declares f struct S; // declares S typedef int Int; // declares Int extern X anotherX; // declares anotherX using N::d; // declares d
— end example]
[Note 1: 
In some circumstances, C++ implementations implicitly define the default constructor ([class.default.ctor]), copy constructor, move constructor ([class.copy.ctor]), copy assignment operator, move assignment operator ([class.copy.assign]), or destructor member functions.
— end note]
[Example 2: 
Given #include <string> struct C { std::string s; // std​::​string is the standard library class ([string.classes]) }; int main() { C a; C b = a; b = a; } the implementation will implicitly define functions to make the definition of C equivalent to struct C { std::string s; C() : s() { } C(const C& x): s(x.s) { } C(C&& x): s(static_cast<std::string&&>(x.s)) { } // : s(std​::​move(x.s)) { } C& operator=(const C& x) { s = x.s; return *this; } C& operator=(C&& x) { s = static_cast<std::string&&>(x.s); return *this; } // { s = std​::​move(x.s); return *this; } ~C() { } };
— end example]
[Note 2: 
A class name can also be implicitly declared by an elaborated-type-specifier ([dcl.type.elab]).
— end note]
In the definition of an object, the type of that object shall not be an incomplete type ([basic.types.general]), an abstract class type ([class.abstract]), or a (possibly multidimensional) array thereof.
15)15)
Appearing inside the brace-enclosed declaration-seq in a linkage-specification does not affect whether a declaration is a definition.

6.3 One-definition rule [basic.def.odr]

Each of the following is termed a definable item:
No translation unit shall contain more than one definition of any definable item.
An expression or conversion is potentially evaluated unless it is an unevaluated operand ([expr.context]), a subexpression thereof, or a conversion in an initialization or conversion sequence in such a context.
The set of potential results of an expression E is defined as follows:
  • If E is an id-expression ([expr.prim.id]), the set contains only E.
  • If E is a subscripting operation with an array operand, the set contains the potential results of that operand.
  • If E is a class member access expression ([expr.ref]) of the form . template naming a non-static data member, the set contains the potential results of .
  • If E is a class member access expression naming a static data member, the set contains the id-expression designating the data member.
  • If E is a pointer-to-member expression of the form .* , the set contains the potential results of .
  • If E has the form (), the set contains the potential results of .
  • If E is a glvalue conditional expression, the set is the union of the sets of potential results of the second and third operands.
  • If E is a comma expression, the set contains the potential results of the right operand.
  • Otherwise, the set is empty.
[Note 1: 
This set is a (possibly-empty) set of id-expressions, each of which is either E or a subexpression of E.
[Example 1: 
In the following example, the set of potential results of the initializer of n contains the first S​::​x subexpression, but not the second S​::​x subexpression.
struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x) // S​::​x is not odr-used here : f(S::x); // S​::​x is odr-used here, so a definition is required — end example]
— end note]
A function is named by an expression or conversion as follows:
  • A function is named by an expression or conversion if it is the selected member of an overload set ([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 the expression is not an id-expression naming the function with an explicitly qualified name or the expression forms a pointer to member ([expr.unary.op]).
    [Note 2: 
    This covers taking the address of functions ([conv.func], [expr.unary.op]), calls to named functions ([expr.call]), operator overloading ([over]), user-defined conversions ([class.conv.fct]), allocation functions for new-expressions ([expr.new]), as well as non-default initialization ([dcl.init]).
    A constructor selected to copy or move an object of class type is considered to be named by an expression or conversion even if the call is actually elided by the implementation ([class.copy.elision]).
    — end note]
  • A deallocation function for a class is named by a new-expression if it is the single matching deallocation function for the allocation function selected by overload resolution, as specified in [expr.new].
  • A deallocation function for a class is named by a delete-expression if it is the selected usual deallocation function as specified in [expr.delete] and [class.free].
A variable is named by an expression if the expression is an id-expression that denotes it.
A variable x that is named by a potentially-evaluated expression N that appears at a point P is odr-used by N unless
  • x is a reference that is usable in constant expressions at P ([expr.const]) or
  • N is an element of the set of potential results of an expression E, where
    • E is a discarded-value expression ([expr.context]) to which the lvalue-to-rvalue conversion is not applied or
    • x is a non-volatile object that is usable in constant expressions at P and has no mutable subobjects and
      • E is a class member access expression ([expr.ref]) naming a non-static data member of reference type and whose object expression has non-volatile-qualified type or
      • the lvalue-to-rvalue conversion ([conv.lval]) is applied to E and E has non-volatile-qualified non-class type
[Example 2: int f(int); int g(int&); struct A { int x; }; struct B { int& r; }; int h(bool cond) { constexpr A a = {1}; constexpr const volatile A& r = a; // odr-uses a int _ = f(cond ? a.x : r.x); // does not odr-use a or r int x, y; constexpr B b1 = {x}, b2 = {y}; // odr-uses x and y int _ = g(cond ? b1.r : b2.r); // does not odr-use b1 or b2 int _ = ((cond ? x : y), 0); // does not odr-use x or y return [] { return b1.r; // error: b1 is odr-used here because the object // referred to by b1.r is not constexpr-referenceable here }(); } — end example]
A structured binding is odr-used if it appears as a potentially-evaluated expression.
*this is odr-used if this appears as a potentially-evaluated expression (including as the result of any implicit transformation to a class member access expression ([expr.prim.id.general])).
A virtual member function is odr-used if it is not pure.
A function is odr-used if it is named by a potentially-evaluated expression or conversion.
A non-placement allocation or deallocation function for a class is odr-used by the definition of a constructor of that class.
A non-placement deallocation function for a class is odr-used by the definition of the destructor of that class, or by being selected by the lookup at the point of definition of a virtual destructor ([class.dtor]).16
An assignment operator function in a class is odr-used by an implicitly-defined copy assignment or move assignment function for another class as specified in [class.copy.assign].
A constructor for a class is odr-used as specified in [dcl.init].
A destructor for a class is odr-used if it is potentially invoked.
A local entity ([basic.pre]) is odr-usable in a scope ([basic.scope.scope]) if
  • either the local entity is not *this, or an enclosing class or non-lambda function parameter scope exists and, if the innermost such scope is a function parameter scope, it corresponds to a non-static member function, and
  • for each intervening scope ([basic.scope.scope]) between the point at which the entity is introduced and the scope (where *this is considered to be introduced within the innermost enclosing class or non-lambda function definition scope), either:
If a local entity is odr-used in a scope in which it is not odr-usable, the program is ill-formed.
[Example 3: void f(int n) { [] { n = 1; }; // error: n is not odr-usable due to intervening lambda-expression struct A { void f() { n = 2; } // error: n is not odr-usable due to intervening function definition scope }; void g(int = n); // error: n is not odr-usable due to intervening function parameter scope [=](int k = n) {}; // error: n is not odr-usable due to being // outside the block scope of the lambda-expression [&] { [n]{ return n; }; }; // OK } — end example]
[Example 4: void g() { constexpr int x = 1; auto lambda = [] <typename T, int = ((T)x, 0)> {}; // OK lambda.operator()<int, 1>(); // OK, does not consider x at all lambda.operator()<int>(); // OK, does not odr-use x lambda.operator()<const int&>(); // error: odr-uses x from a context where x is not odr-usable } void h() { constexpr int x = 1; auto lambda = [] <typename T> { (T)x; }; // OK lambda.operator()<int>(); // OK, does not odr-use x lambda.operator()<void>(); // OK, does not odr-use x lambda.operator()<const int&>(); // error: odr-uses x from a context where x is not odr-usable } — end example]
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; no diagnostic required.
The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.default.ctor], [class.copy.ctor], [class.dtor], and [class.copy.assign]).
[Example 5: auto f() { struct A {}; return A{}; } decltype(f()) g(); auto x = g();
A program containing this translation unit is ill-formed because g is odr-used but not defined, and cannot be defined in any other translation unit because the local class A cannot be named outside this translation unit.
— end example]
A definition domain is a private-module-fragment or the portion of a translation unit excluding its private-module-fragment (if any).
A definition of an inline function or variable shall be reachable from the end of every definition domain in which it is odr-used outside of a discarded statement.
A definition of a class shall be reachable in every context in which the class is used in a way that requires the class type to be complete.
[Example 6: 
The following complete translation unit is well-formed, even though it never defines X: struct X; // declare X as a struct type struct X* x1; // use X in pointer formation X* x2; // use X in pointer formation
— end example]
[Note 3: 
The rules for declarations and expressions describe in which contexts complete class types are required.
A class type T must be complete if
— end note]
For any definable item D with definitions in multiple translation units,
  • if D is a non-inline non-templated function or variable, or
  • if the definitions in different translation units do not satisfy the following requirements,
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 D, or, if D is an unnamed enumeration, for all definitions of D that are reachable at any given program point, the following requirements shall be satisfied.
  • Each such definition shall not be attached to a named module ([module.unit]).
  • Each such definition shall consist of the same sequence of tokens, where the definition of a closure type is considered to consist of the sequence of tokens of the corresponding lambda-expression.
  • In each such definition, corresponding names, looked up according to [basic.lookup], shall refer to the same entity, after overload resolution ([over.match]) and after matching of partial template specialization ([temp.over]), except that a name can refer to
    • a non-volatile const object with internal or no linkage if the object or
    • a reference with internal or no linkage initialized with a constant expression such that the reference refers to the same entity in all definitions of D.
  • In each such definition, except within the default arguments and default template arguments of D, corresponding lambda-expressions shall have the same closure type (see below).
  • In each such definition, corresponding entities shall have the same language linkage.
  • In each such definition, const objects with static or thread storage duration shall be constant-initialized if the object is constant-initialized in any such definition.
  • In each such definition, corresponding manifestly constant-evaluated expressions that are not value-dependent shall have the same value ([expr.const], [temp.dep.constexpr]).
  • In each such definition, the overloaded operators referred to, the implicit calls to conversion functions, constructors, operator new functions and operator delete functions, shall refer to the same function.
  • In each such definition, a default argument used by an (implicit or explicit) function call or a default template argument used by an (implicit or explicit) template-id or simple-template-id is treated as if its token sequence were present in the definition of D; that is, the default argument or default template argument is subject to the requirements described in this paragraph (recursively).
For the purposes of the preceding requirements:
  • If D is a class with an implicitly-declared constructor ([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 constructor for a subobject of D.
    [Example 7: // translation unit 1: struct X { X(int, int); X(int, int, int); }; X::X(int, int = 0) { } class D { X x = 0; }; D d1; // X(int, int) called by D() // translation unit 2: struct X { X(int, int); X(int, int, int); }; X::X(int, int = 0, int = 0) { } class D { X x = 0; }; D d2; // X(int, int, int) called by D(); // D()'s implicit definition violates the ODR — end example]
  • If D is a class with a defaulted three-way comparison operator function ([class.spaceship]), it is as if the operator was implicitly defined in every translation unit where it is odr-used, and the implicit definition in every translation unit shall call the same comparison operators for each subobject of D.
  • If D is a template and is defined in more than one translation unit, the requirements apply both to names from the template's enclosing scope used in the template definition, and also to dependent names at the point of instantiation ([temp.dep]).
These requirements also apply to corresponding entities defined within each definition of D (including the closure types of lambda-expressions, but excluding entities defined within default arguments or default template arguments of either D or an entity not defined within D).
For each such entity and for D itself, the behavior is as if there is a single entity with a single definition, including in the application of these requirements to other entities.
[Note 4: 
The entity is still declared in multiple translation units, and [basic.link] still applies to these declarations.
In particular, lambda-expressions ([expr.prim.lambda]) appearing in the type of D can result in the different declarations having distinct types, and lambda-expressions appearing in a default argument of D might still denote different types in different translation units.
— end note]
[Example 8: inline void f(bool cond, void (*p)()) { if (cond) f(false, []{}); } inline void g(bool cond, void (*p)() = []{}) { if (cond) g(false); } struct X { void h(bool cond, void (*p)() = []{}) { if (cond) h(false); } };
If the definition of f appears in multiple translation units, the behavior of the program is as if there is only one definition of f.
If the definition of g appears in multiple translation units, the program is ill-formed (no diagnostic required) because each such definition uses a default argument that refers to a distinct lambda-expression closure type.
The definition of X can appear in multiple translation units of a valid program; the lambda-expressions defined within the default argument of X​::​h within the definition of X denote the same closure type in each translation unit.
— end example]
If, at any point in the program, there is more than one reachable unnamed enumeration definition in the same scope that have the same first enumerator name and do not have typedef names for linkage purposes ([dcl.enum]), those unnamed enumeration types shall be the same; no diagnostic required.
16)16)
An implementation is not required to call allocation and deallocation functions from constructors or destructors; however, this is a permissible implementation technique.

6.4 Scope [basic.scope]

6.4.1 General [basic.scope.scope]

The declarations in a program appear in a number of scopes that are in general discontiguous.
The global scope contains the entire program; every other scope S is introduced by a declaration, parameter-declaration-clause, statement, or handler (as described in the following subclauses of [basic.scope]) appearing in another scope which thereby contains S.
An enclosing scope at a program point is any scope that contains it; the smallest such scope is said to be the immediate scope at that point.
A scope intervenes between a program point P and a scope S (that does not contain P) if it is or contains S but does not contain P.
Unless otherwise specified:
An entity belongs to a scope S if S is the target scope of a declaration of the entity.
[Note 1: 
Special cases include that:
— end note]
Two non-static member functions have corresponding object parameters if
  • exactly one is an implicit object member function with no ref-qualifier and the types of their object parameters ([dcl.fct]), after removing references, are the same, or
  • their object parameters have the same type.
Two non-static member function templates have corresponding object parameters if
  • exactly one is an implicit object member function with no ref-qualifier and the types of their object parameters, after removing any references, are equivalent, or
  • the types of their object parameters are equivalent.
Two function templates have corresponding signatures if their template-parameter-lists have the same length, their corresponding template-parameters are equivalent, they have equivalent non-object-parameter-type-lists and return types (if any), and, if both are non-static members, they have corresponding object parameters.
Two declarations correspond if they (re)introduce the same name, both declare constructors, or both declare destructors, unless
  • either is a using-declarator, or
  • one declares a type (not a typedef-name) and the other declares a variable, non-static data member other than of an anonymous union ([class.union.anon]), enumerator, function, or function template, or
  • each declares a function or function template and they do not declare corresponding overloads.
Two function or function template declarations declare corresponding overloads if
[Note 2: 
Declarations can correspond even if neither binds a name.
[Example 1: struct A { friend void f(); // #1 }; struct B { friend void f() {} // corresponds to, and defines, #1 }; — end example]
— end note]
[Example 2: typedef int Int; enum E : int { a }; void f(int); // #1 void f(Int) {} // defines #1 void f(E) {} // OK, another overload struct X { static void f(); void f() const; // error: redeclaration void g(); void g() const; // OK void g() &; // error: redeclaration void h(this X&, int); void h(int) &&; // OK, another overload void j(this const X&); void j() const &; // error: redeclaration void k(); void k(this X&); // error: redeclaration }; — end example]
A declaration is name-independent if its name is _ (U+005f low line) and it declares
Recommended practice: Implementations should not emit a warning that a name-independent declaration is used or unused.
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).
The program is ill-formed if, in any scope, a name is bound to two declarations A and B that potentially conflict and A precedes B ([basic.lookup]), unless B is name-independent.
[Note 3: 
An id-expression that names a unique name-independent declaration is usable until an additional declaration of the same name is introduced in the same scope ([basic.lookup.general]).
— end note]
[Note 4: 
Overload resolution can consider potentially conflicting declarations found in multiple scopes (e.g., via using-directives or for operator functions), in which case it is often ambiguous.
— end note]
[Example 3: void f() { int x,y; void x(); // error: different entity for x int y; // error: redefinition } enum { f }; // error: different entity for ​::​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 {} // error: different entity for B void g() { int _; _ = 0; // OK int _; // OK, name-independent declaration _ = 0; // error: two non-function declarations in the lookup set } void h () { int _; // #1 _ ++; // OK static int _; // error: conflicts with #1 because static variables are not name-independent } — end example]
A declaration is nominable in a class, class template, or namespace E at a point P if it precedes P, it does not inhabit a block scope, and its target scope is the scope associated with E or, if E is a namespace, any element of the inline namespace set of E ([namespace.def]).
[Example 4: namespace A { void f() {void g();} inline namespace B { struct S { friend void h(); static int i; }; } }
At the end of this example, the declarations of f, B, S, and h are nominable in A, but those of g and i are not.
— end example]
When instantiating a templated entity ([temp.pre]), any scope S introduced by any part of the template definition is considered to be introduced by the instantiated entity and to contain the instantiations of any declarations that inhabit S.
17)17)
An implicit object parameter ([over.match.funcs]) is not part of the parameter-type-list.

6.4.2 Point of declaration [basic.scope.pdecl]

The locus of a declaration ([basic.pre]) that is a declarator is immediately after the complete declarator ([dcl.decl]).
[Example 1: unsigned char x = 12; { unsigned char x = x; }
Here, the initialization of the second x has undefined behavior, because the initializer accesses the second x outside its lifetime ([basic.life]).
— end example]
[Note 1: 
A name from an outer scope remains visible up to the locus of the declaration that hides it.
[Example 2: 
const int i = 2; { int i[i]; } declares a block-scope array of two integers.
— end example]
— end note]
The locus of a class-specifier is immediately after the identifier or simple-template-id (if any) in its class-head ([class.pre]).
The locus of an enum-specifier is immediately after its enum-head; the locus of an opaque-enum-declaration is immediately after it ([dcl.enum]).
The locus of an alias-declaration is immediately after it.
The locus of a using-declarator that does not name a constructor is immediately after the using-declarator ([namespace.udecl]).
The locus of an enumerator-definition is immediately after it.
[Example 3: const int x = 12; { enum { x = x }; }
Here, the enumerator x is initialized with the value of the constant x, namely 12.
— end example]
[Note 2: 
After the declaration of a class member, the member name can be found in the scope of its class even if the class is an incomplete class.
[Example 4: struct X { enum E { z = 16 }; int b[X::z]; // OK }; — end example]
— end note]
The locus of an elaborated-type-specifier that is a declaration ([dcl.type.elab]) is immediately after it.
The locus of an injected-class-name declaration ([class.pre]) is immediately following the opening brace of the class definition.
The locus of the implicit declaration of a function-local predefined variable ([dcl.fct.def.general]) is immediately before the function-body of its function's definition.
The locus of the declaration of a structured binding ([dcl.struct.bind]) is immediately after the identifier-list of the structured binding declaration.
The locus of a for-range-declaration of a range-based for statement ([stmt.ranged]) is immediately after the for-range-initializer.
The locus of a template-parameter is immediately after it.
[Example 5: typedef unsigned char T; template<class T = T // lookup finds the typedef-name , T // lookup finds the template parameter N = 0> struct A { }; — end example]
The locus of a concept-definition is immediately after its concept-name ([temp.concept]).
[Note 3:  — end note]
The locus of a namespace-definition with an identifier is immediately after the identifier.
[Note 4: 
An identifier is invented for an unnamed-namespace-definition ([namespace.unnamed]).
— end note]
[Note 5: 
Friend declarations can introduce functions or classes that belong to the nearest enclosing namespace or block scope, but they do not bind names anywhere ([class.friend]).
Function declarations at block scope and variable declarations with the extern specifier at block scope declare entities that belong to the nearest enclosing namespace, but they do not bind names in it.
— end note]
[Note 6: 
For point of instantiation of a template, see [temp.point].
— end note]

6.4.3 Block scope [basic.scope.block]

Each introduces a block scope that includes that statement or handler.
[Note 1: 
A substatement that is also a block has only one scope.
— end note]
A variable that belongs to a block scope is a block variable.
[Example 1: int i = 42; int a[10]; for (int i = 0; i < 10; i++) a[i] = i; int j = i; // j = 42 — end example]
If a declaration that is not a name-independent declaration and that binds a name in the block scope S of a potentially conflicts with a declaration whose target scope is the parent scope of S, the program is ill-formed.
[Example 2: if (int x = f()) { int x; // error: redeclaration of x } else { int x; // error: redeclaration of x } — end example]

6.4.4 Function parameter scope [basic.scope.param]

[Note 1: 
A function parameter cannot be used for its value within the parameter-declaration-clause ([dcl.fct.default]).
— end note]

6.4.5 Lambda scope [basic.scope.lambda]

A lambda-expression E introduces a lambda scope that starts immediately after the lambda-introducer of E and extends to the end of the compound-statement of E.

6.4.6 Namespace scope [basic.scope.namespace]

Any namespace-definition for a namespace N introduces a namespace scope that includes the namespace-body for every namespace-definition for N.
For each non-friend redeclaration or specialization whose target scope is or is contained by the scope, the portion after the declarator-id, class-head-name, or enum-head-name is also included in the scope.
The global scope is the namespace scope of the global namespace ([basic.namespace]).
[Example 1: namespace Q { namespace V { void f(); } void V::f() { // in the scope of V void h(); // declares Q​::​V​::​h } } — end example]

6.4.7 Class scope [basic.scope.class]

Any declaration of a class or class template C introduces a class scope that includes the member-specification of the class-specifier for C (if any).
For each non-friend redeclaration or specialization whose target scope is or is contained by the scope, the portion after the declarator-id, class-head-name, or enum-head-name is also included in the scope.
[Note 1: 
Lookup from a program point before the class-specifier of a class will find no bindings in the class scope.
[Example 1: template<class D> struct B { D::type x; // #1 }; struct A { using type = int; }; struct C : A, B<C> {}; // error at #1: C​::​type not found — end example]
— end note]

6.4.8 Enumeration scope [basic.scope.enum]

Any declaration of an enumeration E introduces an enumeration scope that includes the enumerator-list of the enum-specifier for E (if any).

6.4.9 Template parameter scope [basic.scope.temp]

Each template template-parameter introduces a template parameter scope that includes the template-head of the template-parameter.
Each template-declaration D introduces a template parameter scope that extends from the beginning of its template-parameter-list to the end of the template-declaration.
Any declaration outside the template-parameter-list that would inhabit that scope instead inhabits the same scope as D.
The parent scope of any scope S that is not a template parameter scope is the smallest scope that contains S and is not a template parameter scope.
[Note 1: 
Therefore, only template parameters belong to a template parameter scope, and only template parameter scopes have a template parameter scope as a parent scope.
— end note]

6.5 Name lookup [basic.lookup]

6.5.1 General [basic.lookup.general]

Name lookup associates the use of a name with a set of declarations ([basic.def]) of that name.
The name lookup rules apply uniformly to all names (including typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]), and class-names ([class.name])) wherever the grammar allows such names in the context discussed by a particular rule.
Unless otherwise specified, the program is ill-formed if no declarations are found.
If the declarations found by name lookup all denote functions or function templates, the declarations are said to form an overload set.
Otherwise, if the declarations found by name lookup do not all denote the same entity, they are ambiguous and the program is ill-formed.
Overload resolution ([over.match], [over.over]) takes place after name lookup has succeeded.
The access rules ([class.access]) are considered only once name lookup and function overload resolution (if applicable) have succeeded.
Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the semantic properties introduced by the declarations used in further processing.
A program point P is said to follow any declaration in the same translation unit whose locus ([basic.scope.pdecl]) is before P.
[Note 1: 
The declaration might appear in a scope that does not contain P.
— end note]
A declaration X precedes a program point P in a translation unit L if P follows X, X inhabits a class scope and is reachable from P, or else X appears in a translation unit D and
[Note 3: 
A module-import-declaration imports both the named translation unit(s) and any modules named by exported module-import-declarations within them, recursively.
[Example 1: 

Translation unit #1:export module Q; export int sq(int i) { return i*i; }

Translation unit #2:export module R; export import Q;

Translation unit #3:import R; int main() { return sq(9); } // OK, sq from module Q — end example]

— end note]
A single search in a scope S for a name N from a program point P finds all declarations that precede P to which any name that is the same as N ([basic.pre]) is bound in S.
If any such declaration is a using-declarator whose terminal name ([expr.prim.id.unqual]) is not dependent ([temp.dep.type]), it is replaced by the declarations named by the using-declarator ([namespace.udecl]).
In certain contexts, only certain kinds of declarations are included.
After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found.
[Note 4: 
A type (but not a typedef-name or template) is therefore hidden by any other entity in its scope.
— end note]
However, if a lookup is type-only, only declarations of types and templates whose specializations are types are considered; furthermore, if declarations of a typedef-name and of the type to which it refers are found, the declaration of the typedef-name is discarded instead of the type declaration.

6.5.2 Member name lookup [class.member.lookup]

A search in a scope X for a name M from a program point P is a single search in X for M from P unless X is the scope of a class or class template T, in which case the following steps define the result of the search.
[Note 1: 
The result differs only if M is a conversion-function-id or if the single search would find nothing.
— end note]
The lookup set for a name N in a class or class template C, called S(N,C), consists of two component sets: the declaration set, a set of members named N; and the subobject set, a set of subobjects where declarations of these members were found (possibly via using-declarations).
In the declaration set, type declarations (including injected-class-names) are replaced by the types they designate.
S(N,C) is calculated as follows:
The declaration set is the result of a single search in the scope of C for N from immediately after the class-specifier of C if P is in a complete-class context of C or from P otherwise.
If the resulting declaration set is not empty, the subobject set contains C itself, and calculation is complete.
Otherwise (i.e., C does not contain a declaration of N or the resulting declaration set is empty), S(N,C) is initially empty.
Calculate the lookup set for N in each direct non-dependent ([temp.dep.type]) base class subobject , and merge each such lookup set in turn into S(N,C).
[Note 2: 
If C is incomplete, only base classes whose base-specifier appears before P are considered.
If C is an instantiated class, its base classes are not dependent.
— end note]
The following steps define the result of merging lookup set into the intermediate S(N,C):
  • If each of the subobject members of is a base class subobject of at least one of the subobject members of S(N,C), or if is empty, S(N,C) is unchanged and the merge is complete.
    Conversely, if each of the subobject members of S(N,C) is a base class subobject of at least one of the subobject members of , or if S(N,C) is empty, the new S(N,C) is a copy of .
  • Otherwise, if the declaration sets of and S(N,C) differ, the merge is ambiguous: the new S(N,C) is a lookup set with an invalid declaration set and the union of the subobject sets.
    In subsequent merges, an invalid declaration set is considered different from any other.
  • Otherwise, the new S(N,C) is a lookup set with the shared set of declarations and the union of the subobject sets.
The result of the search is the declaration set of S(M,T).
If it is an invalid set, the program is ill-formed.
If it differs from the result of a search in T for M in a complete-class context ([class.mem]) of T, the program is ill-formed, no diagnostic required.
[Example 1: struct A { int x; }; // S(x,A) = { { A​::​x }, { A } } struct B { float x; }; // S(x,B) = { { B​::​x }, { B } } struct C: public A, public B { }; // S(x,C) = { invalid, { A in C, B in C } } struct D: public virtual C { }; // S(x,D) = S(x,C) struct E: public virtual C { char x; }; // S(x,E) = { { E​::​x }, { E } } struct F: public D, public E { }; // S(x,F) = S(x,E) int main() { F f; f.x = 0; // OK, lookup finds E​::​x }
S(x,F) is unambiguous because the A and B base class subobjects of D are also base class subobjects of E, so S(x,D) is discarded in the first merge step.
— end example]
If M is a non-dependent conversion-function-id, conversion function templates that are members of T are considered.
For each such template F, the lookup set S(t,T) is constructed, considering a function template declaration to have the name t only if it corresponds to a declaration of F ([basic.scope.scope]).
The members of the declaration set of each such lookup set, which shall not be an invalid set, are included in the result.
[Note 3: 
Overload resolution will discard those that cannot convert to the type specified by M ([temp.over]).
— end note]
[Note 4: 
A static member, a nested type or an enumerator defined in a base class T can unambiguously be found even if an object has more than one base class subobject of type T.
Two base class subobjects share the non-static member subobjects of their common virtual base classes.
— end note]
[Example 2: struct V { int v; }; struct A { int a; static int s; enum { e }; }; struct B : A, virtual V { }; struct C : A, virtual V { }; struct D : B, C { }; void f(D* pd) { pd->v++; // OK, only one v (virtual) pd->s++; // OK, only one s (static) int i = pd->e; // OK, only one e (enumerator) pd->a++; // error: ambiguous: two as in D } — end example]
[Note 5: 
When virtual base classes are used, a hidden declaration can be reached along a path through the subobject lattice that does not pass through the hiding declaration.
This is not an ambiguity.
The identical use with non-virtual base classes is an ambiguity; in that case there is no unique instance of the name that hides all the others.
— end note]
[Example 3: struct V { int f(); int x; }; struct W { int g(); int y; }; struct B : virtual V, W { int f(); int x; int g(); int y; }; struct C : virtual V, W { }; struct D : B, C { void glorp(); };
virt W1 W V V W2 W B B B->W1 B->V C C C->V C->W2 D D D->B D->C
Figure 1 — Name lookup  [fig:class.lookup]
As illustrated in Figure 1, the names declared in V and the left-hand instance of W are hidden by those in B, but the names declared in the right-hand instance of W are not hidden at all.
void D::glorp() { x++; // OK, B​::​x hides V​::​x f(); // OK, B​::​f() hides V​::​f() y++; // error: B​::​y and C's W​::​y g(); // error: B​::​g() and C's W​::​g() } — end example]
An explicit or implicit conversion from a pointer to or an expression designating an object of a derived class to a pointer or reference to one of its base classes shall unambiguously refer to a unique object representing the base class.
[Example 4: struct V { }; struct A { }; struct B : A, virtual V { }; struct C : A, virtual V { }; struct D : B, C { }; void g() { D d; B* pb = &d; A* pa = &d; // error: ambiguous: C's A or B's A? V* pv = &d; // OK, only one V subobject } — end example]
[Note 6: 
Even if the result of name lookup is unambiguous, use of a name found in multiple subobjects might still be ambiguous ([conv.mem], [expr.ref], [class.access.base]).
— end note]
[Example 5: struct B1 { void f(); static void f(int); int i; }; struct B2 { void f(double); }; struct I1: B1 { }; struct I2: B1 { }; struct D: I1, I2, B2 { using B1::f; using B2::f; void g() { f(); // Ambiguous conversion of this f(0); // Unambiguous (static) f(0.0); // Unambiguous (only one B2) int B1::* mpB1 = &D::i; // Unambiguous int D::* mpD = &D::i; // Ambiguous conversion } }; — end example]

6.5.3 Unqualified name lookup [basic.lookup.unqual]

A using-directive is active in a scope S at a program point P if it precedes P and inhabits either S or the scope of a namespace nominated by a using-directive that is active in S at P.
An unqualified search in a scope S from a program point P includes the results of searches from P in
  • S, and
  • for any scope U that contains P and is or is contained by S, each namespace contained by S that is nominated by a using-directive that is active in U at P.
If no declarations are found, the results of the unqualified search are the results of an unqualified search in the parent scope of S, if any, from P.
[Note 1: 
When a class scope is searched, the scopes of its base classes are also searched ([class.member.lookup]).
If it inherits from a single base, it is as if the scope of the base immediately contains the scope of the derived class.
Template parameter scopes that are associated with one scope in the chain of parents are also considered ([temp.local]).
— end note]
Unqualified name lookup from a program point performs an unqualified search in its immediate scope.
An unqualified name is a name that does not immediately follow a nested-name-specifier or the . or -> in a class member access expression ([expr.ref]), possibly after a template keyword or ~.
Unless otherwise specified, such a name undergoes unqualified name lookup from the point where it appears.
An unqualified name that is a component name ([expr.prim.id.unqual]) of a type-specifier or ptr-operator of a conversion-type-id is looked up in the same fashion as the conversion-function-id in which it appears.
If that lookup finds nothing, it undergoes unqualified name lookup; in each case, only names that denote types or templates whose specializations are types are considered.
[Example 1: struct T1 { struct U { int i; }; }; struct T2 { }; struct U1 {}; struct U2 {}; struct B { using T = T1; using U = U1; operator U1 T1::*(); operator U1 T2::*(); operator U2 T1::*(); operator U2 T2::*(); }; template<class X, class T> int g() { using U = U2; X().operator U T::*(); // #1, searches for T in the scope of X first X().operator U decltype(T())::*(); // #2 return 0; } int x = g<B, T2>(); // #1 calls B​::​operator U1 T1​::​* // #2 calls B​::​operator U1 T2​::​* — end example]
In a friend declaration declarator whose declarator-id is a qualified-id whose lookup context ([basic.lookup.qual]) is a class or namespace S, lookup for an unqualified name that appears after the declarator-id performs a search in the scope associated with S.
If that lookup finds nothing, it undergoes unqualified name lookup.
[Example 2: using I = int; using D = double; namespace A { inline namespace N {using C = char; } using F = float; void f(I); void f(D); void f(C); void f(F); } struct X0 {using F = float; }; struct W { using D = void; struct X : X0 { void g(I); void g(::D); void g(F); }; }; namespace B { typedef short I, F; class Y { friend void A::f(I); // error: no void A​::​f(short) friend void A::f(D); // OK friend void A::f(C); // error: A​::​N​::​C not found friend void A::f(F); // OK friend void W::X::g(I); // error: no void X​::​g(short) friend void W::X::g(D); // OK friend void W::X::g(F); // OK }; } — end example]

6.5.4 Argument-dependent name lookup [basic.lookup.argdep]

When the postfix-expression in a function call ([expr.call]) is an unqualified-id, and unqualified lookup ([basic.lookup.unqual]) for the name in the unqualified-id does not find any
  • declaration of a class member, or
  • function declaration inhabiting a block scope, or
  • declaration not of a function or function template
then lookup for the name also includes the result of argument-dependent lookup in a set of associated namespaces that depends on the types of the arguments (and for template template arguments, the namespace of the template argument), as specified below.
[Example 1: namespace N { struct S { }; void f(S); } void g() { N::S s; f(s); // OK, calls N​::​f (f)(s); // error: N​::​f not considered; parentheses prevent argument-dependent lookup } — end example]
[Note 1: 
For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.
In some cases a name followed by < is treated as a template-name even though name lookup did not find a template-name (see [temp.names]).
For example, int h; void g(); namespace N { struct A {}; template <class T> int f(T); template <class T> int g(T); template <class T> int h(T); } int x = f<N::A>(N::A()); // OK, lookup of f finds nothing, f treated as template name int y = g<N::A>(N::A()); // OK, lookup of g finds a function, g treated as template name int z = h<N::A>(N::A()); // error: h< does not begin a template-id
The rules have no effect on the syntactic interpretation of an expression.
For example, typedef int f; namespace N { struct A { friend void f(A &); operator int(); void g(A a) { int i = f(a); // f is the typedef, not the friend function: equivalent to int(a) } }; }
Because the expression is not a function call, argument-dependent name lookup does not apply and the friend function f is not found.
— end note]
For each argument type T in the function call, there is a set of zero or more associated entities to be considered.
The set of entities is determined entirely by the types of the function arguments (and any template template arguments).
Any typedef-names and using-declarations used to specify the types do not contribute to this set.
The set of entities is determined in the following way:
  • If T is a fundamental type, its associated set of entities is empty.
  • If T is a class type (including unions), its associated entities are: the class itself; the class of which it is a member, if any; and, if it is a complete type, its direct and indirect base classes.
    Furthermore, if T is a class template specialization, its associated entities also include: the entities associated with the types of the template arguments provided for template type parameters; the templates used as template template arguments; and the classes of which any member templates used as template template arguments are members.
    [Note 2: 
    Non-type template arguments do not contribute to the set of associated entities.
    — end note]
  • If T is an enumeration type, its associated entities are T and, if it is a class member, the member's class.
  • If T is a pointer to U or an array of U, its associated entities are those associated with U.
  • If T is a function type, its associated entities are those associated with the function parameter types and those associated with the return type.
  • If T is a pointer to a member function of a class X, its associated entities are those associated with the function parameter types and return type, together with those associated with X.
  • If T is a pointer to a data member of class X, its associated entities are those associated with the member type together with those associated with X.
In addition, if the argument is an overload set or the address of such a set, its associated entities are the union of those associated with each of the members of the set, i.e., the entities associated with its parameter types and return type.
Additionally, if the aforementioned overload set is named with a template-id, its associated entities also include its template template-arguments and those associated with its type template-arguments.
The associated namespaces for a call are the innermost enclosing non-inline namespaces for its associated entities as well as every element of the inline namespace set ([namespace.def]) of those namespaces.
Argument-dependent lookup finds all declarations of functions and function templates that
  • are found by a search of any associated namespace, or
  • are declared as a friend ([class.friend]) of any class with a reachable definition in the set of associated entities, or
  • are exported, are attached to a named module M ([module.interface]), do not appear in the translation unit containing the point of the lookup, and have the same innermost enclosing non-inline namespace scope as a declaration of an associated entity attached to M ([basic.link]).
If the lookup is for a dependent name ([temp.dep], [temp.dep.candidate]), the above lookup is also performed from each point in the instantiation context ([module.context]) of the lookup, additionally ignoring any declaration that appears in another translation unit, is attached to the global module, and is either discarded ([module.global.frag]) or has internal linkage.
[Example 2: 

Translation unit #1:export module M; namespace R { export struct X {}; export void f(X); } namespace S { export void f(R::X, R::X); }

Translation unit #2:export module N; import M; export R::X make(); namespace R { static int g(X); } export template<typename T, typename U> void apply(T t, U u) { f(t, u); g(t); }

Translation unit #3:module Q; import N; namespace S { struct Z { template<typename T> operator T(); }; } void test() { auto x = make(); // OK, decltype(x) is R​::​X in module M R::f(x); // error: R and R​::​f are not visible here f(x); // OK, calls R​::​f from interface of M f(x, S::Z()); // error: S​::​f in module M not considered // even though S is an associated namespace apply(x, S::Z()); // error: S​::​f is visible in instantiation context, but // R​::​g has internal linkage and cannot be used outside TU #2 } — end example]

[Note 3: 
The associated namespace can include namespaces already considered by ordinary unqualified lookup.
— end note]
[Example 3: namespace NS { class T { }; void f(T); void g(T, int); } NS::T parm; void g(NS::T, float); int main() { f(parm); // OK, calls NS​::​f extern void g(NS::T, float); g(parm, 1); // OK, calls g(NS​::​T, float) } — end example]

6.5.5 Qualified name lookup [basic.lookup.qual]

6.5.5.1 General [basic.lookup.qual.general]

Lookup of an identifier followed by a ​::​ scope resolution operator considers only namespaces, types, and templates whose specializations are types.
If a name, template-id, or computed-type-specifier is followed by a ​::​, it shall designate a namespace, class, enumeration, or dependent type, and the ​::​ is never interpreted as a complete nested-name-specifier.
[Example 1: class A { public: static int n; }; int main() { int A; A::n = 42; // OK A b; // error: A does not name a type } template<int> struct B : A {}; namespace N { template<int> void B(); int f() { return B<0>::n; // error: N​::​B<0> is not a type } } — end example]
A member-qualified name is the (unique) component name ([expr.prim.id.unqual]), if any, of in the id-expression of a class member access expression ([expr.ref]).
The lookup context of a member-qualified name is the type of its associated object expression (considered dependent if the object expression is type-dependent).
The lookup context of any other qualified name is the type, template, or namespace nominated by the preceding nested-name-specifier.
[Note 1: 
When parsing a class member access, the name following the -> or . is a qualified name even though it is not yet known of which kind.
— end note]
[Example 2: 
In N::C::m.Base::f() Base is a member-qualified name; the other qualified names are C, m, and f.
— end example]
Qualified name lookup in a class, namespace, or enumeration performs a search of the scope associated with it ([class.member.lookup]) except as specified below.
Unless otherwise specified, a qualified name undergoes qualified name lookup in its lookup context from the point where it appears unless the lookup context either is dependent and is not the current instantiation ([temp.dep.type]) or is not a class or class template.
If nothing is found by qualified lookup for a member-qualified name that is the terminal name ([expr.prim.id.unqual]) of a nested-name-specifier and is not dependent, it undergoes unqualified lookup.
[Note 2: 
During lookup for a template specialization, no names are dependent.
— end note]
[Example 3: int f(); struct A { int B, C; template<int> using D = void; using T = void; void f(); }; using B = A; template<int> using C = A; template<int> using D = A; template<int> using X = A; template<class T> void g(T *p) { // as instantiated for g<A>: p->X<0>::f(); // error: A​::​X not found in ((p->X) < 0) > ​::​f() p->template X<0>::f(); // OK, ​::​X found in definition context p->B::f(); // OK, non-type A​::​B ignored p->template C<0>::f(); // error: A​::​C is not a template p->template D<0>::f(); // error: A​::​D<0> is not a class type p->T::f(); // error: A​::​T is not a class type } template void g(A*); — end example]
If a qualified name Q follows a ~:
  • If Q is a member-qualified name, it undergoes unqualified lookup as well as qualified lookup.
  • Otherwise, its nested-name-specifier N shall nominate a type.
    If N has another nested-name-specifier S, Q is looked up as if its lookup context were that nominated by S.
  • Otherwise, if the terminal name of N is a member-qualified name M, Q is looked up as if ~Q appeared in place of M (as above).
  • Otherwise, Q undergoes unqualified lookup.
  • Each lookup for Q considers only types (if Q is not followed by a <) and templates whose specializations are types.
    If it finds nothing or is ambiguous, it is discarded.
  • The type-name that is or contains Q shall refer to its (original) lookup context (ignoring cv-qualification) under the interpretation established by at least one (successful) lookup performed.
[Example 4: struct C { typedef int I; }; typedef int I1, I2; extern int* p; extern int* q; void f() { p->C::I::~I(); // I is looked up in the scope of C q->I1::~I2(); // I2 is found by unqualified lookup } struct A { ~A(); }; typedef A AB; int main() { AB* p; p->AB::~AB(); // explicitly calls the destructor for A } — end example]

6.5.5.2 Class members [class.qual]

In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored,18 N is instead considered to name the constructor of class C.
Such a constructor name shall be used only in the declarator-id of a (friend) declaration of a constructor or in a using-declaration.
[Example 1: struct A { A(); }; struct B: public A { B(); }; A::A() { } B::B() { } B::A ba; // object of type A A::A a; // error: A​::​A is not a type name struct A::A a2; // object of type A — end example]
18)18)
Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.

6.5.5.3 Namespace members [namespace.qual]

Qualified name lookup in a namespace N additionally searches every element of the inline namespace set of N ([namespace.def]).
If nothing is found, the results of the lookup are the results of qualified name lookup in each namespace nominated by a using-directive that precedes the point of the lookup and inhabits N or an element of N's inline namespace set.
[Note 1: 
If a using-directive refers to a namespace that has already been considered, it does not affect the result.
— end note]
[Example 1: int x; namespace Y { void f(float); void h(int); } namespace Z { void h(double); } namespace A { using namespace Y; void f(int); void g(int); int i; } namespace B { using namespace Z; void f(char); int i; } namespace AB { using namespace A; using namespace B; void g(); } void h() { AB::g(); // g is declared directly in AB, therefore S is { AB​::​g() } and AB​::​g() is chosen AB::f(1); // f is not declared directly in AB so the rules are applied recursively to A and B; // namespace Y is not searched and Y​::​f(float) is not considered; // S is { A​::​f(int), B​::​f(char) } and overload resolution chooses A​::​f(int) AB::f('c'); // as above but resolution chooses B​::​f(char) AB::x++; // x is not declared directly in AB, and is not declared in A or B, so the rules // are applied recursively to Y and Z, S is { } so the program is ill-formed AB::i++; // i is not declared directly in AB so the rules are applied recursively to A and B, // S is { A​::​i, B​::​i } so the use is ambiguous and the program is ill-formed AB::h(16.8); // h is not declared directly in AB and not declared directly in A or B so the rules // are applied recursively to Y and Z, S is { Y​::​h(int), Z​::​h(double) } and // overload resolution chooses Z​::​h(double) } — end example]
[Note 2: 
The same declaration found more than once is not an ambiguity (because it is still a unique declaration).
[Example 2: namespace A { int a; } namespace B { using namespace A; } namespace C { using namespace A; } namespace BC { using namespace B; using namespace C; } void f() { BC::a++; // OK, S is { A​::​a, A​::​a } } namespace D { using A::a; } namespace BD { using namespace B; using namespace D; } void g() { BD::a++; // OK, S is { A​::​a, A​::​a } } — end example]
— end note]
[Example 3: 
Because each referenced namespace is searched at most once, the following is well-defined: namespace B { int b; } namespace A { using namespace B; int a; } namespace B { using namespace A; } void f() { A::a++; // OK, a declared directly in A, S is { A​::​a } B::a++; // OK, both A and B searched (once), S is { A​::​a } A::b++; // OK, both A and B searched (once), S is { B​::​b } B::b++; // OK, b declared directly in B, S is { B​::​b } }
— end example]
[Note 3: 
Class and enumeration declarations are not discarded because of other declarations found in other searches.
— end note]
[Example 4: namespace A { struct x { }; int x; int y; } namespace B { struct y { }; } namespace C { using namespace A; using namespace B; int i = C::x; // OK, A​::​x (of type int) int j = C::y; // ambiguous, A​::​y or B​::​y } — end example]

6.5.6 Elaborated type specifiers [basic.lookup.elab]

If the class-key or enum keyword in an elaborated-type-specifier is followed by an identifier that is not followed by ​::​, lookup for the identifier is type-only ([basic.lookup.general]).
[Note 1: 
In general, the recognition of an elaborated-type-specifier depends on the following tokens.
If the identifier is followed by ​::​, see [basic.lookup.qual].
— end note]
If the terminal name of the elaborated-type-specifier is a qualified name, lookup for it is type-only.
If the name lookup does not find a previously declared type-name, the elaborated-type-specifier is ill-formed.
[Example 1: struct Node { struct Node* Next; // OK, refers to injected-class-name Node struct Data* Data; // OK, declares type Data at global scope and member Data }; struct Data { struct Node* Node; // OK, refers to Node at global scope friend struct ::Glob; // error: Glob is not declared, cannot introduce a qualified type ([dcl.type.elab]) friend struct Glob; // OK, refers to (as yet) undeclared Glob at global scope. /* ... */ }; struct Base { struct Data; // OK, declares nested Data struct ::Data* thatData; // OK, refers to ​::​Data struct Base::Data* thisData; // OK, refers to nested Data friend class ::Data; // OK, global Data is a friend friend class Data; // OK, nested Data is a friend struct Data { /* ... */ }; // Defines nested Data }; struct Data; // OK, redeclares Data at global scope struct ::Data; // error: cannot introduce a qualified type ([dcl.type.elab]) struct Base::Data; // error: cannot introduce a qualified type ([dcl.type.elab]) struct Base::Datum; // error: Datum undefined struct Base::Data* pBase; // OK, refers to nested Data — end example]

6.5.7 Using-directives and namespace aliases [basic.lookup.udir]

In a using-directive or namespace-alias-definition, during the lookup for a namespace-name or for a name in a nested-name-specifier only namespace names are considered.

6.7 Memory and objects [basic.memobj]

6.7.1 Memory model [intro.memory]

The fundamental storage unit in the C++ memory model is the byte.
A byte is at least large enough to contain the ordinary literal encoding of any element of the basic literal character set ([lex.charset]) and the eight-bit code units of the Unicode UTF-8 encoding form and is composed of a contiguous sequence of bits,19 the number of which is implementation-defined.
The memory available to a C++ program consists of one or more sequences of contiguous bytes.
Every byte has a unique address.
[Note 1: 
The representation of types is described in [basic.types.general].
— end note]
A memory location is the storage occupied by the object representation of either an object of scalar type that is not a bit-field or a maximal sequence of adjacent bit-fields all having nonzero width.
[Note 2: 
Various features of the language, such as references and virtual functions, might involve additional memory locations that are not accessible to programs but are managed by the implementation.
— end note]
Two or more threads of execution can access separate memory locations without interfering with each other.
[Note 3: 
Thus a bit-field and an adjacent non-bit-field are in separate memory locations, and therefore can be concurrently updated by two threads of execution without interference.
The same applies to two bit-fields, if one is declared inside a nested struct declaration and the other is not, or if the two are separated by a zero-length bit-field declaration, or if they are separated by a non-bit-field declaration.
It is not safe to concurrently update two bit-fields in the same struct if all fields between them are also bit-fields of nonzero width.
— end note]
[Example 1: 
A class declared as struct { char a; int b:5, c:11, :0, d:8; struct {int ee:8;} e; }; contains four separate memory locations: The member a and bit-fields d and e.ee are each separate memory locations, and can be modified concurrently without interfering with each other.
The bit-fields b and c together constitute the fourth memory location.
The bit-fields b and c cannot be concurrently modified, but b and a, for example, can be.
— end example]
19)19)
The number of bits in a byte is reported by the macro CHAR_BIT in the header <climits>.

6.7.2 Object model [intro.object]

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects.
An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).
An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).
[Note 1: 
A function is not an object, regardless of whether or not it occupies storage in the way that objects do.
— end note]
The properties of an object are determined when the object is created.
An object can have a name ([basic.pre]).
An object has a storage duration ([basic.stc]) which influences its lifetime ([basic.life]).
An object has a type ([basic.types]).
[Note 2: 
Some objects are polymorphic ([class.virtual]); the implementation generates information associated with each such object that makes it possible to determine that object's type during program execution.
— end note]
Objects can contain other objects, called subobjects.
A subobject can be a member subobject ([class.mem]), a base class subobject ([class.derived]), or an array element.
An object that is not a subobject of any other object is called a complete object.
If an object is created in storage associated with a member subobject or array element e (which may or may not be within its lifetime), the created object is a subobject of e's containing object if
  • the lifetime of e's containing object has begun and not ended, and
  • the storage for the new object exactly overlays the storage location associated with e, and
  • the new object is of the same type as e (ignoring cv-qualification).
If a complete object is created ([expr.new]) in storage associated with another object e of type “array of N unsigned char” or of type “array of N std​::​byte” ([cstddef.syn]), that array provides storage for the created object if
  • the lifetime of e has begun and not ended, and
  • the storage for the new object fits entirely within e, and
  • there is no array object that satisfies these constraints nested within e.
[Note 3: 
If that portion of the array previously provided storage for another object, the lifetime of that object ends because its storage was reused ([basic.life]).
— end note]
[Example 1: // assumes that sizeof(int) is equal to 4 template<typename ...T> struct AlignedUnion { alignas(T...) unsigned char data[max(sizeof(T)...)]; }; int f() { AlignedUnion<int, char> au; int *p = new (au.data) int; // OK, au.data provides storage char *c = new (au.data) char(); // OK, ends lifetime of *p char *d = new (au.data + 1) char(); return *c + *d; // OK } struct A { unsigned char a[32]; }; struct B { unsigned char b[16]; }; alignas(int) A a; B *b = new (a.a + 8) B; // a.a provides storage for *b int *p = new (b->b + 4) int; // b->b provides storage for *p // a.a does not provide storage for *p (directly), // but *p is nested within a (see below) — end example]
An object a is nested within another object b if
  • a is a subobject of b, or
  • b provides storage for a, or
  • there exists an object c where a is nested within c, and c is nested within b.
For every object x, there is some object called the complete object of x, determined as follows:
  • If x is a complete object, then the complete object of x is itself.
  • Otherwise, the complete object of x is the complete object of the (unique) object that contains x.
If a complete object, a member subobject, or an array element is of class type, its type is considered the most derived class, to distinguish it from the class type of any base class subobject; an object of a most derived class type or of a non-class type is called a most derived object.
A potentially-overlapping subobject is either:
An object has nonzero size if it
  • is not a potentially-overlapping subobject, or
  • is not of class type, or
  • is of a class type with virtual member functions or virtual base classes, or
  • has subobjects of nonzero size or unnamed bit-fields of nonzero length.
Otherwise, if the object is a base class subobject of a standard-layout class type with no non-static data members, it has zero size.
Otherwise, the circumstances under which the object has zero size are implementation-defined.
Unless it is a bit-field, an object with nonzero size shall occupy one or more bytes of storage, including every byte that is occupied in full or in part by any of its subobjects.
An object of trivially copyable or standard-layout type ([basic.types.general]) shall occupy contiguous bytes of storage.
An object is a potentially non-unique object if it is a string literal object ([lex.string]), the backing array of an initializer list ([dcl.init.ref]), or a subobject thereof.
Unless an object is a bit-field or a subobject of zero size, the address of that object is the address of the first byte it occupies.
Two objects with overlapping lifetimes that are not bit-fields may have the same address if
  • one is nested within the other,
  • at least one is a subobject of zero size and they are not of similar types ([conv.qual]), or
  • they are both potentially non-unique objects;
otherwise, they have distinct addresses and occupy disjoint bytes of storage.20
[Example 2: static const char test1 = 'x'; static const char test2 = 'x'; const bool b = &test1 != &test2; // always true static const char (&r) [] = "x"; static const char *s = "x"; static std::initializer_list<char> il = { 'x' }; const bool b2 = r != il.begin(); // unspecified result const bool b3 = r != s; // unspecified result const bool b4 = il.begin() != &test1; // always true const bool b5 = r != &test1; // always true — end example]
The address of a non-bit-field subobject of zero size is the address of an unspecified byte of storage occupied by the complete object of that subobject.
Some operations are described as implicitly creating objects within a specified region of storage.
For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types ([basic.types.general]) in its specified region of storage if doing so would result in the program having defined behavior.
If no such set of objects would give the program defined behavior, the behavior of the program is undefined.
If multiple such sets of objects would give the program defined behavior, it is unspecified which such set of objects is created.
[Note 4: 
Such operations do not start the lifetimes of subobjects of such objects that are not themselves of implicit-lifetime types.
— end note]
Further, after implicitly creating objects within a specified region of storage, some operations are described as producing a pointer to a suitable created object.
These operations select one of the implicitly-created objects whose address is the address of the start of the region of storage, and produce a pointer value that points to that object, if that value would result in the program having defined behavior.
If no such pointer value would give the program defined behavior, the behavior of the program is undefined.
If multiple such pointer values would give the program defined behavior, it is unspecified which such pointer value is produced.
[Example 3: #include <cstdlib> struct X { int a, b; }; X *make_x() { // The call to std​::​malloc implicitly creates an object of type X // and its subobjects a and b, and returns a pointer to that X object // (or an object that is pointer-interconvertible ([basic.compound]) with it), // in order to give the subsequent class member access operations // defined behavior. X *p = (X*)std::malloc(sizeof(struct X)); p->a = 1; p->b = 2; return p; } — end example]
Except during constant evaluation, an operation that begins the lifetime of an array of unsigned char or std​::​byte implicitly creates objects within the region of storage occupied by the array.
[Note 5: 
The array object provides storage for these objects.
— end note]
Except during constant evaluation, any implicit or explicit invocation of a function named operator new or operator new[] implicitly creates objects in the returned region of storage and returns a pointer to a suitable created object.
[Note 6: 
Some functions in the C++ standard library implicitly create objects ([obj.lifetime], [c.malloc], [mem.res.public], [bit.cast], [cstring.syn]).
— end note]
20)20)
Under the “as-if” rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference ([intro.execution]).

6.7.3 Alignment [basic.align]

Object types have alignment requirements ([basic.fundamental], [basic.compound]) which place restrictions on the addresses at which an object of that type may be allocated.
An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated.
An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier ([dcl.align]).
Attempting to create an object ([intro.object]) in storage that does not meet the alignment requirements of the object's type is undefined behavior.
A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std​::​max_align_t) ([support.types]).
The alignment required for a type may be different when it is used as the type of a complete object and when it is used as the type of a subobject.
[Example 1: struct B { long double d; }; struct D : virtual B { char c; };
When D is the type of a complete object, it will have a subobject of type B, so it must be aligned appropriately for a long double.
If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different subobject, reducing the alignment requirements on the D subobject.
— end example]
The result of the alignof operator reflects the alignment requirement of the type in the complete-object case.
An extended alignment is represented by an alignment greater than alignof(std​::​max_align_t).
It is implementation-defined whether any extended alignments are supported and the contexts in which they are supported ([dcl.align]).
A type having an extended alignment requirement is an over-aligned type.
[Note 1: 
Every over-aligned type is or contains a class type to which extended alignment applies (possibly through a non-static data member).
— end note]
A new-extended alignment is represented by an alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__ ([cpp.predefined]).
Alignments are represented as values of the type std​::​size_t.
Valid alignments include only those values returned by an alignof expression for the fundamental types plus an additional implementation-defined set of values, which may be empty.
Every alignment value shall be a non-negative integral power of two.
Alignments have an order from weaker to stronger or stricter alignments.
Stricter alignments have larger alignment values.
An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.
The alignment requirement of a complete type can be queried using an alignof expression ([expr.alignof]).
Furthermore, the narrow character types ([basic.fundamental]) shall have the weakest alignment requirement.
[Note 2: 
This enables the ordinary character types to be used as the underlying type for an aligned memory area ([dcl.align]).
— end note]
Comparing alignments is meaningful and provides the obvious results:
  • Two alignments are equal when their numeric values are equal.
  • Two alignments are different when their numeric values are not equal.
  • When an alignment is larger than another it represents a stricter alignment.
[Note 3: 
The runtime pointer alignment function ([ptr.align]) can be used to obtain an aligned pointer within a buffer; an alignment-specifier ([dcl.align]) can be used to align storage explicitly.
— end note]
If a request for a specific extended alignment in a specific context is not supported by an implementation, the program is ill-formed.

6.7.4 Lifetime [basic.life]

In this subclause, “before” and “after” refer to the “happens before” relation ([intro.multithread]).
The lifetime of an object or reference is a runtime property of the object or reference.
A variable is said to have vacuous initialization if it is default-initialized, no other initialization is performed, and, if it is of class type or a (possibly multidimensional) array thereof, a trivial constructor of that class type is selected for the default-initialization.
The lifetime of an object of type T begins when:
  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
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 ([dcl.init.aggr], [class.base.init]), or as described in [class.union], [class.copy.ctor], and [class.copy.assign], and except as described in [allocator.members].
The lifetime of an object o of type T ends when:
  • if T is a non-class type, the object is destroyed, or
  • if T is a class type, the destructor call starts, or
  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).
When evaluating a new-expression, storage is considered reused after it is returned from the allocation function, but before the evaluation of the new-initializer ([expr.new]).
[Example 1: struct S { int m; }; void f() { S x{1}; new(&x) S(x.m); // undefined behavior } — end example]
The lifetime of a reference begins when its initialization is complete.
The lifetime of a reference ends as if it were a scalar object requiring storage.
[Note 1: 
[class.base.init] describes the lifetime of base and member subobjects.
— end note]
The properties ascribed to objects and references throughout this document apply for a given object or reference only during its lifetime.
[Note 2: 
In particular, before the lifetime of an object starts and after its lifetime ends there are significant restrictions on the use of the object, as described below, in [class.base.init], and in [class.cdtor].
Also, the behavior of an object under construction and destruction can differ from the behavior of an object whose lifetime has started and not ended.
[class.base.init] and [class.cdtor] describe the behavior of an object during its periods of construction and destruction.
— end note]
A program may end the lifetime of an object of class type without invoking the destructor, by reusing or releasing the storage as described above.
[Note 3: 
A delete-expression ([expr.delete]) invokes the destructor prior to releasing the storage.
— end note]
In this case, the destructor is not implicitly invoked.
[Note 4: 
The correct behavior of a program often depends on the destructor being invoked for each object of class type.
— end note]
Before the lifetime of an object has started but after the storage which the object will occupy has been allocated21 or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways.
For an object under construction or destruction, see [class.cdtor].
Otherwise, such a pointer refers to allocated storage ([basic.stc.dynamic.allocation]), and using the pointer as if the pointer were of type void* is well-defined.
Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below.
The program has undefined behavior if
  • the pointer is used as the operand of a delete-expression,
  • the pointer is used to access a non-static data member or call a non-static member function of the object, or
  • the pointer is implicitly converted ([conv.ptr]) to a pointer to a virtual base class, or
  • the pointer is used as the operand of a static_cast ([expr.static.cast]), except when the conversion is to pointer to cv void, or to pointer to cv void and subsequently to pointer to cv char, cv unsigned char, or cv std​::​byte ([cstddef.syn]), or
  • the pointer is used as the operand of a dynamic_cast ([expr.dynamic.cast]).
[Example 2: #include <cstdlib> struct B { virtual void f(); void mutate(); virtual ~B(); }; struct D1 : B { void f(); }; struct D2 : B { void f(); }; void B::mutate() { new (this) D2; // reuses storage --- ends the lifetime of *this f(); // undefined behavior ... = this; // OK, this points to valid memory } void g() { void* p = std::malloc(sizeof(D1) + sizeof(D2)); B* pb = new (p) D1; pb->mutate(); *pb; // OK, pb points to valid memory void* q = pb; // OK, pb points to valid memory pb->f(); // undefined behavior: lifetime of *pb has ended } — end example]
Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways.
For an object under construction or destruction, see [class.cdtor].
Otherwise, such a glvalue refers to allocated storage ([basic.stc.dynamic.allocation]), and using the properties of the glvalue that do not depend on its value is well-defined.
The program has undefined behavior if
  • the glvalue is used to access the object, or
  • the glvalue is used to call a non-static member function of the object, or
  • the glvalue is bound to a reference to a virtual base class ([dcl.init.ref]), or
  • the glvalue is used as the operand of a dynamic_cast ([expr.dynamic.cast]) or as the operand of typeid.
[Note 5: 
Therefore, undefined behavior results if an object that is being constructed in one thread is referenced from another thread without adequate synchronization.
— end note]
An object is transparently replaceable by an object if
  • the storage that occupies exactly overlays the storage that occupied, and
  • and are of the same type (ignoring the top-level cv-qualifiers), and
  • is not a const, complete object, and
  • neither nor is a potentially-overlapping subobject ([intro.object]), and
  • either and are both complete objects, or and are direct subobjects of objects and , respectively, and is transparently replaceable by .
After the lifetime of an object has ended and before the storage which the object occupied is reused or released, if a new object is created at the storage location which the original object occupied and the original object was transparently replaceable by the new object, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object.
[Example 3: struct C { int i; void f(); const C& operator=( const C& ); }; const C& C::operator=( const C& other) { if ( this != &other ) { this->~C(); // lifetime of *this ends new (this) C(other); // new object of type C created f(); // well-defined } return *this; } C c1; C c2; c1 = c2; // well-defined c1.f(); // well-defined; c1 refers to a new object of type C — end example]
[Note 6: 
If these conditions are not met, a pointer to the new object can be obtained from a pointer that represents the address of its storage by calling std​::​launder ([ptr.launder]).
— end note]
If a program ends the lifetime of an object of type T with static ([basic.stc.static]), thread ([basic.stc.thread]), or automatic ([basic.stc.auto]) storage duration and if T has a non-trivial destructor,22 and another object of the original type does not occupy that same storage location when the implicit destructor call takes place, the behavior of the program is undefined.
This is true even if the block is exited with an exception.
[Example 4: class T { }; struct B { ~B(); }; void h() { B b; new (&b) T; } // undefined behavior at block exit — end example]
Creating a new object within the storage that a const, complete object with static, thread, or automatic storage duration occupies, or within the storage that such a const object used to occupy before its lifetime ended, results in undefined behavior.
[Example 5: struct B { B(); ~B(); }; const B b; void h() { b.~B(); new (const_cast<B*>(&b)) const B; // undefined behavior } — end example]
21)21)
For example, before the dynamic initialization of an object with static storage duration ([basic.start.dynamic]).
22)22)
That is, an object for which a destructor will be called implicitly—upon exit from the block for an object with automatic storage duration, upon exit from the thread for an object with thread storage duration, or upon exit from the program for an object with static storage duration.

6.7.5 Indeterminate and erroneous values [basic.indet]

When storage for an object with automatic or dynamic storage duration is obtained, the bytes comprising the storage for the object have the following initial value:
  • If the object has dynamic storage duration, or is the object associated with a variable or function parameter whose first declaration is marked with the [[indeterminate]] attribute ([dcl.attr.indet]), the bytes have indeterminate values;
  • otherwise, the bytes have erroneous values, where each value is determined by the implementation independently of the state of the program.
If no initialization is performed for an object (including subobjects), such a byte retains its initial value until that value is replaced ([dcl.init.general], [expr.ass]).
If any bit in the value representation has an indeterminate value, the object has an indeterminate value; otherwise, if any bit in the value representation has an erroneous value, the object has an erroneous value ([conv.lval]).
[Note 1: 
Objects with static or thread storage duration are zero-initialized, see [basic.start.static].
— end note]
Except in the following cases, if an indeterminate value is produced by an evaluation, the behavior is undefined, and if an erroneous value is produced by an evaluation, the behavior is erroneous and the result of the evaluation is the value so produced but is not erroneous:
  • If an indeterminate or erroneous value of unsigned ordinary character type ([basic.fundamental]) or std​::​byte type ([cstddef.syn]) is produced by the evaluation of: then the result of the operation is an indeterminate value or that erroneous value, respectively.
  • If an indeterminate or erroneous value of unsigned ordinary character type or std​::​byte type is produced by the evaluation of the right operand of a simple assignment operator ([expr.ass]) whose first operand is an lvalue of unsigned ordinary character type or std​::​byte type, an indeterminate value or that erroneous value, respectively, replaces the value of the object referred to by the left operand.
  • If an indeterminate or erroneous value of unsigned ordinary character type is produced by the evaluation of the initialization expression when initializing an object of unsigned ordinary character type, that object is initialized to an indeterminate value or that erroneous value, respectively.
  • If an indeterminate value of unsigned ordinary character type or std​::​byte type is produced by the evaluation of the initialization expression when initializing an object of std​::​byte type, that object is initialized to an indeterminate value or that erroneous value, respectively.
Converting an indeterminate or erroneous value of unsigned ordinary character type or std​::​byte type produces an indeterminate or erroneous value, respectively.
In the latter case, the result of the conversion is the value of the converted operand.
[Example 1: int f(bool b) { unsigned char *c = new unsigned char; unsigned char d = *c; // OK, d has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if b is true } int g(bool b) { unsigned char c; unsigned char d = c; // no erroneous behavior, but d has an erroneous value assert(c == d); // holds, both integral promotions have erroneous behavior int e = d; // erroneous behavior return b ? d : 0; // erroneous behavior if b is true } void h() { int d1, d2; int e1 = d1; // erroneous behavior int e2 = d1; // erroneous behavior assert(e1 == e2); // holds assert(e1 == d1); // holds, erroneous behavior assert(e2 == d1); // holds, erroneous behavior std::memcpy(&d2, &d1, sizeof(int)); // no erroneous behavior, but d2 has an erroneous value assert(e1 == d2); // holds, erroneous behavior assert(e2 == d2); // holds, erroneous behavior } — end example]

6.7.6 Storage duration [basic.stc]

6.7.6.1 General [basic.stc.general]

The storage duration is the property of an object that defines the minimum potential lifetime of the storage containing the object.
The storage duration is determined by the construct used to create the object and is one of the following:
  • static storage duration
  • thread storage duration
  • automatic storage duration
  • dynamic storage duration
[Note 1: 
After the duration of a region of storage has ended, the use of pointers to that region of storage is limited ([basic.compound]).
— end note]
Static, thread, and automatic storage durations are associated with objects introduced by declarations ([basic.def]) and with temporary objects ([class.temporary]).
The dynamic storage duration is associated with objects created by a new-expression ([expr.new]) or with implicitly created objects ([intro.object]).
The storage duration categories apply to references as well.
The storage duration of subobjects and reference members is that of their complete object ([intro.object]).

6.7.6.2 Static storage duration [basic.stc.static]

All variables which have static storage duration.
The storage for these entities lasts for the duration of the program ([basic.start.static], [basic.start.term]).
If a variable with static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in [class.copy.elision].
[Note 1: 
The keyword static can be used to declare a block variable ([basic.scope.block]) with static storage duration; [stmt.dcl] and [basic.start.term] describe the initialization and destruction of such variables.
The keyword static applied to a class data member in a class definition gives the data member static storage duration ([class.static.data]).
— end note]

6.7.6.3 Thread storage duration [basic.stc.thread]

All variables declared with the thread_local keyword have thread storage duration.
The storage for these entities lasts for the duration of the thread in which they are created.
There is a distinct object or reference per thread, and use of the declared name refers to the entity associated with the current thread.
[Note 1: 
A variable with thread storage duration is initialized as specified in [basic.start.static], [basic.start.dynamic], and [stmt.dcl] and, if constructed, is destroyed on thread exit ([basic.start.term]).
— end note]

6.7.6.4 Automatic storage duration [basic.stc.auto]

Variables that belong to a block scope and are not explicitly declared static, thread_local, or extern have automatic storage duration.
The storage for such variables lasts until the block in which they are created exits.
[Note 1: 
These variables are initialized and destroyed as described in [stmt.dcl].
— end note]
Variables that belong to a parameter scope also have automatic storage duration.
The storage for a function parameter lasts until immediately after its destruction ([expr.call]).
If a variable with automatic storage duration has initialization or a destructor with side effects, an implementation shall not destroy it before the end of its block nor eliminate it as an optimization, even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in [class.copy.elision].

6.7.6.5 Dynamic storage duration [basic.stc.dynamic]

6.7.6.5.1 General [basic.stc.dynamic.general]

Objects can be created dynamically during program execution, using new-expressions ([expr.new]), and destroyed using delete-expressions ([expr.delete]).
A C++ implementation provides access to, and management of, dynamic storage via the global allocation functions operator new and operator new[] and the global deallocation functions operator delete and operator delete[].
[Note 1: 
The non-allocating forms described in [new.delete.placement] do not perform allocation or deallocation.
— end note]
The library provides default definitions for the global allocation and deallocation functions.
Some global allocation and deallocation functions are replaceable ([new.delete]); these are attached to the global module ([module.unit]).
A C++ program shall provide at most one definition of a replaceable allocation or deallocation function.
Any such function definition replaces the default version provided in the library ([replacement.functions]).
The following allocation and deallocation functions ([support.dynamic]) are implicitly declared in global scope in each translation unit of a program.
void* operator new(std::size_t); void* operator new(std::size_t, std::align_val_t); void operator delete(void*) noexcept; void operator delete(void*, std::size_t) noexcept; void operator delete(void*, std::align_val_t) noexcept; void operator delete(void*, std::size_t, std::align_val_t) noexcept; void* operator new[](std::size_t); void* operator new[](std::size_t, std::align_val_t); void operator delete[](void*) noexcept; void operator delete[](void*, std::size_t) noexcept; void operator delete[](void*, std::align_val_t) noexcept; void operator delete[](void*, std::size_t, std::align_val_t) noexcept;
These implicit declarations introduce only the function names operator new, operator new[], operator delete, and operator delete[].
[Note 2: 
The implicit declarations do not introduce the names std, std​::​size_t, std​::​align_val_t, or any other names that the library uses to declare these names.
Thus, a new-expression, delete-expression, or function call that refers to one of these functions without importing or including the header <new> or importing a C++ library module ([std.modules]) is well-formed.
However, referring to std or std​::​size_t or std​::​align_val_t is ill-formed unless a standard library declaration ([cstddef.syn], [new.syn], [std.modules]) of that name precedes ([basic.lookup.general]) the use of that name.
— end note]
Allocation and/or deallocation functions may also be declared and defined for any class ([class.free]).
If the behavior of an allocation or deallocation function does not satisfy the semantic constraints specified in [basic.stc.dynamic.allocation] and [basic.stc.dynamic.deallocation], the behavior is undefined.

6.7.6.5.2 Allocation functions [basic.stc.dynamic.allocation]

An allocation function that is not a class member function shall belong to the global scope and not have a name with internal linkage.
The return type shall be void*.
The first parameter shall have type std​::​size_t ([support.types]).
The first parameter shall not have an associated default argument ([dcl.fct.default]).
The value of the first parameter is interpreted as the requested size of the allocation.
An allocation function can be a function template.
Such a template shall declare its return type and first parameter as specified above (that is, template parameter types shall not be used in the return type and first parameter type).
Allocation function templates shall have two or more parameters.
An allocation function attempts to allocate the requested amount of storage.
If it is successful, it returns the address of the start of a block of storage whose length in bytes is at least as large as the requested size.
The order, contiguity, and initial value of storage allocated by successive calls to an allocation function are unspecified.
Even if the size of the space requested is zero, the request can fail.
If the request succeeds, the value returned by a replaceable allocation function is a non-null pointer value ([basic.compound]) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to a replaceable deallocation function.
Furthermore, for the library allocation functions in [new.delete.single] and [new.delete.array], p0 represents the address of a block of storage disjoint from the storage for any other object accessible to the caller.
The effect of indirecting through a pointer returned from a request for zero size is undefined.23
For an allocation function other than a reserved placement allocation function ([new.delete.placement]), the pointer returned on a successful call shall represent the address of storage that is aligned as follows:
  • If the allocation function takes an argument of type std​::​align_val_t, the storage will have the alignment specified by the value of this argument.
  • Otherwise, if the allocation function is named operator new[], the storage is aligned for any object that does not have new-extended alignment ([basic.align]) and is no larger than the requested size.
  • Otherwise, the storage is aligned for any object that does not have new-extended alignment and is of the requested size.
An allocation function that fails to allocate storage can invoke the currently installed new-handler function ([new.handler]), if any.
[Note 1: 
A program-supplied allocation function can obtain the currently installed new_handler using the std​::​get_new_handler function ([get.new.handler]).
— end note]
An allocation function that has a non-throwing exception specification ([except.spec]) indicates failure by returning a null pointer value.
Any other allocation function never returns a null pointer value and indicates failure only by throwing an exception ([except.throw]) of a type that would match a handler ([except.handle]) of type std​::​bad_alloc ([bad.alloc]).
A global allocation function is only called as the result of a new expression, or called directly using the function call syntax, or called indirectly to allocate storage for a coroutine state ([dcl.fct.def.coroutine]), or called indirectly through calls to the functions in the C++ standard library.
[Note 2: 
In particular, a global allocation function is not called to allocate storage for objects with static storage duration, for objects or references with thread storage duration, for objects of type std​::​type_info, or for an exception object.
— end note]
23)23)
The intent is to have operator new() implementable by calling std​::​malloc() or std​::​calloc(), so the rules are substantially the same.
C++ differs from C in requiring a zero request to return a non-null pointer.

6.7.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]

A deallocation function that is not a class member function shall belong to the global scope and not have a name with internal linkage.
A deallocation function is a destroying operator delete if it has at least two parameters and its second parameter is of type std​::​destroying_delete_t.
A destroying operator delete shall be a class member function named operator delete.
[Note 1: 
Array deletion cannot use a destroying operator delete.
— end note]
Each deallocation function shall return void.
If the function is a destroying operator delete declared in class type C, the type of its first parameter shall be C*; otherwise, the type of its first parameter shall be void*.
A deallocation function may have more than one parameter.
A usual deallocation function is a deallocation function whose parameters after the first are
  • optionally, a parameter of type std​::​destroying_delete_t, then
  • optionally, a parameter of type std​::​size_t,24 then
  • optionally, a parameter of type std​::​align_val_t.
A destroying operator delete shall be a usual deallocation function.
A deallocation function may be an instance of a function template.
Neither the first parameter nor the return type shall depend on a template parameter.
A deallocation function template shall have two or more function parameters.
A template instance is never a usual deallocation function, regardless of its signature.
If a deallocation function terminates by throwing an exception, the behavior is undefined.
The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect.
If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value ([basic.compound]), the deallocation function shall deallocate the storage referenced by the pointer, ending the duration of the region of storage.
24)24)
The global operator delete(void*, std​::​size_t) precludes use of an allocation function void operator new(std​::​size_t, std​::​size_t) as a placement allocation function ([diff.cpp11.basic]).

6.7.7 Temporary objects [class.temporary]

Temporary objects are created
  • when a prvalue is converted to an xvalue ([conv.rval]) and
  • when needed by the implementation to pass or return an object of trivially copyable type (see below).
Even when the creation of the temporary object is unevaluated ([expr.context]), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed.
[Note 1: 
This includes accessibility ([class.access]) and whether it is deleted, for the constructor selected and for the destructor.
However, in the special case of the operand of a decltype-specifier ([dcl.type.decltype]), no temporary is introduced, so the foregoing does not apply to such a prvalue.
— end note]
The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects.
[Note 2: 
Temporary objects are materialized:
— end note]
[Example 1: 
Consider the following code: class X { public: X(int); X(const X&); X& operator=(const X&); ~X(); }; class Y { public: Y(int); Y(Y&&); ~Y(); }; X f(X); Y g(Y); void h() { X a(1); X b = f(X(2)); Y c = g(Y(3)); a = f(a); }
X(2) is constructed in the space used to hold f()'s argument and Y(3) is constructed in the space used to hold g()'s argument.
Likewise, f()'s result is constructed directly in b and g()'s result is constructed directly in c.
On the other hand, the expression a = f(a) requires a temporary for the result of f(a), which is materialized so that the reference parameter of X​::​operator=(const X&) can bind to it.
— end example]
When an object of class type X is passed to or returned from a potentially-evaluated function call, if X has at least one eligible copy or move constructor ([special]), each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object.
The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the eligible trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object).
[Note 3: 
This latitude is granted to allow objects of class type to be passed to or returned from functions in registers.
— end note]
Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created.
This is true even if that evaluation ends in throwing an exception.
The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.
There are five contexts in which temporaries are destroyed at a different point than the end of the full-expression.
The first context is when a default constructor is called to initialize an element of an array with no corresponding initializer ([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 ([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.
The third context is when a reference binds to a temporary object.25
The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained through one of the following:
  • a temporary materialization conversion ([conv.rval]),
  • ( expression ), where expression is one of these expressions,
  • subscripting ([expr.sub]) of an array operand, where that operand is one of these expressions,
  • a class member access ([expr.ref]) using the . operator where the left operand is one of these expressions and the right operand designates a non-static data member of non-reference type,
  • a pointer-to-member operation ([expr.mptr.oper]) using the .* operator where the left operand is one of these expressions and the right operand is a pointer to data member of non-reference type,
  • a converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,
  • a conditional expression ([expr.cond]) that is a glvalue where the second or third operand is one of these expressions, or
  • a comma expression ([expr.comma]) that is a glvalue where the right operand is one of these expressions.
[Example 2: template<typename T> using id = T; int i = 1; int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as a const int& b = static_cast<const int&>(0); // temporary int has same lifetime as b int&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended — end example]
[Note 4: 
An explicit type conversion ([expr.type.conv], [expr.cast]) is interpreted as a sequence of elementary casts, covered above.
[Example 3: const int& x = (const int&)1; // temporary for value 1 has same lifetime as x — end example]
— end note]
[Note 5: 
If a temporary object has a reference member initialized by another temporary object, lifetime extension applies recursively to such a member's initializer.
[Example 4: struct S { const int& m; }; const S& s = S{1}; // both S and int temporaries have lifetime of s — end example]
— end note]
The exceptions to this lifetime rule are:
  • A temporary object bound to a reference parameter in a function call ([expr.call]) persists until the completion of the full-expression containing the call.
  • A temporary object bound to a reference element of an aggregate of class type initialized from a parenthesized expression-list ([dcl.init]) persists until the completion of the full-expression containing the expression-list.
  • A temporary bound to a reference in a new-initializer ([expr.new]) persists until the completion of the full-expression containing the new-initializer.
    [Note 6: 
    This might introduce a dangling reference.
    — end note]
    [Example 5: struct S { int mi; const std::pair<int,int>& mp; }; S a { 1, {2,3} }; S* p = new S{ 1, {2,3} }; // creates dangling reference — end example]
The fourth context is when a temporary object is created in the for-range-initializer of a range-based for statement.
If such a temporary object would otherwise be destroyed at the end of the for-range-initializer full-expression, the object persists for the lifetime of the reference initialized by the for-range-initializer.
The fifth context is when a temporary object is created in a structured binding declaration ([dcl.struct.bind]).
Any temporary objects introduced by the initializers for the variables with unique names are destroyed at the end of the structured binding declaration.
Let x and y each be either a temporary object whose lifetime is not extended, or a function parameter.
If the lifetimes of x and y end at the end of the same full-expression, and x is initialized before y, then the destruction of y is sequenced before that of x.
If the lifetime of two or more temporaries with lifetimes extending beyond the full-expressions in which they were created ends at the same point, these temporaries are destroyed at that point in the reverse order of the completion of their construction.
In addition, the destruction of such temporaries shall take into account the ordering of destruction of objects with static, thread, or automatic storage duration ([basic.stc.static], [basic.stc.thread], [basic.stc.auto]); that is, if obj1 is an object with the same storage duration as the temporary and created before the temporary is created the temporary shall be destroyed before obj1 is destroyed; if obj2 is an object with the same storage duration as the temporary and created after the temporary is created the temporary shall be destroyed after obj2 is destroyed.
[Example 6: struct S { S(); S(int); friend S operator+(const S&, const S&); ~S(); }; S obj1; const S& cr = S(16)+S(23); S obj2;
The expression S(16) + S(23) creates three temporaries: a first temporary T1 to hold the result of the expression S(16), a second temporary T2 to hold the result of the expression S(23), and a third temporary T3 to hold the result of the addition of these two expressions.
The temporary T3 is then bound to the reference cr.
It is unspecified whether T1 or T2 is created first.
On an implementation where T1 is created before T2, T2 shall be destroyed before T1.
The temporaries T1 and T2 are bound to the reference parameters of operator+; these temporaries are destroyed at the end of the full-expression containing the call to operator+.
The temporary T3 bound to the reference cr is destroyed at the end of cr's lifetime, that is, at the end of the program.
In addition, the order in which T3 is destroyed takes into account the destruction order of other objects with static storage duration.
That is, because obj1 is constructed before T3, and T3 is constructed before obj2, obj2 shall be destroyed before T3, and T3 shall be destroyed before obj1.
— end example]
25)25)
The same rules apply to initialization of an initializer_list object ([dcl.init.list]) with its underlying temporary array.

6.8 Types [basic.types]

6.8.1 General [basic.types.general]

[Note 1: 
[basic.types] and the subclauses thereof impose requirements on implementations regarding the representation of types.
There are two kinds of types: fundamental types and compound types.
Types describe objects, references, or functions.
— end note]
For any object (other than a potentially-overlapping subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std​::​byte ([cstddef.syn]).26
If the content of that array is copied back into the object, the object shall subsequently hold its original value.
[Example 1: constexpr std::size_t N = sizeof(T); char buf[N]; T obj; // obj initialized to its original value std::memcpy(buf, &obj, N); // between these two calls to std​::​memcpy, obj might be modified std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type holds its original value — end example]
For two distinct objects obj1 and obj2 of trivially copyable type T, where neither obj1 nor obj2 is a potentially-overlapping subobject, if the underlying bytes ([intro.memory]) making up obj1 are copied into obj2,27 obj2 shall subsequently hold the same value as obj1.
[Example 2: T* t1p; T* t2p; // provided that t2p points to an initialized object ... std::memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of trivially copyable type in *t1p contains // the same value as the corresponding subobject in *t2p — end example]
The object representation of a complete object type T is the sequence of N unsigned char objects taken up by a non-bit-field complete object of type T, where N equals sizeof(T).
The value representation of a type T is the set of bits in the object representation of T that participate in representing a value of type T.
The object and value representation of a non-bit-field complete object of type T are the bytes and bits, respectively, of the object corresponding to the object and value representation of its type.
The object representation of a bit-field object is the sequence of N bits taken up by the object, where N is the width of the bit-field ([class.bit]).
The value representation of a bit-field object is the set of bits in the object representation that participate in representing its value.
Bits in the object representation of a type or object that are not part of the value representation are padding bits.
For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.28
A class that has been declared but not defined, an enumeration type in certain contexts ([dcl.enum]), or an array of unknown bound or of incomplete element type, is an incompletely-defined object type.29
Incompletely-defined object types and cv void are incomplete types ([basic.fundamental]).
[Note 2: 
Objects cannot be defined to have an incomplete type ([basic.def]).
— end note]
A class type (such as “class X”) can be incomplete at one point in a translation unit and complete later on; the type “class X” is the same type at both points.
The declared type of an array object can be an array of incomplete class type and therefore incomplete; if the class type is completed later on in the translation unit, the array type becomes complete; the array type at those two points is the same type.
The declared type of an array object can be an array of unknown bound and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types.
[Note 3: 
The type of a pointer or reference to array of unknown bound permanently points to or refers to an incomplete type.
An array of unknown bound named by a typedef declaration permanently refers to an incomplete type.
In either case, the array type cannot be completed.
— end note]
[Example 3: class X; // X is an incomplete type extern X* xp; // xp is a pointer to an incomplete type extern int arr[]; // the type of arr is incomplete typedef int UNKA[]; // UNKA is an incomplete type UNKA* arrp; // arrp is a pointer to an incomplete type UNKA** arrpp; void foo() { xp++; // error: X is incomplete arrp++; // error: incomplete type arrpp++; // OK, sizeof UNKA* is known } struct X { int i; }; // now X is a complete type int arr[10]; // now the type of arr is complete X x; void bar() { xp = &x; // OK; type is “pointer to X'' arrp = &arr; // OK; qualification conversion ([conv.qual]) xp++; // OK, X is complete arrp++; // error: UNKA can't be completed } — end example]
[Note 4: 
The rules for declarations and expressions describe in which contexts incomplete types are prohibited.
— end note]
An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not cv void.
Arithmetic types ([basic.fundamental]), enumeration types, pointer types, pointer-to-member types ([basic.compound]), std​::​nullptr_t, and cv-qualified versions of these types are collectively called scalar types.
Scalar types, trivially copyable class types ([class.prop]), arrays of such types, and cv-qualified versions of these types are collectively called trivially copyable types.
Scalar types, standard-layout class types ([class.prop]), arrays of such types, and cv-qualified versions of these types are collectively called standard-layout types.
Scalar types, implicit-lifetime class types ([class.prop]), array types, and cv-qualified versions of these types are collectively called implicit-lifetime types.
A type is a literal type if it is:
  • cv void; or
  • a scalar type; or
  • a reference type; or
  • an array of literal type; or
  • a possibly cv-qualified class type that has all of the following properties:
    • it has a constexpr destructor ([dcl.constexpr]),
    • all of its non-static non-variant data members and base classes are of non-volatile literal types, and
    • it
      • is a closure type ([expr.prim.lambda.closure]),
      • is an aggregate union type that has either no variant members or at least one variant member of non-volatile literal type,
      • is a non-union aggregate type for which each of its anonymous union members satisfies the above requirements for an aggregate union type, or
      • has at least one constexpr constructor or constructor template (possibly inherited ([namespace.udecl]) from a base class) that is not a copy or move constructor.
[Note 5: 
A literal type is one for which it might be possible to create an object within a constant expression.
It is not a guarantee that it is possible to create such an object, nor is it a guarantee that any object of that type will be usable in a constant expression.
— end note]
Two types cv1 T1 and cv2 T2 are layout-compatible types if T1 and T2 are the same type, layout-compatible enumerations, or layout-compatible standard-layout class types.
26)26)
By using, for example, the library functions ([headers]) std​::​memcpy or std​::​memmove.
27)27)
By using, for example, the library functions ([headers]) std​::​memcpy or std​::​memmove.
28)28)
The intent is that the memory model of C++ is compatible with that of the C programming language.
29)29)
The size and layout of an instance of an incompletely-defined object type is unknown.

6.8.2 Fundamental types [basic.fundamental]

There are five standard signed integer types: signed char”, “short int”, “int”, “long int”, and “long long int.
In this list, each type provides at least as much storage as those preceding it in the list.
There may also be implementation-defined extended signed integer types.
The standard and extended signed integer types are collectively called signed integer types.
The range of representable values for a signed integer type is to (inclusive), where N is called the width of the type.
[Note 1: 
Plain ints are intended to have the natural width suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs.
— end note]
For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: unsigned char”, “unsigned short int”, “unsigned int”, “unsigned long int”, and “unsigned long long int.
Likewise, for each of the extended signed integer types, there exists a corresponding extended unsigned integer type.
The standard and extended unsigned integer types are collectively called unsigned integer types.
An unsigned integer type has the same width N as the corresponding signed integer type.
The range of representable values for the unsigned type is 0 to (inclusive); arithmetic for the unsigned type is performed modulo .
[Note 2: 
Unsigned arithmetic does not overflow.
Overflow for signed arithmetic yields undefined behavior ([expr.pre]).
— end note]
An unsigned integer type has the same object representation, value representation, and alignment requirements ([basic.align]) as the corresponding signed integer type.
For each value x of a signed integer type, the value of the corresponding unsigned integer type congruent to x modulo has the same value of corresponding bits in its value representation.30
[Example 1: 
The value of a signed integer type has the same representation as the largest value of the corresponding unsigned type.
— end example]
Table 14 — Minimum width [tab:basic.fundamental.width]
Type
Minimum width N
signed char
8
short int
16
int
16
long int
32
long long int
64
The width of each standard signed integer type shall not be less than the values specified in Table 14.
The value representation of a signed or unsigned integer type comprises N bits, where N is the respective width.
Each set of values for any padding bits ([basic.types.general]) in the object representation are alternative representations of the value specified by the value representation.
[Note 3: 
Padding bits have unspecified value, but cannot cause traps.
In contrast, see ISO/IEC 9899:2018 6.2.6.2.
— end note]
[Note 4: 
The signed and unsigned integer types satisfy the constraints given in ISO/IEC 9899:2018 5.2.4.2.1.
— end note]
Except as specified above, the width of a signed or unsigned integer type is implementation-defined.
Each value x of an unsigned integer type with width N has a unique representation , where each coefficient is either 0 or 1; this is called the base-2 representation of x.
The base-2 representation of a value of signed integer type is the base-2 representation of the congruent value of the corresponding unsigned integer type.
The standard signed integer types and standard unsigned integer types are collectively called the standard integer types, and the extended signed integer types and extended unsigned integer types are collectively called the extended integer types.
A fundamental type specified to have a signed or unsigned integer type as its underlying type has the same object representation, value representation, alignment requirements ([basic.align]), and range of representable values as the underlying type.
Further, each value has the same representation in both types.
Type char is a distinct type that has an implementation-defined choice of “signed char” or “unsigned char” as its underlying type.
The three types char, signed char, and unsigned char are collectively called ordinary character types.
The ordinary character types and char8_t are collectively called narrow character types.
For narrow character types, each possible bit pattern of the object representation represents a distinct value.
[Note 5: 
This requirement does not hold for other types.
— end note]
[Note 6: 
A bit-field of narrow character type whose width is larger than the width of that type has padding bits; see [basic.types.general].
— end note]
Type wchar_t is a distinct type that has an implementation-defined signed or unsigned integer type as its underlying type.
Type char8_t denotes a distinct type whose underlying type is unsigned char.
Types char16_t and char32_t denote distinct types whose underlying types are uint_least16_t and uint_least32_t, respectively, in <cstdint>.
Type bool is a distinct type that has the same object representation, value representation, and alignment requirements as an implementation-defined unsigned integer type.
The values of type bool are true and false.
[Note 7: 
There are no signed, unsigned, short, or long bool types or values.
— end note]
The types char, wchar_t, char8_t, char16_t, and char32_t are collectively called character types.
The character types, bool, the signed and unsigned integer types, and cv-qualified versions ([basic.type.qualifier]) thereof, are collectively termed integral types.
A synonym for integral type is integer type.
[Note 8: 
Enumerations ([dcl.enum]) are not integral; however, unscoped enumerations can be promoted to integral types as specified in [conv.prom].
— end note]
The three distinct types float, double, and long double can represent floating-point numbers.
The type double provides at least as much precision as float, and the type long double provides at least as much precision as double.
The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double.
The types float, double, and long double, and cv-qualified versions ([basic.type.qualifier]) thereof, are collectively termed standard floating-point types.
An implementation may also provide additional types that represent floating-point values and define them (and cv-qualified versions thereof) to be extended floating-point types.
The standard and extended floating-point types are collectively termed floating-point types.
[Note 9: 
Any additional implementation-specific types representing floating-point values that are not defined by the implementation to be extended floating-point types are not considered to be floating-point types, and this document imposes no requirements on them or their interactions with floating-point types.
— end note]
Except as specified in [basic.extended.fp], the object and value representations and accuracy of operations of floating-point types are implementation-defined.
The minimum range of representable values for a floating-point type is the most negative finite floating-point number representable in that type through the most positive finite floating-point number representable in that type.
In addition, if negative infinity is representable in a type, the range of that type is extended to all negative real numbers; likewise, if positive infinity is representable in a type, the range of that type is extended to all positive real numbers.
[Note 10: 
Since negative and positive infinity are representable in ISO/IEC 60559 formats, all real numbers lie within the range of representable values of a floating-point type adhering to ISO/IEC 60559.
— end note]
Integral and floating-point types are collectively termed arithmetic types.
[Note 11: 
Properties of the arithmetic types, such as their minimum and maximum representable value, can be queried using the facilities in the standard library headers <limits>, <climits>, and <cfloat>.
— end note]
A type cv void is an incomplete type that cannot be completed; such a type has an empty set of values.
It is used as the return type for functions that do not return a value.
An expression of type cv void shall be used only as
The types denoted by cv std​::​nullptr_t are distinct types.
A prvalue of type std​::​nullptr_t is a null pointer constant ([conv.ptr]).
Such values participate in the pointer and the pointer-to-member conversions ([conv.ptr], [conv.mem]).
sizeof(std​::​nullptr_t) shall be equal to sizeof(void*).
The types described in this subclause are called fundamental types.
[Note 12: 
Even if the implementation defines two or more fundamental types to have the same value representation, they are nevertheless different types.
— end note]
30)30)
This is also known as two's complement representation.

6.8.3 Optional extended floating-point types [basic.extended.fp]

If the implementation supports an extended floating-point type ([basic.fundamental]) whose properties are specified by the ISO/IEC 60559 floating-point interchange format binary16, then the typedef-name std​::​float16_t is defined in the header <stdfloat> and names such a type, the macro __STDCPP_FLOAT16_T__ is defined ([cpp.predefined]), and the floating-point literal suffixes f16 and F16 are supported ([lex.fcon]).
If the implementation supports an extended floating-point type whose properties are specified by the ISO/IEC 60559 floating-point interchange format binary32, then the typedef-name std​::​float32_t is defined in the header <stdfloat> and names such a type, the macro __STDCPP_FLOAT32_T__ is defined, and the floating-point literal suffixes f32 and F32 are supported.
If the implementation supports an extended floating-point type whose properties are specified by the ISO/IEC 60559 floating-point interchange format binary64, then the typedef-name std​::​float64_t is defined in the header <stdfloat> and names such a type, the macro __STDCPP_FLOAT64_T__ is defined, and the floating-point literal suffixes f64 and F64 are supported.
If the implementation supports an extended floating-point type whose properties are specified by the ISO/IEC 60559 floating-point interchange format binary128, then the typedef-name std​::​float128_t is defined in the header <stdfloat> and names such a type, the macro __STDCPP_FLOAT128_T__ is defined, and the floating-point literal suffixes f128 and F128 are supported.
If the implementation supports an extended floating-point type with the properties, as specified by ISO/IEC 60559, of radix (b) of 2, storage width in bits (k) of 16, precision in bits (p) of 8, maximum exponent (emax) of 127, and exponent field width in bits (w) of 8, then the typedef-name std​::​bfloat16_t is defined in the header <stdfloat> and names such a type, the macro __STDCPP_BFLOAT16_T__ is defined, and the floating-point literal suffixes bf16 and BF16 are supported.
[Note 1: 
A summary of the parameters for each type is given in Table 15.
The precision p includes the implicit 1 bit at the beginning of the significand, so the storage used for the significand is bits.
ISO/IEC 60559 does not assign a name for a type having the parameters specified for std​::​bfloat16_t.
— end note]
Table 15 — Properties of named extended floating-point types [tab:basic.extended.fp]
Parameter
float16_t
float32_t
float64_t
float128_t
bfloat16_t
ISO/IEC 60559 name
binary16
binary32
binary64
binary128
k, storage width in bits
16
32
64
128
16
p, precision in bits
11
24
53
113
8
emax, maximum exponent
15
127
1023
16383
127
w, exponent field width in bits
5
8
11
15
8
Recommended practice: Any names that the implementation provides for the extended floating-point types described in this subsection that are in addition to the names defined in the <stdfloat> header should be chosen to increase compatibility and interoperability with the interchange types _Float16, _Float32, _Float64, and _Float128 defined in ISO/IEC TS 18661-3 and with future versions of ISO/IEC 9899.

6.8.4 Compound types [basic.compound]

Compound types can be constructed in the following ways:
These methods of constructing types can be applied recursively; restrictions are mentioned in [dcl.meaning].
Constructing a type such that the number of bytes in its object representation exceeds the maximum value representable in the type std​::​size_t ([support.types]) is ill-formed.
The type of a pointer to cv void or a pointer to an object type is called an object pointer type.
[Note 1: 
A pointer to void does not have a pointer-to-object type, however, because void is not an object type.
— end note]
The type of a pointer that can designate a function is called a function pointer type.
A pointer to an object of type T is referred to as a “pointer to T.
[Example 1: 
A pointer to an object of type int is referred to as “pointer to int” and a pointer to an object of class X is called a “pointer to X.
— end example]
Except for pointers to static members, text referring to “pointers” does not apply to pointers to members.
Pointers to incomplete types are allowed although there are restrictions on what can be done with them ([basic.types.general]).
Every value of pointer type is one of the following:
A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object32 or the first byte in memory after the end of the storage occupied by the object, respectively.
[Note 2: 
A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type, even if the unrelated object is located at that address.
— end note]
For purposes of pointer arithmetic ([expr.add]) and comparison ([expr.rel], [expr.eq]), a pointer past the end of the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical array element n of x, and an object of type T that is not an array element is considered to belong to an array with one element of type T.
The value representation of pointer types is implementation-defined.
Pointers to layout-compatible types shall have the same value representation and alignment requirements ([basic.align]).
[Note 3: 
Pointers to over-aligned types have no special representation, but their range of valid values is restricted by the extended alignment requirement.
— end note]
A pointer value P is valid in the context of an evaluation E if P is a pointer to function or a null pointer value, or if it is a pointer to or past the end of an object O and E happens before the end of the duration of the region of storage for O.
If a pointer value P is used in an evaluation E and P is not valid in the context of E, then the behavior is undefined if E is an indirection ([expr.unary.op]) or an invocation of a deallocation function ([basic.stc.dynamic.deallocation]), and implementation-defined otherwise.33
[Note 4: 
P can be valid in the context of E even if it points to a type unrelated to that of O or if O is not within its lifetime, although further restrictions apply to such pointer values ([basic.life], [basic.lval], [expr.add]).
— end note]
Two objects a and b are pointer-interconvertible if
  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object ([class.union]), or
  • one is a standard-layout class object and the other is the first non-static data member of that object or any base class subobject of that object ([class.mem]), or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast ([expr.reinterpret.cast]).
[Note 5: 
An array object and its first element are not pointer-interconvertible, even though they have the same address.
— end note]
A byte of storage b is reachable through a pointer value that points to an object x if there is an object y, pointer-interconvertible with x, such that b is within the storage occupied by y, or the immediately-enclosing array object if y is an array element.
A pointer to cv void can be used to point to objects of unknown type.
Such a pointer shall be able to hold any object pointer.
An object of type “pointer to cv void” shall have the same representation and alignment requirements as an object of type “pointer to cv char.
31)31)
Static class members are objects or functions, and pointers to them are ordinary pointers to objects or functions.
32)32)
For an object that is not within its lifetime, this is the first byte in memory that it will occupy or used to occupy.
33)33)
Some implementations might define that copying such a pointer value causes a system-generated runtime fault.

6.8.5 CV-qualifiers [basic.type.qualifier]

Each type other than a function or reference type is part of a group of four distinct, but related, types: a cv-unqualified version, a const-qualified version, a volatile-qualified version, and a const-volatile-qualified version.
The types in each such group shall have the same representation and alignment requirements ([basic.align]).34
A function or reference type is always cv-unqualified.
  • A const object is an object of type const T or a non-mutable subobject of a const object.
  • A volatile object is an object of type volatile T or a subobject of a volatile object.
  • A const volatile object is an object of type const volatile T, a non-mutable subobject of a const volatile object, a const subobject of a volatile object, or a non-mutable volatile subobject of a const object.
[Note 1: 
The type of an object ([intro.object]) includes the cv-qualifiers specified in the decl-specifier-seq ([dcl.spec]), declarator ([dcl.decl]), type-id ([dcl.name]), or new-type-id ([expr.new]) when the object is created.
— end note]
Except for array types, a compound type ([basic.compound]) is not cv-qualified by the cv-qualifiers (if any) of the types from which it is compounded.
An array type whose elements are cv-qualified is also considered to have the same cv-qualifications as its elements.
[Note 2: 
Cv-qualifiers applied to an array type attach to the underlying element type, so the notation “cv T”, where T is an array type, refers to an array whose elements are so-qualified ([dcl.array]).
— end note]
[Example 1: typedef char CA[5]; typedef const char CC; CC arr1[5] = { 0 }; const CA arr2 = { 0 };
The type of both arr1 and arr2 is “array of 5 const char”, and the array type is considered to be const-qualified.
— end example]
[Note 3: 
See [dcl.fct] and [over.match.funcs] regarding function types that have cv-qualifiers.
— end note]
There is a partial ordering on cv-qualifiers, so that a type can be said to be more cv-qualified than another.
Table 16 shows the relations that constitute this ordering.
Table 16 — Relations on const and volatile[tab:basic.type.qualifier.rel]
no cv-qualifier
<
const
no cv-qualifier
<
volatile
no cv-qualifier
<
const volatile
const
<
const volatile
volatile
<
const volatile
In this document, the notation cv (or cv1, cv2, etc.)
, used in the description of types, represents an arbitrary set of cv-qualifiers, i.e., one of {const}, {volatile}, {const, volatile}, or the empty set.
For a type cv T, the top-level cv-qualifiers of that type are those denoted by cv.
[Example 2: 
The type corresponding to the type-id const int& has no top-level cv-qualifiers.
The type corresponding to the type-id volatile int * const has the top-level cv-qualifier const.
For a class type C, the type corresponding to the type-id void (C​::​* volatile)(int) const has the top-level cv-qualifier volatile.
— end example]
34)34)
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and non-static data members of unions.

6.8.6 Conversion ranks [conv.rank]

Every integer type has an integer conversion rank defined as follows:
  • No two signed integer types other than char and signed char (if char is signed) have the same rank, even if they have the same representation.
  • The rank of a signed integer type is greater than the rank of any signed integer type with a smaller width.
  • The rank of long long int is greater than the rank of long int, which is greater than the rank of int, which is greater than the rank of short int, which is greater than the rank of signed char.
  • The rank of any unsigned integer type equals the rank of the corresponding signed integer type.
  • The rank of any standard integer type is greater than the rank of any extended integer type with the same width.
  • The rank of char equals the rank of signed char and unsigned char.
  • The rank of bool is less than the rank of all standard integer types.
  • The ranks of char8_t, char16_t, char32_t, and wchar_t equal the ranks of their underlying types ([basic.fundamental]).
  • The rank of any extended signed integer type relative to another extended signed integer type with the same width is implementation-defined, but still subject to the other rules for determining the integer conversion rank.
  • For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has greater rank than T3, then T1 has greater rank than T3.
[Note 1: 
The integer conversion rank is used in the definition of the integral promotions ([conv.prom]) and the usual arithmetic conversions ([expr.arith.conv]).
— end note]
Every floating-point type has a floating-point conversion rank defined as follows:
  • The rank of a floating point type T is greater than the rank of any floating-point type whose set of values is a proper subset of the set of values of T.
  • The rank of long double is greater than the rank of double, which is greater than the rank of float.
  • Two extended floating-point types with the same set of values have equal ranks.
  • An extended floating-point type with the same set of values as exactly one cv-unqualified standard floating-point type has a rank equal to the rank of that standard floating-point type.
  • An extended floating-point type with the same set of values as more than one cv-unqualified standard floating-point type has a rank equal to the rank of double.
    [Note 2: 
    The treatment of std​::​float64_t differs from that of the analoguous _Float64 in C, for example on platforms where all of long double, double, and std​::​float64_t have the same set of values (see ISO/IEC 9899:2024 H.4.2).
    — end note]
[Note 3: 
The conversion ranks of floating-point types T1 and T2 are unordered if the set of values of T1 is neither a subset nor a superset of the set of values of T2.
This can happen when one type has both a larger range and a lower precision than the other.
— end note]
Floating-point types that have equal floating-point conversion ranks are ordered by floating-point conversion subrank.
The subrank forms a total order among types with equal ranks.
The types std​::​float16_t, std​::​float32_t, std​::​float64_t, and std​::​float128_t ([stdfloat.syn]) have a greater conversion subrank than any standard floating-point type with equal conversion rank.
Otherwise, the conversion subrank order is implementation-defined.
[Note 4: 
The floating-point conversion rank and subrank are used in the definition of the usual arithmetic conversions ([expr.arith.conv]).
— end note]

6.9 Program execution [basic.exec]

6.9.1 Sequential execution [intro.execution]

An instance of each object with automatic storage duration is associated with each entry into its block.
Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function, suspension of a coroutine ([expr.await]), or receipt of a signal).
A constituent expression is defined as follows:
[Example 1: struct A { int x; }; struct B { int y; struct A a; }; B b = { 5, { 1+1 } };
The constituent expressions of the initializer used for the initialization of b are 5 and 1+1.
— end example]
The immediate subexpressions of an expression E are
A subexpression of an expression E is an immediate subexpression of E or a subexpression of an immediate subexpression of E.
[Note 1: 
Expressions appearing in the compound-statement of a lambda-expression are not subexpressions of the lambda-expression.
— end note]
The potentially-evaluated subexpressions of an expression, conversion, or initializer E are
  • the constituent expressions of E and
  • the subexpressions thereof that are not subexpressions of a nested unevaluated operand ([expr.context]).
A full-expression is
If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.
Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.
For an initializer, performing the initialization of the entity (including evaluating default member initializers of an aggregate) is also considered part of the full-expression.
[Example 2: struct S { S(int i): I(i) { } // full-expression is initialization of I int& v() { return I; } ~S() noexcept(false) { } private: int I; }; S s1(1); // full-expression comprises call of S​::​S(int) void f() { S s2 = 2; // full-expression comprises call of S​::​S(int) if (S(3).v()) // full-expression includes lvalue-to-rvalue and int to bool conversions, // performed before temporary is deleted at end of full-expression { } bool b = noexcept(S(4)); // exception specification of destructor of S considered for noexcept // full-expression is destruction of s2 at end of block } struct B { B(S = S(0)); }; B b[2] = { B(), B() }; // full-expression is the entire initialization // including the destruction of temporaries — end example]
[Note 2: 
The evaluation of a full-expression can include the evaluation of subexpressions that are not lexically part of the full-expression.
For example, subexpressions involved in evaluating default arguments ([dcl.fct.default]) are considered to be created in the expression that calls the function, not the expression that defines the default argument.
— end note]
Reading an object designated by a volatile glvalue ([basic.lval]), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.
Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects.
When a call to a library I/O function returns or an access through a volatile glvalue is evaluated, the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.
Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread ([intro.multithread]), which induces a partial order among those evaluations.
Given any two evaluations A and B, if A is sequenced before B (or, equivalently, B is sequenced after A), then the execution of A shall precede the execution of B.
If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced.
[Note 3: 
The execution of unsequenced evaluations can overlap.
— end note]
Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which.
[Note 4: 
Indeterminately sequenced evaluations cannot overlap, but either can be executed first.
— end note]
An expression X is said to be sequenced before an expression Y if every value computation and every side effect associated with the expression X is sequenced before every value computation and every side effect associated with the expression Y.
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.35
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
[Note 5: 
In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.
— end note]
The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
The behavior is undefined if
  • a side effect on a memory location ([intro.memory]) or
  • starting or ending the lifetime of an object in a memory location
is unsequenced relative to
  • another side effect on the same memory location,
  • starting or ending the lifetime of an object occupying storage that overlaps with the memory location, or
  • a value computation using the value of any object in the same memory location,
and the two evaluations are not potentially concurrent ([intro.multithread]).
[Note 6: 
Starting the lifetime of an object in a memory location can end the lifetime of objects in other memory locations ([basic.life]).
— end note]
[Note 7: 
The next subclause imposes similar, but more complex restrictions on potentially concurrent computations.
— end note]
[Example 3: void g(int i) { i = 7, i++, i++; // i becomes 9 i = i++ + 1; // the value of i is incremented i = i++ + i; // undefined behavior i = i + 1; // the value of i is incremented union U { int x, y; } u; (u.x = 1, 0) + (u.y = 2, 0); // undefined behavior } — end example]
When invoking a function (whether or not the function is inline), every argument expression and the postfix expression designating the called function are sequenced before every expression or statement in the body of the called function.
For each F, each evaluation that does not occur within F but is evaluated on the same thread and as part of the same signal handler (if any) is either sequenced before all evaluations that occur within F or sequenced after all evaluations that occur within F;36 if F invokes or resumes a coroutine ([expr.await]), only evaluations subsequent to the previous suspension (if any) and prior to the next suspension (if any) are considered to occur within F.
Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit.
[Example 4: 
Evaluation of a new-expression invokes one or more allocation and constructor functions; see [expr.new].
For another example, invocation of a conversion function ([class.conv.fct]) can arise in contexts in which no function call syntax appears.
— end example]
The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, regardless of the syntax of the expression that calls the function.
If a signal handler is executed as a result of a call to the std​::​raise function, then the execution of the handler is sequenced after the invocation of the std​::​raise function and before its return.
[Note 8: 
When a signal is received for another reason, the execution of the signal handler is usually unsequenced with respect to the rest of the program.
— end note]
35)35)
As specified in [class.temporary], after a full-expression is evaluated, a sequence of zero or more invocations of destructor functions for temporary objects takes place, usually in reverse order of the construction of each temporary object.
36)36)
In other words, function executions do not interleave with each other.

6.9.2 Multi-threaded executions and data races [intro.multithread]

6.9.2.1 General [intro.multithread.general]

A thread of execution (also known as a thread) is a single flow of control within a program, including the initial invocation of a specific top-level function, and recursively including every function invocation subsequently executed by the thread.
[Note 1: 
When one thread creates another, the initial call to the top-level function of the new thread is executed by the new thread, not by the creating thread.
— end note]
Every thread in a program can potentially access every object and function in a program.37
Under a hosted implementation, a C++ program can have more than one thread running concurrently.
The execution of each thread proceeds as defined by the remainder of this document.
The execution of the entire program consists of an execution of all of its threads.
[Note 2: 
Usually the execution can be viewed as an interleaving of all its threads.
However, some kinds of atomic operations, for example, allow executions inconsistent with a simple interleaving, as described below.
— end note]
Under a freestanding implementation, it is implementation-defined whether a program can have more than one thread of execution.
For a signal handler that is not executed as a result of a call to the std​::​raise function, it is unspecified which thread of execution contains the signal handler invocation.
37)37)
An object with automatic or thread storage duration ([basic.stc]) is associated with one specific thread, and can be accessed by a different thread only indirectly through a pointer or reference ([basic.compound]).

6.9.2.2 Data races [intro.races]

The value of an object visible to a thread T at a particular point is the initial value of the object, a value assigned to the object by T, or a value assigned to the object by another thread, according to the rules below.
[Note 1: 
In some cases, there might instead be undefined behavior.
Much of this subclause is motivated by the desire to support atomic operations with explicit and detailed visibility constraints.
However, it also implicitly supports a simpler view for more restricted programs.
— end note]
Two expression evaluations conflict if one of them and the other one
  • reads or modifies the same memory location or
  • starts or ends the lifetime of an object occupying storage that overlaps with the memory location.
[Note 2: 
A modification can still conflict even if it does not alter the value of any bits.
— end note]
The library defines a number of atomic operations ([atomics]) and operations on mutexes ([thread]) that are specially identified as synchronization operations.
These operations play a special role in making assignments in one thread visible to another.
A synchronization operation on one or more memory locations is either a consume operation, an acquire operation, a release operation, or both an acquire and release operation.
A synchronization operation without an associated memory location is a fence and can be either an acquire fence, a release fence, or both an acquire and release fence.
In addition, there are relaxed atomic operations, which are not synchronization operations, and atomic read-modify-write operations, which have special characteristics.
[Note 3: 
For example, a call that acquires a mutex will perform an acquire operation on the locations comprising the mutex.
Correspondingly, a call that releases the same mutex will perform a release operation on those same locations.
Informally, performing a release operation on A forces prior side effects on other memory locations to become visible to other threads that later perform a consume or an acquire operation on A.
“Relaxed” atomic operations are not synchronization operations even though, like synchronization operations, they cannot contribute to data races.
— end note]
All modifications to a particular atomic object M occur in some particular total order, called the modification order of M.
[Note 4: 
There is a separate order for each atomic object.
There is no requirement that these can be combined into a single total order for all objects.
In general this will be impossible since different threads can observe modifications to different objects in inconsistent orders.
— end note]
A release sequence headed by a release operation A on an atomic object M is a maximal contiguous sub-sequence of side effects in the modification order of M, where the first operation is A, and every subsequent operation is an atomic read-modify-write operation.
Certain library calls synchronize with other library calls performed by another thread.
For example, an atomic store-release synchronizes with a load-acquire that takes its value from the store ([atomics.order]).
[Note 5: 
Except in the specified cases, reading a later value does not necessarily ensure visibility as described below.
Such a requirement would sometimes interfere with efficient implementation.
— end note]
[Note 6: 
The specifications of the synchronization operations define when one reads the value written by another.
For atomic objects, the definition is clear.
All operations on a given mutex occur in a single total order.
Each mutex acquisition “reads the value written” by the last mutex release.
— end note]
An evaluation A carries a dependency to an evaluation B if
  • the value of A is used as an operand of B, unless: or
  • A writes a scalar object or bit-field M, B reads the value written by A from M, and A is sequenced before B, or
  • for some evaluation X, A carries a dependency to X, and X carries a dependency to B.
[Note 7: 
“Carries a dependency to” is a subset of “is sequenced before”, and is similarly strictly intra-thread.
— end note]
An evaluation A is dependency-ordered before an evaluation B if
  • A performs a release operation on an atomic object M, and, in another thread, B performs a consume operation on M and reads the value written by A, or
  • for some evaluation X, A is dependency-ordered before X and X carries a dependency to B.
[Note 8: 
The relation “is dependency-ordered before” is analogous to “synchronizes with”, but uses release/consume in place of release/acquire.
— end note]
An evaluation A inter-thread happens before an evaluation B if
  • A synchronizes with B, or
  • A is dependency-ordered before B, or
  • for some evaluation X
    • A synchronizes with X and X is sequenced before B, or
    • A is sequenced before X and X inter-thread happens before B, or
    • A inter-thread happens before X and X inter-thread happens before B.
[Note 9: 
The “inter-thread happens before” relation describes arbitrary concatenations of “sequenced before”, “synchronizes with” and “dependency-ordered before” relationships, with two exceptions.
The first exception is that a concatenation never ends with “dependency-ordered before” followed by “sequenced before”.
The reason for this limitation is that a consume operation participating in a “dependency-ordered before” relationship provides ordering only with respect to operations to which this consume operation actually carries a dependency.
The reason that this limitation applies only to the end of such a concatenation is that any subsequent release operation will provide the required ordering for a prior consume operation.
The second exception is that a concatenation never consist entirely of “sequenced before”.
The reasons for this limitation are (1) to permit “inter-thread happens before” to be transitively closed and (2) the “happens before” relation, defined below, provides for relationships consisting entirely of “sequenced before”.
— end note]
An evaluation A happens before an evaluation B (or, equivalently, B happens after A) if
  • A is sequenced before B, or
  • A inter-thread happens before B.
The implementation shall ensure that no program execution demonstrates a cycle in the “happens before” relation.
[Note 10: 
This cycle would otherwise be possible only through the use of consume operations.
— end note]
An evaluation A simply happens before an evaluation B if either
  • A is sequenced before B, or
  • A synchronizes with B, or
  • A simply happens before X and X simply happens before B.
[Note 11: 
In the absence of consume operations, the happens before and simply happens before relations are identical.
— end note]
An evaluation A strongly happens before an evaluation D if, either
  • A is sequenced before D, or
  • A synchronizes with D, and both A and D are sequentially consistent atomic operations ([atomics.order]), or
  • there are evaluations B and C such that A is sequenced before B, B simply happens before C, and C is sequenced before D, or
  • there is an evaluation B such that A strongly happens before B, and B strongly happens before D.
[Note 12: 
Informally, if A strongly happens before B, then A appears to be evaluated before B in all contexts.
Strongly happens before excludes consume operations.
— end note]
A visible side effect A on a scalar object or bit-field M with respect to a value computation B of M satisfies the conditions:
  • A happens before B and
  • there is no other side effect X to M such that A happens before X and X happens before B.
The value of a non-atomic scalar object or bit-field M, as determined by evaluation B, is the value stored by the visible side effect A.
[Note 13: 
If there is ambiguity about which side effect to a non-atomic object or bit-field is visible, then the behavior is either unspecified or undefined.
— end note]
[Note 14: 
This states that operations on ordinary objects are not visibly reordered.
This is not actually detectable without data races, but is needed to ensure that data races, as defined below, and with suitable restrictions on the use of atomics, correspond to data races in a simple interleaved (sequentially consistent) execution.
— end note]
The value of an atomic object M, as determined by evaluation B, is the value stored by some unspecified side effect A that modifies M, where B does not happen before A.
[Note 15: 
The set of such side effects is also restricted by the rest of the rules described here, and in particular, by the coherence requirements below.
— end note]
If an operation A that modifies an atomic object M happens before an operation B that modifies M, then A is earlier than B in the modification order of M.
[Note 16: 
This requirement is known as write-write coherence.
— end note]
If a value computation A of an atomic object M happens before a value computation B of M, and A takes its value from a side effect X on M, then the value computed by B is either the value stored by X or the value stored by a side effect Y on M, where Y follows X in the modification order of M.
[Note 17: 
This requirement is known as read-read coherence.
— end note]
If a value computation A of an atomic object M happens before an operation B that modifies M, then A takes its value from a side effect X on M, where X precedes B in the modification order of M.
[Note 18: 
This requirement is known as read-write coherence.
— end note]
If a side effect X on an atomic object M happens before a value computation B of M, then the evaluation B takes its value from X or from a side effect Y that follows X in the modification order of M.
[Note 19: 
This requirement is known as write-read coherence.
— end note]
[Note 20: 
The four preceding coherence requirements effectively disallow compiler reordering of atomic operations to a single object, even if both operations are relaxed loads.
This effectively makes the cache coherence guarantee provided by most hardware available to C++ atomic operations.
— end note]
[Note 21: 
The value observed by a load of an atomic depends on the “happens before” relation, which depends on the values observed by loads of atomics.
The intended reading is that there must exist an association of atomic loads with modifications they observe that, together with suitably chosen modification orders and the “happens before” relation derived as described above, satisfy the resulting constraints as imposed here.
— end note]
Two actions are potentially concurrent if
  • they are performed by different threads, or
  • they are unsequenced, at least one is performed by a signal handler, and they are not both performed by the same signal handler invocation.
The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other, except for the special case for signal handlers described below.
Any such data race results in undefined behavior.
[Note 22: 
It can be shown that programs that correctly use mutexes and memory_order​::​seq_cst operations to prevent all data races and use no other synchronization operations behave as if the operations executed by their constituent threads were simply interleaved, with each value computation of an object being taken from the last side effect on that object in that interleaving.
This is normally referred to as “sequential consistency”.
However, this applies only to data-race-free programs, and data-race-free programs cannot observe most program transformations that do not change single-threaded program semantics.
In fact, most single-threaded program transformations remain possible, since any program that behaves differently as a result has undefined behavior.
— end note]
Two accesses to the same object of type volatile std​::​sig_atomic_t do not result in a data race if both occur in the same thread, even if one or more occurs in a signal handler.
For each signal handler invocation, evaluations performed by the thread invoking a signal handler can be divided into two groups A and B, such that no evaluations in B happen before evaluations in A, and the evaluations of such volatile std​::​sig_atomic_t objects take values as though all evaluations in A happened before the execution of the signal handler and the execution of the signal handler happened before all evaluations in B.
[Note 23: 
Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this document, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race.
This includes implementations of data member assignment that overwrite adjacent members in separate memory locations.
Reordering of atomic loads in cases in which the atomics in question might alias is also generally precluded, since this could violate the coherence rules.
— end note]
[Note 24: 
It is possible that transformations that introduce a speculative read of a potentially shared memory location do not preserve the semantics of the C++ program as defined in this document, since they potentially introduce a data race.
However, they are typically valid in the context of an optimizing compiler that targets a specific machine with well-defined semantics for data races.
They would be invalid for a hypothetical machine that is not tolerant of races or provides hardware race detection.
— end note]

6.9.2.3 Forward progress [intro.progress]

The implementation may assume that any thread will eventually do one of the following:
[Note 1: 
This is intended to allow compiler transformations such as removal, merging, and reordering of empty loops, even when termination cannot be proven.
An affordance is made for trivial infinite loops, which cannot be removed nor reordered.
— end note]
Executions of atomic functions that are either defined to be lock-free ([atomics.flag]) or indicated as lock-free ([atomics.lockfree]) are lock-free executions.
  • If there is only one thread that is not blocked ([defns.block]) in a standard library function, a lock-free execution in that thread shall complete.
    [Note 2: 
    Concurrently executing threads might prevent progress of a lock-free execution.
    For example, this situation can occur with load-locked store-conditional implementations.
    This property is sometimes termed obstruction-free.
    — end note]
  • When one or more lock-free executions run concurrently, at least one should complete.
    [Note 3: 
    It is difficult for some implementations to provide absolute guarantees to this effect, since repeated and particularly inopportune interference from other threads could prevent forward progress, e.g., by repeatedly stealing a cache line for unrelated purposes between load-locked and store-conditional instructions.
    For implementations that follow this recommendation and ensure that such effects cannot indefinitely delay progress under expected operating conditions, such anomalies can therefore safely be ignored by programmers.
    Outside this document, this property is sometimes termed lock-free.
    — end note]
During the execution of a thread of execution, each of the following is termed an execution step:
  • termination of the thread of execution,
  • performing an access through a volatile glvalue, or
  • completion of a call to a library I/O function, a synchronization operation, or an atomic operation.
An invocation of a standard library function that blocks ([defns.block]) is considered to continuously execute execution steps while waiting for the condition that it blocks on to be satisfied.
[Example 1: 
A library I/O function that blocks until the I/O operation is complete can be considered to continuously check whether the operation is complete.
Each such check consists of one or more execution steps, for example using observable behavior of the abstract machine.
— end example]
[Note 4: 
Because of this and the preceding requirement regarding what threads of execution have to perform eventually, it follows that no thread of execution can execute forever without an execution step occurring.
— end note]
A thread of execution makes progress when an execution step occurs or a lock-free execution does not complete because there are other concurrent threads that are not blocked in a standard library function (see above).
For a thread of execution providing concurrent forward progress guarantees, the implementation ensures that the thread will eventually make progress for as long as it has not terminated.
[Note 5: 
This applies regardless of whether or not other threads of execution (if any) have been or are making progress.
To eventually fulfill this requirement means that this will happen in an unspecified but finite amount of time.
— end note]
It is implementation-defined whether the implementation-created thread of execution that executes main ([basic.start.main]) and the threads of execution created by std​::​thread ([thread.thread.class]) or std​::​jthread ([thread.jthread.class]) provide concurrent forward progress guarantees.
General-purpose implementations should provide these guarantees.
For a thread of execution providing parallel forward progress guarantees, the implementation is not required to ensure that the thread will eventually make progress if it has not yet executed any execution step; once this thread has executed a step, it provides concurrent forward progress guarantees.
[Note 6: 
This does not specify a requirement for when to start this thread of execution, which will typically be specified by the entity that creates this thread of execution.
For example, a thread of execution that provides concurrent forward progress guarantees and executes tasks from a set of tasks in an arbitrary order, one after the other, satisfies the requirements of parallel forward progress for these tasks.
— end note]
For a thread of execution providing weakly parallel forward progress guarantees, the implementation does not ensure that the thread will eventually make progress.
[Note 7: 
Threads of execution providing weakly parallel forward progress guarantees cannot be expected to make progress regardless of whether other threads make progress or not; however, blocking with forward progress guarantee delegation, as defined below, can be used to ensure that such threads of execution make progress eventually.
— end note]
Concurrent forward progress guarantees are stronger than parallel forward progress guarantees, which in turn are stronger than weakly parallel forward progress guarantees.
[Note 8: 
For example, some kinds of synchronization between threads of execution might only make progress if the respective threads of execution provide parallel forward progress guarantees, but will fail to make progress under weakly parallel guarantees.
— end note]
When a thread of execution P is specified to block with forward progress guarantee delegation on the completion of a set S of threads of execution, then throughout the whole time of P being blocked on S, the implementation shall ensure that the forward progress guarantees provided by at least one thread of execution in S is at least as strong as P's forward progress guarantees.
[Note 9: 
It is unspecified which thread or threads of execution in S are chosen and for which number of execution steps.
The strengthening is not permanent and not necessarily in place for the rest of the lifetime of the affected thread of execution.
As long as P is blocked, the implementation has to eventually select and potentially strengthen a thread of execution in S.
— end note]
Once a thread of execution in S terminates, it is removed from S.
Once S is empty, P is unblocked.
[Note 10: 
A thread of execution B thus can temporarily provide an effectively stronger forward progress guarantee for a certain amount of time, due to a second thread of execution A being blocked on it with forward progress guarantee delegation.
In turn, if B then blocks with forward progress guarantee delegation on C, this can also temporarily provide a stronger forward progress guarantee to C.
— end note]
[Note 11: 
If all threads of execution in S finish executing (e.g., they terminate and do not use blocking synchronization incorrectly), then P's execution of the operation that blocks with forward progress guarantee delegation will not result in P's progress guarantee being effectively weakened.
— end note]
[Note 12: 
This does not remove any constraints regarding blocking synchronization for threads of execution providing parallel or weakly parallel forward progress guarantees because the implementation is not required to strengthen a particular thread of execution whose too-weak progress guarantee is preventing overall progress.
— end note]
An implementation should ensure that the last value (in modification order) assigned by an atomic or synchronization operation will become visible to all other threads in a finite period of time.

6.9.3 Start and termination [basic.start]

6.9.3.1 main function [basic.start.main]

A program shall contain exactly one function called main that belongs to the global scope.
Executing a program starts a main thread of execution ([intro.multithread], [thread.threads]) in which the main function is invoked.
It is implementation-defined whether a program in a freestanding environment is required to define a main function.
[Note 1: 
In a freestanding environment, startup and termination is implementation-defined; startup contains the execution of constructors for non-local objects with static storage duration; termination contains the execution of destructors for objects with static storage duration.
— end note]
An implementation shall not predefine the main function.
Its type shall have C++ language linkage and it shall have a declared return type of type int, but otherwise its type is implementation-defined.
An implementation shall allow both
  • a function of () returning int and
  • a function of (int, pointer to pointer to char) returning int
as the type of main ([dcl.fct]).
In the latter form, for purposes of exposition, the first function parameter is called argc and the second function parameter is called argv, where argc shall be the number of arguments passed to the program from the environment in which the program is run.
If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (ntmbss) ([multibyte.strings]) and argv[0] shall be the pointer to the initial character of an ntmbs that represents the name used to invoke the program or "".
The value of argc shall be non-negative.
The value of argv[argc] shall be 0.
Recommended practice: Any further (optional) parameters should be added after argv.
The function main shall not be named by an expression.
The linkage ([basic.link]) of main is implementation-defined.
A program that defines main as deleted or that declares main to be inline, static, constexpr, or consteval is ill-formed.
The function main shall not be a coroutine ([dcl.fct.def.coroutine]).
The main function shall not be declared with a linkage-specification ([dcl.link]).
A program that declares
  • a variable main that belongs to the global scope, or
  • a function main that belongs to the global scope and is attached to a named module, or
  • a function template main that belongs to the global scope, or
  • an entity named main with C language linkage (in any namespace)
is ill-formed.
The name main is not otherwise reserved.
[Example 1: 
Member functions, classes, and enumerations can be called main, as can entities in other namespaces.
— end example]
Terminating the program without leaving the current block (e.g., by calling the function std​::​exit(int) ([support.start.term])) does not destroy any objects with automatic storage duration ([class.dtor]).
If std​::​exit is invoked during the destruction of an object with static or thread storage duration, the program has undefined behavior.
A return statement ([stmt.return]) in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std​::​exit with the return value as the argument.
If control flows off the end of the compound-statement of main, the effect is equivalent to a return with operand 0 (see also [except.handle]).

6.9.3.2 Static initialization [basic.start.static]

Variables with static storage duration are initialized as a consequence of program initiation.
Variables with thread storage duration are initialized as a consequence of thread execution.
Within each of these phases of initiation, initialization occurs as follows.
Constant initialization is performed if a variable with static or thread storage duration is constant-initialized ([expr.const]).
If constant initialization is not performed, a variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is zero-initialized ([dcl.init]).
Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization.
All static initialization strongly happens before ([intro.races]) any dynamic initialization.
[Note 1: 
The dynamic initialization of non-block variables is described in [basic.start.dynamic]; that of static block variables is described in [stmt.dcl].
— end note]
An implementation is permitted to perform the initialization of a variable with static or thread storage duration as a static initialization even if such initialization is not required to be done statically, provided that
  • the dynamic version of the initialization does not change the value of any other object of static or thread storage duration prior to its initialization, and
  • the static version of the initialization produces the same value in the initialized variable as would be produced by the dynamic initialization if all variables not required to be initialized statically were initialized dynamically.
[Note 2: 
As a consequence, if the initialization of an object obj1 refers to an object obj2 potentially requiring dynamic initialization and defined later in the same translation unit, it is unspecified whether the value of obj2 used will be the value of the fully initialized obj2 (because obj2 was statically initialized) or will be the value of obj2 merely zero-initialized.
For example, inline double fd() { return 1.0; } extern double d1; double d2 = d1; // unspecified: // either statically initialized to 0.0 or // dynamically initialized to 0.0 if d1 is // dynamically initialized, or 1.0 otherwise double d1 = fd(); // either initialized statically or dynamically to 1.0
— end note]

6.9.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]

Dynamic initialization of a non-block variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated specialization, and otherwise is ordered.
[Note 1: 
A non-inline explicit specialization of a templated variable has ordered initialization.
— end note]
A declaration D is appearance-ordered before a declaration E if
  • D appears in the same translation unit as E, or
  • the translation unit containing E has an interface dependency on the translation unit containing D,
in either case prior to E.
Dynamic initialization of non-block variables V and W with static storage duration are ordered as follows:
  • If V and W have ordered initialization and the definition of V is appearance-ordered before the definition of W, or if V has partially-ordered initialization, W does not have unordered initialization, and for every definition E of W there exists a definition D of V such that D is appearance-ordered before E, then
    • if the program does not start a thread ([intro.multithread]) other than the main thread ([basic.start.main]) or V and W have ordered initialization and they are defined in the same translation unit, the initialization of V is sequenced before the initialization of W;
    • otherwise, the initialization of V strongly happens before the initialization of W.
  • Otherwise, if the program starts a thread other than the main thread before either V or W is initialized, it is unspecified in which threads the initializations of V and W occur; the initializations are unsequenced if they occur in the same thread.
  • Otherwise, the initializations of V and W are indeterminately sequenced.
[Note 2: 
This definition permits initialization of a sequence of ordered variables concurrently with another sequence.
— end note]
A non-initialization odr-use is an odr-use ([basic.def.odr]) not caused directly or indirectly by the initialization of a non-block static or thread storage duration variable.
It is implementation-defined whether the dynamic initialization of a non-block non-inline variable with static storage duration is sequenced before the first statement of main or is deferred.
If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.38
It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.
Recommended practice: An implementation should choose such points in a way that allows the programmer to avoid deadlocks.
[Example 1: // - File 1 - #include "a.h" #include "b.h" B b; A::A() { b.Use(); } // - File 2 - #include "a.h" A a; // - File 3 - #include "a.h" #include "b.h" extern A a; extern B b; int main() { a.Use(); b.Use(); }
It is implementation-defined whether either a or b is initialized before main is entered or whether the initializations are delayed until a is first odr-used in main.
In particular, if a is initialized before main is entered, it is not guaranteed that b will be initialized before it is odr-used by the initialization of a, that is, before A​::​A is called.
If, however, a is initialized at some point after the first statement of main, b will be initialized prior to its use in A​::​A.
— end example]
It is implementation-defined whether the dynamic initialization of a non-block inline variable with static storage duration is sequenced before the first statement of main or is deferred.
If it is deferred, it strongly happens before any non-initialization odr-use of that variable.
It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.
It is implementation-defined whether the dynamic initialization of a non-block non-inline variable with thread storage duration is sequenced before the first statement of the initial function of a thread or is deferred.
If it is deferred, the initialization associated with the entity for thread t is sequenced before the first non-initialization odr-use by t of any non-inline variable with thread storage duration defined in the same translation unit as the variable to be initialized.
It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.
If the initialization of a non-block variable with static or thread storage duration exits via an exception, the function std​::​terminate is called ([except.terminate]).
38)38)
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 ([basic.def.odr], [basic.stc.static]).

6.9.3.4 Termination [basic.start.term]

Constructed objects ([dcl.init]) with static storage duration are destroyed and functions registered with std​::​atexit are called as part of a call to std​::​exit ([support.start.term]).
The call to std​::​exit is sequenced before the destructions and the registered functions.
[Note 1: 
Returning from main invokes std​::​exit ([basic.start.main]).
— end note]
Constructed objects with thread storage duration within a given thread are destroyed as a result of returning from the initial function of that thread and as a result of that thread calling std​::​exit.
The destruction of all constructed objects with thread storage duration within that thread strongly happens before destroying any object with static storage duration.
If the completion of the constructor or dynamic initialization of an object with static storage duration strongly happens before that of another, the completion of the destructor of the second is sequenced before the initiation of the destructor of the first.
If the completion of the constructor or dynamic initialization of an object with thread storage duration is sequenced before that of another, the completion of the destructor of the second is sequenced before the initiation of the destructor of the first.
If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized.
For an object of array or class type, all subobjects of that object are destroyed before any block variable with static storage duration initialized during the construction of the subobjects is destroyed.
If the destruction of an object with static or thread storage duration exits via an exception, the function std​::​terminate is called ([except.terminate]).
If a function contains a block variable of static or thread storage duration that has been destroyed and the function is called during the destruction of an object with static or thread storage duration, the program has undefined behavior if the flow of control passes through the definition of the previously destroyed block variable.
[Note 2: 
Likewise, the behavior is undefined if the block variable is used indirectly (e.g., through a pointer) after its destruction.
— end note]
If the completion of the initialization of an object with static storage duration strongly happens before a call to std​::​atexit (see <cstdlib>, [support.start.term]), the call to the function passed to std​::​atexit is sequenced before the call to the destructor for the object.
If a call to std​::​atexit strongly happens before the completion of the initialization of an object with static storage duration, the call to the destructor for the object is sequenced before the call to the function passed to std​::​atexit.
If a call to std​::​atexit strongly happens before another call to std​::​atexit, the call to the function passed to the second std​::​atexit call is sequenced before the call to the function passed to the first std​::​atexit call.
If there is a use of a standard library object or function not permitted within signal handlers ([support.runtime]) that does not happen before ([intro.multithread]) completion of destruction of objects with static storage duration and execution of std​::​atexit registered functions ([support.start.term]), the program has undefined behavior.
[Note 3: 
If there is a use of an object with static storage duration that does not happen before the object's destruction, the program has undefined behavior.
Terminating every thread before a call to std​::​exit or the exit from main is sufficient, but not necessary, to satisfy these requirements.
These requirements permit thread managers as static-storage-duration objects.
— end note]
Calling the function std​::​abort() declared in <cstdlib> terminates the program without executing any destructors and without calling the functions passed to std​::​atexit() or std​::​at_quick_exit().

7 Expressions [expr]

7.1 Preamble [expr.pre]

[Note 1: 
[expr] defines the syntax, order of evaluation, and meaning of expressions.39
An expression is a sequence of operators and operands that specifies a computation.
An expression can result in a value and can cause side effects.
— end note]
[Note 2: 
Operators can be overloaded, that is, given meaning when applied to expressions of class type or enumeration type.
Uses of overloaded operators are transformed into function calls as described in [over.oper].
Overloaded operators obey the rules for syntax and evaluation order specified in [expr.compound], but the requirements of operand type and value category are replaced by the rules for function call.
Relations between operators, such as ++a meaning a+=1, are not guaranteed for overloaded operators.
— end note]
Subclause [expr.compound] defines the effects of operators when applied to types for which they have not been overloaded.
Operator overloading shall not modify the rules for the built-in operators, that is, for operators applied to types for which they are defined by this Standard.
However, these built-in operators participate in overload resolution, and as part of that process user-defined conversions will be considered where necessary to convert the operands to types appropriate for the built-in operator.
If a built-in operator is selected, such conversions will be applied to the operands before the operation is considered further according to the rules in [expr.compound]; see [over.match.oper], [over.built].
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
[Note 3: 
Treatment of division by zero, forming a remainder using a zero divisor, and all floating-point exceptions varies among machines, and is sometimes adjustable by a library function.
— end note]
[Note 4: 
The implementation can regroup operators according to the usual mathematical rules only where the operators really are associative or commutative.40
For example, in the following fragment int a, b; /* ... */ a = a + 32760 + b + 5; the expression statement behaves exactly the same as a = (((a + 32760) + b) + 5); due to the associativity and precedence of these operators.
Thus, the result of the sum (a + 32760) is next added to b, and that result is then added to 5 which results in the value assigned to a.
On a machine in which overflows produce an exception and in which the range of values representable by an int is [-32768, +32767], the implementation cannot rewrite this expression as a = ((a + b) + 32765); since if the values for a and b were, respectively, and , the sum a + b would produce an exception while the original expression would not; nor can the expression be rewritten as either a = ((a + 32765) + b); or a = (a + (b + 32765)); since the values for a and b might have been, respectively, 4 and or and 12.
However on a machine in which overflows do not produce an exception and in which the results of overflows are reversible, the above expression statement can be rewritten by the implementation in any of the above ways because the same result will occur.
— end note]
The values of the floating-point operands and the results of floating-point expressions may be represented in greater precision and range than that required by the type; the types are not changed thereby.41
39)39)
The precedence of operators is not directly specified, but it can be derived from the syntax.
40)40)
Overloaded operators are never assumed to be associative or commutative.
41)41)
The cast and assignment operators must still perform their specific conversions as described in [expr.type.conv], [expr.cast], [expr.static.cast] and [expr.ass].

7.2 Properties of expressions [expr.prop]

7.2.1 Value category [basic.lval]

Expressions are categorized according to the taxonomy in Figure 2.
categories expression expression glvalue glvalue expression->glvalue rvalue rvalue expression->rvalue lvalue lvalue glvalue->lvalue xvalue xvalue glvalue->xvalue rvalue->xvalue prvalue prvalue rvalue->prvalue
Figure 2 — Expression category taxonomy  [fig:basic.lval]
  • A glvalue is an expression whose evaluation determines the identity of an object or function.
  • A prvalue is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, or an expression that has type cv void.
  • An xvalue is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime).
  • An lvalue is a glvalue that is not an xvalue.
  • An rvalue is a prvalue or an xvalue.
Every expression belongs to exactly one of the fundamental categories in this taxonomy: lvalue, xvalue, or prvalue.
This property of an expression is called its value category.
[Note 1: 
The discussion of each built-in operator in [expr.compound] indicates the category of the value it yields and the value categories of the operands it expects.
For example, the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result.
User-defined operators are functions, and the categories of values they expect and yield are determined by their parameter and return types.
— end note]
[Note 2: 
Historically, lvalues and rvalues were so-called because they could appear on the left- and right-hand side of an assignment (although this is no longer generally true); glvalues are “generalized” lvalues, prvalues are “pure” rvalues, and xvalues are “eXpiring” lvalues.
Despite their names, these terms apply to expressions, not values.
— end note]
[Note 3: 
An expression is an xvalue if it is:
In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not.
— end note]
[Example 1: struct A { int m; }; A&& operator+(A, A); A&& f(); A a; A&& ar = static_cast<A&&>(a);
The expressions f(), f().m, static_cast<A&&>(a), and a + a are xvalues.
The expression ar is an lvalue.
— end example]
The result of a glvalue is the entity denoted by the expression.
The result of a prvalue is the value that the expression stores into its context; a prvalue that has type cv void has no result.
A prvalue whose result is the value V is sometimes said to have or name the value V.
The result object of a prvalue is the object initialized by the prvalue; a non-discarded prvalue that is used to compute the value of an operand of a built-in operator or a prvalue that has type cv void has no result object.
[Note 4: 
Except when the prvalue is the operand of a decltype-specifier, a prvalue of class or array type always has a result object.
For a discarded prvalue that has type other than cv void, a temporary object is materialized; see [expr.context].
— end note]
Whenever a glvalue appears as an operand of an operator that requires a prvalue for that operand, the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), or function-to-pointer ([conv.func]) standard conversions are applied to convert the expression to a prvalue.
[Note 5: 
An attempt to bind an rvalue reference to an lvalue is not such a context; see [dcl.init.ref].
— end note]
[Note 6: 
Because cv-qualifiers are removed from the type of an expression of non-class type when the expression is converted to a prvalue, an lvalue of type const int can, for example, be used where a prvalue of type int is required.
— end note]
[Note 7: 
There are no prvalue bit-fields; if a bit-field is converted to a prvalue ([conv.lval]), a prvalue of the type of the bit-field is created, which might then be promoted ([conv.prom]).
— end note]
Unless otherwise specified ([expr.reinterpret.cast], [expr.const.cast]), whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, the temporary materialization conversion is applied to convert the expression to an xvalue.
[Note 8: 
The discussion of reference initialization in [dcl.init.ref] and of temporaries in [class.temporary] indicates the behavior of lvalues and rvalues in other significant contexts.
— end note]
Unless otherwise indicated ([dcl.type.decltype]), a prvalue shall always have complete type or the void type; if it has a class type or (possibly multidimensional) array of class type, that class shall not be an abstract class ([class.abstract]).
A glvalue shall not have type cv void.
[Note 9: 
A glvalue can have complete or incomplete non-void type.
Class and array prvalues can have cv-qualified types; other prvalues always have cv-unqualified types.
— end note]
An lvalue is modifiable unless its type is const-qualified or is a function type.
[Note 10: 
A program that attempts to modify an object through a nonmodifiable lvalue or through an rvalue is ill-formed ([expr.ass], [expr.post.incr], [expr.pre.incr]).
— end note]
An object of dynamic type is type-accessible through a glvalue of type if is similar ([conv.qual]) to:
  • ,
  • a type that is the signed or unsigned type corresponding to , or
  • a char, unsigned char, or std​::​byte type.
If a program attempts to access ([defns.access]) the stored value of an object through a glvalue through which it is not type-accessible, the behavior is undefined.42
If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type U with a glvalue argument that does not denote an object of type cv U within its lifetime, the behavior is undefined.
[Note 11: 
In C, an entire object of structure type can be accessed, e.g., using assignment.
By contrast, C++ has no notion of accessing an object of class type through an lvalue of class type.
— end note]
42)42)
The intent of this list is to specify those circumstances in which an object can or cannot be aliased.

7.2.2 Type [expr.type]

If an expression initially has the type “reference to T” ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis; the value category of the expression is not altered.
Let X be the object or function denoted by the reference.
If a pointer to X would be valid in the context of the evaluation of the expression ([basic.fundamental]), the result designates X; otherwise, the behavior is undefined.
[Note 1: 
Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see [basic.life]).
— end note]
If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.
The composite pointer type of two operands p1 and p2 having types T1 and T2, respectively, where at least one is a pointer or pointer-to-member type or std​::​nullptr_t, is:
  • if both p1 and p2 are null pointer constants, std​::​nullptr_t;
  • if either p1 or p2 is a null pointer constant, T2 or T1, respectively;
  • if T1 or T2 is “pointer to cv1 void” and the other type is “pointer to cv2 T”, where T is an object type or void, “pointer to cv12 void”, where cv12 is the union of cv1 and cv2;
  • if T1 or T2 is “pointer to noexcept function” and the other type is “pointer to function”, where the function types are otherwise the same, “pointer to function”;
  • if T1 is “pointer to cv1 C1” and T2 is “pointer to cv2 C2”, where C1 is reference-related to C2 or C2 is reference-related to C1 ([dcl.init.ref]), the qualification-combined type ([conv.qual]) of T1 and T2 or the qualification-combined type of T2 and T1, respectively;
  • if T1 or T2 is “pointer to member of C1 of type function”, the other type is “pointer to member of C2 of type noexcept function”, and C1 is reference-related to C2 or C2 is reference-related to C1 ([dcl.init.ref]), where the function types are otherwise the same, “pointer to member of C2 of type function” or “pointer to member of C1 of type function”, respectively;
  • if T1 is “pointer to member of C1 of type cv1 U” and T2 is “pointer to member of C2 of type cv2 U”, for some non-function type U, where C1 is reference-related to C2 or C2 is reference-related to C1 ([dcl.init.ref]), the qualification-combined type of T2 and T1 or the qualification-combined type of T1 and T2, respectively;
  • if T1 and T2 are similar types ([conv.qual]), the qualification-combined type of T1 and T2;
  • otherwise, a program that necessitates the determination of a composite pointer type is ill-formed.
[Example 1: typedef void *p; typedef const int *q; typedef int **pi; typedef const int **pci;
The composite pointer type of p and q is “pointer to const void”; the composite pointer type of pi and pci is “pointer to const pointer to const int.
— end example]

7.2.3 Context dependence [expr.context]

An unevaluated operand is not evaluated.
[Note 1: 
In an unevaluated operand, a non-static class member can be named ([expr.prim.id]) and naming of objects or functions does not, by itself, require that a definition be provided ([basic.def.odr]).
An unevaluated operand is considered a full-expression.
— end note]
In some contexts, an expression only appears for its side effects.
Such an expression is called a discarded-value expression.
The array-to-pointer and function-to-pointer standard conversions are not applied.
The lvalue-to-rvalue conversion is applied if and only if the expression is a glvalue of volatile-qualified type and it is one of the following:
[Note 2: 
Using an overloaded operator causes a function call; the above covers only operators with built-in meaning.
— end note]
The temporary materialization conversion ([conv.rval]) is applied if the (possibly converted) expression is a prvalue of object type.
[Note 3: 
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 expression is evaluated and its result (if any) is discarded.

7.3 Standard conversions [conv]

7.3.1 General [conv.general]

Standard conversions are implicit conversions with built-in meaning.
[conv] enumerates the full set of such conversions.
A standard conversion sequence is a sequence of standard conversions in the following order:
  • Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.
  • Zero or one conversion from the following set: integral promotions, floating-point promotion, integral conversions, floating-point conversions, floating-integral conversions, pointer conversions, pointer-to-member conversions, and boolean conversions.
  • Zero or one function pointer conversion.
  • Zero or one qualification conversion.
[Note 1: 
A standard conversion sequence can be empty, i.e., it can consist of no conversions.
— end note]
A standard conversion sequence will be applied to an expression if necessary to convert it to an expression having a required destination type and value category.
[Note 2: 
Expressions with a given type will be implicitly converted to other types in several contexts:
  • When used as operands of operators.
    The operator's requirements for its operands dictate the destination type ([expr.compound]).
  • When used in the condition of an if statement ([stmt.if]) or iteration statement ([stmt.iter]).
    The destination type is bool.
  • When used in the expression of a switch statement ([stmt.switch]).
    The destination type is integral.
  • When used as the source expression for an initialization (which includes use as an argument in a function call and use as the expression in a return statement).
    The type of the entity being initialized is (generally) the destination type.
— end note]
An expression E can be implicitly converted to a type T if and only if the declaration T t=E; is well-formed, for some invented temporary variable t ([dcl.init]).
Certain language constructs require that an expression be converted to a Boolean value.
An expression E appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(E); is well-formed, for some invented temporary variable t ([dcl.init]).
Certain language constructs require conversion to a value having one of a specified set of types appropriate to the construct.
An expression E of class type C appearing in such a context is said to be contextually implicitly converted to a specified type T and is well-formed if and only if E can be implicitly converted to a type T that is determined as follows: C is searched for non-explicit conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context.
There shall be exactly one such T.
The effect of any implicit conversion is the same as performing the corresponding declaration and initialization and then using the temporary variable as the result of the conversion.
The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type ([dcl.ref]), an xvalue if T is an rvalue reference to object type, and a prvalue otherwise.
The expression E is used as a glvalue if and only if the initialization uses it as a glvalue.
[Note 3: 
For class types, user-defined conversions are considered as well; see [class.conv].
In general, an implicit conversion sequence ([over.best.ics]) consists of a standard conversion sequence followed by a user-defined conversion followed by another standard conversion sequence.
— end note]
[Note 4: 
There are some contexts where certain conversions are suppressed.
For example, the lvalue-to-rvalue conversion is not done on the operand of the unary & operator.
Specific exceptions are given in the descriptions of those operators and contexts.
— end note]

7.3.2 Lvalue-to-rvalue conversion [conv.lval]

A glvalue of a non-function, non-array type T can be converted to a prvalue.43
If T is an incomplete type, a program that necessitates this conversion is ill-formed.
If T is a non-class type, the type of the prvalue is the cv-unqualified version of T.
Otherwise, the type of the prvalue is T.44
When an lvalue-to-rvalue conversion is applied to an expression E, and either
  • E is not potentially evaluated, or
  • the evaluation of E results in the evaluation of a member of the set of potential results of E, and names a variable x that is not odr-used by ([basic.def.odr]),
the value contained in the referenced object is not accessed.
[Example 1: struct S { int n; }; auto f() { S x { 1 }; constexpr S y { 2 }; return [&](bool b) { return (b ? y : x).n; }; } auto g = f(); int m = g(false); // undefined behavior: access of x.n outside its lifetime int n = g(true); // OK, does not access y.n — end example]
The result of the conversion is determined according to the following rules:
  • If T is cv std​::​nullptr_t, the result is a null pointer constant ([conv.ptr]).
    [Note 1: 
    Since the conversion does not access the object to which the glvalue refers, there is no side effect even if T is volatile-qualified ([intro.execution]), and the glvalue can refer to an inactive member of a union ([class.union]).
    — end note]
  • Otherwise, if T has a class type, the conversion copy-initializes the result object from the glvalue.
  • Otherwise, if the object to which the glvalue refers contains an invalid pointer value ([basic.stc.dynamic.deallocation]), the behavior is implementation-defined.
  • Otherwise, if the bits in the value representation of the object to which the glvalue refers are not valid for the object's type, the behavior is undefined.
    [Example 2: bool f() { bool b = true; char c = 42; memcpy(&b, &c, 1); return b; // undefined behavior if 42 is not a valid value representation for bool } — end example]
  • Otherwise, the object indicated by the glvalue is read ([defns.access]).
    Let V be the value contained in the object.
    If T is an integer type, the prvalue result is the value of type T congruent ([basic.fundamental]) to V, and V otherwise.
[Note 2: 
See also [basic.lval].
— end note]
43)43)
For historical reasons, this conversion is called the “lvalue-to-rvalue” conversion, even though that name does not accurately reflect the taxonomy of expressions described in [basic.lval].
44)44)
In C++ class and array prvalues can have cv-qualified types.
This differs from C, in which non-lvalues never have cv-qualified types.

7.3.3 Array-to-pointer conversion [conv.array]

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T.
The temporary materialization conversion ([conv.rval]) is applied.
The result is a pointer to the first element of the array.

7.3.4 Function-to-pointer conversion [conv.func]

An lvalue of function type T can be converted to a prvalue of type “pointer to T.
The result is a pointer to the function.45
45)45)
This conversion never applies to non-static member functions because an lvalue that refers to a non-static member function cannot be obtained.

7.3.5 Temporary materialization conversion [conv.rval]

A prvalue of type T can be converted to an xvalue of type T.
This conversion initializes a temporary object ([class.temporary]) of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object.
T shall be a complete type.
[Note 1: 
If T is a class type (or array thereof), it must have an accessible and non-deleted destructor; see [class.dtor].
— end note]
[Example 1: struct X { int n; }; int k = X().n; // OK, X() prvalue is converted to xvalue — end example]

7.3.6 Qualification conversions [conv.qual]

A qualification-decomposition of a type T is a sequence of and such that T is U” for n  ≥ 0, where each is a set of cv-qualifiers ([basic.type.qualifier]), and each is “pointer to” ([dcl.ptr]), “pointer to member of class of type” ([dcl.mptr]), “array of ”, or “array of unknown bound of” ([dcl.array]).
If designates an array, the cv-qualifiers on the element type are also taken as the cv-qualifiers of the array.
[Example 1: 
The type denoted by the type-id const int ** has three qualification-decompositions, taking U as “int”, as “pointer to const int”, and as “pointer to pointer to const int.
— end example]
The n-tuple of cv-qualifiers after the first one in the longest qualification-decomposition of T, that is, , is called the cv-qualification signature of T.
Two types T1 and T2 are similar if they have qualification-decompositions with the same n such that corresponding components are either the same or one is “array of ” and the other is “array of unknown bound of”, and the types denoted by U are the same.
The qualification-combined type of two types T1 and T2 is the type T3 similar to T1 whose qualification-decomposition is such that:
  • for every , is the union of and ,
  • if either or is “array of unknown bound of”, is “array of unknown bound of”, otherwise it is , and
  • if the resulting is different from or , or the resulting is different from or , then const is added to every for ,
where and are the components of the qualification-decomposition of Tj.
A prvalue of type T1 can be converted to type T2 if the qualification-combined type of T1 and T2 is T2.
[Note 1: 
If a program could assign a pointer of type T** to a pointer of type const T** (that is, if line #1 below were allowed), a program could inadvertently modify a const object (as it is done on line #2).
For example, int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object }
— end note]
[Note 2: 
Given similar types T1 and T2, this construction ensures that both can be converted to the qualification-combined type of T1 and T2.
— end note]
[Note 3: 
A prvalue of type “pointer to cv1 T” can be converted to a prvalue of type “pointer to cv2 T” if “cv2 T” is more cv-qualified than “cv1 T.
A prvalue of type “pointer to member of X of type cv1 T” can be converted to a prvalue of type “pointer to member of X of type cv2 T” if “cv2 T” is more cv-qualified than “cv1 T.
— end note]
[Note 4: 
Function types (including those used in pointer-to-member-function types) are never cv-qualified ([dcl.fct]).
— end note]

7.3.7 Integral promotions [conv.prom]

For the purposes of [conv.prom], a converted bit-field is a prvalue that is the result of an lvalue-to-rvalue conversion ([conv.lval]) applied to a bit-field ([class.bit]).
A prvalue that is not a converted bit-field and has an integer type other than bool, char8_t, char16_t, char32_t, or wchar_t whose integer conversion rank ([conv.rank]) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.
A prvalue of an unscoped enumeration type whose underlying type is not fixed can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration ([dcl.enum]): int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int.
If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended integer type with lowest integer conversion rank ([conv.rank]) greater than the rank of long long in which all the values of the enumeration can be represented.
If there are two such extended types, the signed one is chosen.
A prvalue of an unscoped enumeration type whose underlying type is fixed ([dcl.enum]) can be converted to a prvalue of its underlying type.
Moreover, if integral promotion can be applied to its underlying type, a prvalue of an unscoped enumeration type whose underlying type is fixed can also be converted to a prvalue of the promoted underlying type.
[Note 1: 
A converted bit-field of enumeration type is treated as any other value of that type for promotion purposes.
— end note]
A converted bit-field of integral type can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field.
A prvalue of type char8_t, char16_t, char32_t, or wchar_t ([basic.fundamental]) (including a converted bit-field that was not already promoted to int or unsigned int according to the rules above) can be converted to a prvalue of the first of the following types that can represent all the values of its underlying type: int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, or its underlying type.
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
These conversions are called integral promotions.

7.3.8 Floating-point promotion [conv.fpprom]

A prvalue of type float can be converted to a prvalue of type double.
The value is unchanged.
This conversion is called floating-point promotion.

7.3.9 Integral conversions [conv.integral]

A prvalue of an integer type can be converted to a prvalue of another integer type.
A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
If the destination type is bool, see [conv.bool].
If the source type is bool, the value false is converted to zero and the value true is converted to one.
Otherwise, the result is the unique value of the destination type that is congruent to the source integer modulo , where N is the width of the destination type.
The conversions allowed as integral promotions are excluded from the set of integral conversions.

7.3.10 Floating-point conversions [conv.double]

A prvalue of floating-point type can be converted to a prvalue of another floating-point type with a greater or equal conversion rank ([conv.rank]).
A prvalue of standard floating-point type can be converted to a prvalue of another standard floating-point type.
If the source value can be exactly represented in the destination type, the result of the conversion is that exact representation.
If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values.
Otherwise, the behavior is undefined.
The conversions allowed as floating-point promotions are excluded from the set of floating-point conversions.

7.3.11 Floating-integral conversions [conv.fpint]

A prvalue of a floating-point type can be converted to a prvalue of an integer type.
The conversion truncates; that is, the fractional part is discarded.
The behavior is undefined if the truncated value cannot be represented in the destination type.
[Note 1: 
If the destination type is bool, see [conv.bool].
— end note]
A prvalue of an integer type or of an unscoped enumeration type can be converted to a prvalue of a floating-point type.
The result is exact if possible.
If the value being converted is in the range of values that can be represented but the value cannot be represented exactly, it is an implementation-defined choice of either the next lower or higher representable value.
[Note 2: 
Loss of precision occurs if the integral value cannot be represented exactly as a value of the floating-point type.
— end note]
If the value being converted is outside the range of values that can be represented, the behavior is undefined.
If the source type is bool, the value false is converted to zero and the value true is converted to one.

7.3.12 Pointer conversions [conv.ptr]

A null pointer constant is an integer literal ([lex.icon]) with value zero or a prvalue of type std​::​nullptr_t.
A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type ([basic.compound]) and is distinguishable from every other value of object pointer or function pointer type.
Such a conversion is called a null pointer conversion.
The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion ([conv.qual]).
A null pointer constant of integral type can be converted to a prvalue of type std​::​nullptr_t.
[Note 1: 
The resulting prvalue is not a null pointer value.
— end note]
A prvalue of type “pointer to cv T”, where T is an object type, can be converted to a prvalue of type “pointer to cv void.
The pointer value ([basic.compound]) is unchanged by this conversion.
A prvalue v of type “pointer to cv D”, where D is a complete class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class ([class.derived]) of D.
If B is an inaccessible ([class.access]) or ambiguous ([class.member.lookup]) base class of D, a program that necessitates this conversion is ill-formed.
If v is a null pointer value, the result is a null pointer value.
Otherwise, if B is a virtual base class of D and v does not point to an object whose type is similar ([conv.qual]) to D and that is within its lifetime or within its period of construction or destruction ([class.cdtor]), the behavior is undefined.
Otherwise, the result is a pointer to the base class subobject of the derived class object.

7.3.13 Pointer-to-member conversions [conv.mem]

A null pointer constant can be converted to a pointer-to-member type; the result is the null member pointer value of that type and is distinguishable from any pointer to member not created from a null pointer constant.
Such a conversion is called a null member pointer conversion.
The conversion of a null pointer constant to a pointer to member of cv-qualified type is a single conversion, and not the sequence of a pointer-to-member conversion followed by a qualification conversion ([conv.qual]).
A prvalue of type “pointer to member of B of type cv T”, where B is a class type, can be converted to a prvalue of type “pointer to member of D of type cv T”, where D is a complete class derived ([class.derived]) from B.
If B is an inaccessible ([class.access]), ambiguous ([class.member.lookup]), or virtual ([class.mi]) base class of D, or a base class of a virtual base class of D, a program that necessitates this conversion is ill-formed.
If class D does not contain the original member and is not a base class of the class containing the original member, the behavior is undefined.
Otherwise, the result of the conversion refers to the same member as the pointer to member before the conversion took place, but it refers to the base class member as if it were a member of the derived class.
The result refers to the member in D's instance of B.
Since the result has type “pointer to member of D of type cv T”, indirection through it with a D object is valid.
The result is the same as if indirecting through the pointer to member of B with the B subobject of D.
The null member pointer value is converted to the null member pointer value of the destination type.46
46)46)
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) ([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 of such pointers do not apply to pointers to members.
In particular, a pointer to member cannot be converted to a void*.

7.3.14 Function pointer conversions [conv.fctptr]

A prvalue of type “pointer to noexcept function” can be converted to a prvalue of type “pointer to function”.
The result is a pointer to the function.
A prvalue of type “pointer to member of type noexcept function” can be converted to a prvalue of type “pointer to member of type function”.
The result designates the member function.
[Example 1: void (*p)(); void (**pp)() noexcept = &p; // error: cannot convert to pointer to noexcept function struct S { typedef void (*p)(); operator p(); }; void (*q)() noexcept = S(); // error: cannot convert to pointer to noexcept function — end example]

7.3.15 Boolean conversions [conv.bool]

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member type can be converted to a prvalue of type bool.
A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true.

7.4 Usual arithmetic conversions [expr.arith.conv]

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way.
The purpose is to yield a common type, which is also the type of the result.
This pattern is called the usual arithmetic conversions, which are defined as follows:
  • The lvalue-to-rvalue conversion ([conv.lval]) is applied to each operand and the resulting prvalues are used in place of the original operands for the remainder of this section.
  • If either operand is of scoped enumeration type ([dcl.enum]), no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.
  • Otherwise, if one operand is of enumeration type and the other operand is of a different enumeration type or a floating-point type, the expression is ill-formed.
  • Otherwise, if either operand is of floating-point type, the following rules are applied:
    • If both operands have the same type, no further conversion is performed.
    • Otherwise, if one of the operands is of a non-floating-point type, that operand is converted to the type of the operand with the floating-point type.
    • Otherwise, if the floating-point conversion ranks ([conv.rank]) of the types of the operands are ordered but not equal, then the operand of the type with the lesser floating-point conversion rank is converted to the type of the other operand.
    • Otherwise, if the floating-point conversion ranks of the types of the operands are equal, then the operand with the lesser floating-point conversion subrank ([conv.rank]) is converted to the type of the other operand.
    • Otherwise, the expression is ill-formed.
  • Otherwise, each operand is converted to a common type C.
    The integral promotion rules ([conv.prom]) are used to determine a type T1 and type T2 for each operand.47
    Then the following rules are applied to determine C:
    • If T1 and T2 are the same type, C is that type.
    • Otherwise, if T1 and T2 are both signed integer types or are both unsigned integer types, C is the type with greater rank.
    • Otherwise, let U be the unsigned integer type and S be the signed integer type.
      • If U has rank greater than or equal to the rank of S, C is U.
      • Otherwise, if S can represent all of the values of U, C is S.
      • Otherwise, C is the unsigned integer type corresponding to S.
47)47)
As a consequence, operands of type bool, char8_t, char16_t, char32_t, wchar_t, or of enumeration type are converted to some integral type.

7.5 Primary expressions [expr.prim]

7.5.2 Literals [expr.prim.literal]

The type of a literal is determined based on its form as specified in [lex.literal].
A string-literal is an lvalue designating a corresponding string literal object ([lex.string]), a user-defined-literal has the same value category as the corresponding operator call expression described in [lex.ext], and any other literal is a prvalue.

7.5.3 This [expr.prim.this]

The keyword this names a pointer to the object for which an implicit object member function ([class.mfct.non.static]) is invoked or a non-static data member's initializer ([class.mem]) is evaluated.
The current class at a program point is the class associated with the innermost class scope containing that point.
[Note 1: 
A lambda-expression does not introduce a class scope.
— end note]
If a declaration declares a member function or member function template of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” wherever X is the current class between the optional cv-qualifier-seq and the end of the function-definition, member-declarator, or declarator.
It shall not appear within the declaration of a static or explicit object member function of the current class (although its type and value category are defined within such member functions as they are within an implicit object member function).
[Note 2: 
This is because declaration matching does not occur until the complete declarator is known.
— end note]
[Note 3: 
In a trailing-return-type, the class being defined is not required to be complete for purposes of class member access.
Class members declared later are not visible.
[Example 1: struct A { char g(); template<class T> auto f(T t) -> decltype(t + g()) { return t + g(); } }; template auto A::f(int t) -> decltype(t + g()); — end example]
— end note]
Otherwise, if a member-declarator declares a non-static data member ([class.mem]) of a class X, the expression this is a prvalue of type “pointer to X” wherever X is the current class within the optional default member initializer ([class.mem]).
The expression this shall not appear in any other context.
[Example 2: class Outer { int a[sizeof(*this)]; // error: not inside a member function unsigned int sz = sizeof(*this); // OK, in default member initializer void f() { int b[sizeof(*this)]; // OK struct Inner { int c[sizeof(*this)]; // error: not inside a member function of Inner }; } }; — end example]

7.5.4 Parentheses [expr.prim.paren]

A parenthesized expression (E) is a primary expression whose type, result, and value category are identical to those of E.
The parenthesized expression can be used in exactly the same contexts as those where E can be used, and with the same meaning, except as otherwise indicated.

7.5.5 Names [expr.prim.id]

7.5.5.1 General [expr.prim.id.general]

An id-expression is a restricted form of a primary-expression.
[Note 1:  — end note]
If an id-expression E denotes a non-static non-type member of some class C at a point where the current class ([expr.prim.this]) is X and the id-expression is transformed into a class member access expression using (*this) as the object expression.
[Note 2: 
If C is not X or a base class of X, the class member access expression is ill-formed.
Also, if the id-expression occurs within a static or explicit object member function, the class member access is ill-formed.
— end note]
This transformation does not apply in the template definition context ([temp.dep.type]).
If an id-expression E denotes a member M of an anonymous union ([class.union.anon]) U:
  • 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 implicit transformation to a class member access expression).
    [Example 1: 
    o.x is interpreted as o.u.x, where u names the anonymous union member.
    — end example]
  • Otherwise, E is interpreted as a class member access ([expr.ref]) that designates the member subobject M of the anonymous union variable for U.
    [Note 3: 
    Under this interpretation, E no longer denotes a non-static data member.
    — end note]
    [Example 2: 
    N​::​x is interpreted as N​::​u.x, where u names the anonymous union variable.
    — end example]
An id-expression that denotes a non-static data member or implicit object member function of a class can only be used:
  • as part of a class member access (after any implicit transformation (see above)) in which the object expression refers to the member's class or a class derived from that class, or
  • to form a pointer to member ([expr.unary.op]), or
  • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
    [Example 3: struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK — end example]
For an id-expression that denotes an overload set, overload resolution is performed to select a unique function ([over.match], [over.over]).
[Note 4: 
A program cannot refer to a function with a trailing requires-clause whose constraint-expression is not satisfied, because such functions are never selected by overload resolution.
[Example 4: template<typename T> struct A { static void f(int) requires false; }; void g() { A<int>::f(0); // error: cannot call f void (*p1)(int) = A<int>::f; // error: cannot take the address of f decltype(A<int>::f)* p2 = nullptr; // error: the type decltype(A<int>​::​f) is invalid }
In each case, the constraints of f are not satisfied.
In the declaration of p2, those constraints need to be satisfied even though f is an unevaluated operand.
— end example]
— end note]

7.5.5.2 Unqualified names [expr.prim.id.unqual]

An identifier is only an id-expression if it has been suitably declared ([dcl.dcl]) or if it appears as part of a declarator-id ([dcl.decl]).
An identifier that names a coroutine parameter refers to the copy of the parameter ([dcl.fct.def.coroutine]).
[Note 1: 
A type-name or computed-type-specifier prefixed by ~ denotes the destructor of the type so named; see [expr.prim.id.dtor].
— end note]
A component name of an unqualified-id U is
[Note 2: 
Other constructs that contain names to look up can have several component names ([expr.prim.id.qual], [dcl.type.simple], [dcl.type.elab], [dcl.mptr], [namespace.udecl], [temp.param], [temp.names], [temp.res]).
— end note]
The terminal name of a construct is the component name of that construct that appears lexically last.
The result is the entity denoted by the unqualified-id ([basic.lookup.unqual]).
If the unqualified-id appears in a lambda-expression at program point P and the entity is a local entity ([basic.pre]) or a variable declared by an init-capture ([expr.prim.lambda.capture]), then let S be the compound-statement of the innermost enclosing lambda-expression of P.
If naming the entity from outside of an unevaluated operand within S would refer to an entity captured by copy in some intervening lambda-expression, then let E be the innermost such lambda-expression.
  • If there is such a lambda-expression and if P is in E's function parameter scope but not its parameter-declaration-clause, then the type of the expression is the type of a class member access expression ([expr.ref]) naming the non-static data member that would be declared for such a capture in the object parameter ([dcl.fct]) of the function call operator of E.
    [Note 3: 
    If E is not declared mutable, the type of such an identifier will typically be const qualified.
    — end note]
  • Otherwise (if there is no such lambda-expression or if P either precedes E's function parameter scope or is in E's parameter-declaration-clause), the type of the expression is the type of the result.
If the entity is a template parameter object for a template parameter of type T ([temp.param]), the type of the expression is const T.
In all other cases, the type of the expression is the type of the entity.
[Note 4: 
The type will be adjusted as described in [expr.type] if it is cv-qualified or is a reference type.
— end note]
The expression is an xvalue if it is move-eligible (see below); an lvalue if the entity is a function, variable, structured binding, data member, or template parameter object; and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.
[Example 1: void f() { float x, &r = x; [=]() -> decltype((x)) { // lambda returns float const& because this lambda is not mutable and // x is an lvalue decltype(x) y1; // y1 has type float decltype((x)) y2 = y1; // y2 has type float const& decltype(r) r1 = y1; // r1 has type float& decltype((r)) r2 = y2; // r2 has type float const& return y2; }; [=](decltype((x)) y) { decltype((x)) z = x; // OK, y has type float&, z has type float const& }; [=] { [](decltype((x)) y) {}; // OK, lambda takes a parameter of type float const& [x=1](decltype((x)) y) { decltype((x)) z = x; // OK, y has type int&, z has type int const& }; }; } — end example]
An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type.
In the following contexts, an id-expression is move-eligible:

7.5.5.3 Qualified names [expr.prim.id.qual]

The component names of a qualified-id are those of its nested-name-specifier and unqualified-id.
The component names of a nested-name-specifier are its identifier (if any) and those of its type-name, namespace-name, simple-template-id, and/or nested-name-specifier.
A declarative nested-name-specifier shall not have a computed-type-specifier.
A declaration that uses a declarative nested-name-specifier shall be a friend declaration or inhabit a scope that contains the entity being redeclared or specialized.
The nested-name-specifier ​::​ nominates the global namespace.
A nested-name-specifier with a computed-type-specifier nominates the type denoted by the computed-type-specifier, which shall be a class or enumeration type.
If a nested-name-specifier N is declarative and has a simple-template-id with a template argument list A that involves a template parameter, let T be the template nominated by N without A.
T shall be a class template.
Any other nested-name-specifier nominates the entity denoted by its type-name, namespace-name, identifier, or simple-template-id.
If the nested-name-specifier is not declarative, the entity shall not be a template.
A qualified-id shall not be of the form nested-name-specifier template ~ computed-type-specifier nor of the form computed-type-specifier ​::​ ~ type-name.
The result of a qualified-id Q is the entity it denotes ([basic.lookup.qual]).
The type of the expression is the type of the result.
The result is an lvalue if the member is
  • a function other than a non-static member function,
  • a non-static member function if Q is the operand of a unary & operator,
  • a variable,
  • a structured binding ([dcl.struct.bind]), or
  • a data member,
and a prvalue otherwise.

7.5.5.4 Pack indexing expression [expr.prim.pack.index]

The id-expression P in a pack-index-expression shall be an identifier that denotes a pack.
The constant-expression shall be a converted constant expression ([expr.const]) of type std​::​size_t whose value V, termed the index, is such that .
[Note 1: 
A pack-index-expression denotes the element of the pack.
— end note]

7.5.5.5 Destruction [expr.prim.id.dtor]

An id-expression that denotes the destructor of a type T names the destructor of T if T is a class type ([class.dtor]), otherwise the id-expression is said to name a pseudo-destructor.
If the id-expression names a pseudo-destructor, T shall be a scalar type and the id-expression shall appear as the right operand of a class member access ([expr.ref]) that forms the postfix-expression of a function call ([expr.call]).
[Note 1: 
Such a call ends the lifetime of the object ([expr.call], [basic.life]).
— end note]
[Example 1: struct C { }; void f() { C * pc = new C; using C2 = C; pc->C::~C2(); // OK, destroys *pc C().C::~C(); // undefined behavior: temporary of type C destroyed twice using T = int; 0 .T::~T(); // OK, no effect 0.T::~T(); // error: 0.T is a user-defined-floating-point-literal ([lex.ext]) } — end example]

7.5.6 Lambda expressions [expr.prim.lambda]

7.5.6.1 General [expr.prim.lambda.general]

lambda-specifier:
consteval
constexpr
mutable
static
A lambda-expression provides a concise way to create a simple function object.
[Example 1: #include <algorithm> #include <cmath> void abssort(float* x, unsigned N) { std::sort(x, x + N, [](float a, float b) { return std::abs(a) < std::abs(b); }); } — end example]
A lambda-expression is a prvalue whose result object is called the closure object.
[Note 1: 
A closure object behaves like a function object.
— end note]
An ambiguity can arise because a requires-clause can end in an attribute-specifier-seq, which collides with the attribute-specifier-seq in lambda-expression.
In such cases, any attributes are treated as attribute-specifier-seq in lambda-expression.
[Note 2: 
Such ambiguous cases cannot have valid semantics because the constraint expression would not have type bool.
[Example 2: auto x = []<class T> requires T::operator int [[some_attribute]] (int) { } — end example]
— end note]
A lambda-specifier-seq shall contain at most one of each lambda-specifier and shall not contain both constexpr and consteval.
If the lambda-declarator contains an explicit object parameter ([dcl.fct]), then no lambda-specifier in the lambda-specifier-seq shall be mutable or static.
The lambda-specifier-seq shall not contain both mutable and static.
If the lambda-specifier-seq contains static, there shall be no lambda-capture.
[Note 3: 
The trailing requires-clause is described in [dcl.decl].
— end note]
If the lambda-declarator does not include a trailing-return-type, it is considered to be -> auto.
[Note 4: 
In that case, the return type is deduced from return statements as described in [dcl.spec.auto].
— end note]
[Example 3: auto x1 = [](int i) { return i; }; // OK, return type is int auto x2 = []{ return { 1, 2 }; }; // error: deducing return type from braced-init-list int j; auto x3 = [&]()->auto&& { return j; }; // OK, return type is int& — end example]
A lambda is a generic lambda if the lambda-expression has any generic parameter type placeholders ([dcl.spec.auto]), or if the lambda has a template-parameter-list.
[Example 4: auto x = [](int i, auto a) { return i; }; // OK, a generic lambda auto y = [](this auto self, int i) { return i; }; // OK, a generic lambda auto z = []<class T>(int i) { return i; }; // OK, a generic lambda — end example]

7.5.6.2 Closure types [expr.prim.lambda.closure]

The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.
[Note 1: 
This determines the set of namespaces and classes associated with the closure type ([basic.lookup.argdep]).
The parameter types of a lambda-declarator do not affect these associated namespaces and classes.
— end note]
The closure type is not an aggregate type ([dcl.init.aggr]); it is a structural type ([temp.param]) if and only if the lambda has no lambda-capture.
An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
An implementation shall not add members of rvalue reference type to the closure type.
The closure type for a lambda-expression has a public inline function call operator (for a non-generic lambda) or function call operator template (for a generic lambda) ([over.call]) whose parameters and return type are those of the lambda-expression's parameter-declaration-clause and trailing-return-type respectively, and whose template-parameter-list consists of the specified template-parameter-list, if any.
The requires-clause of the function call operator template is the requires-clause immediately following < template-parameter-list >, if any.
The trailing requires-clause of the function call operator or operator template is the requires-clause of the lambda-declarator, if any.
[Note 2: 
The function call operator template for a generic lambda can be an abbreviated function template ([dcl.fct]).
— end note]
[Example 1: auto glambda = [](auto a, auto&& b) { return a < b; }; bool b = glambda(3, 3.14); // OK auto vglambda = [](auto printer) { return [=](auto&& ... ts) { // OK, ts is a function parameter pack printer(std::forward<decltype(ts)>(ts)...); return [=]() { printer(ts ...); }; }; }; auto p = vglambda( [](auto v1, auto v2, auto v3) { std::cout << v1 << v2 << v3; } ); auto q = p(1, 'a', 3.14); // OK, outputs 1a3.14 q(); // OK, outputs 1a3.14 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 — end example]
Given a lambda with a lambda-capture, the type of the explicit object parameter, if any, of the lambda's function call operator (possibly instantiated from a function call operator template) shall be either:
  • the closure type,
  • a class type publicly and unambiguously derived from the closure type, or
  • a reference to a possibly cv-qualified such type.
[Example 2: struct C { template <typename T> C(T); }; void func(int i) { int x = [=](this auto&&) { return i; }(); // OK int y = [=](this C) { return i; }(); // error int z = [](this C) { return 42; }(); // OK } — end example]
The function call operator or operator template is a static member function or static member function template ([class.static.mfct]) if the lambda-expression's parameter-declaration-clause is followed by static.
Otherwise, it is a non-static member function or member function template ([class.mfct.non.static]) that is declared const ([class.mfct.non.static]) if and only if the lambda-expression's parameter-declaration-clause is not followed by mutable and the lambda-declarator does not contain an explicit object parameter.
It is neither virtual nor declared volatile.
Any noexcept-specifier specified on a lambda-expression applies to the corresponding function call operator or operator template.
An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator or operator template.
An attribute-specifier-seq in a lambda-expression preceding a 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 lambda-expression's parameter-declaration-clause is followed by constexpr or consteval, or it is constexpr-suitable ([dcl.constexpr]).
It is an immediate function ([dcl.constexpr]) if the corresponding lambda-expression's parameter-declaration-clause is followed by consteval.
[Example 3: auto ID = [](auto a) { return a; }; static_assert(ID(3) == 3); // OK struct NonLiteral { NonLiteral(int n) : n(n) { } int n; }; static_assert(ID(NonLiteral{3}).n == 3); // error — end example]
[Example 4: auto monoid = [](auto v) { return [=] { return v; }; }; auto add = [](auto m1) constexpr { auto ret = m1(); return [=](auto m2) mutable { auto m1val = m1(); auto plus = [=](auto m2val) mutable constexpr { return m1val += m2val; }; ret = plus(m2()); return monoid(ret); }; }; constexpr auto zero = monoid(0); constexpr auto one = monoid(1); static_assert(add(one)(zero)() == one()); // OK // Since two below is not declared constexpr, an evaluation of its constexpr member function call operator // cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture) // in a constant expression. auto two = monoid(2); assert(two() == 2); // OK, not a constant expression. static_assert(add(one)(one)() == two()); // error: two() is not a constant expression static_assert(add(one)(one)() == monoid(2)()); // OK — end example]
[Note 3: 
The function call operator or operator template can be constrained ([temp.constr.decl]) by a type-constraint ([temp.param]), a requires-clause ([temp.pre]), or a trailing requires-clause ([dcl.decl]).
[Example 5: template <typename T> concept C1 = /* ... */; template <std::size_t N> concept C2 = /* ... */; template <typename A, typename B> concept C3 = /* ... */; auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)> (T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> { // T2 is constrained by a type-constraint. // T1 and T2 are constrained by a requires-clause, and // T2 and the type of a4 are constrained by a trailing requires-clause. }; — end example]
— end note]
The closure type for a non-generic lambda-expression with no lambda-capture and no explicit object parameter ([dcl.fct]) whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type's function call operator.
The conversion is to “pointer to noexcept function” if the function call operator has a non-throwing exception specification.
If the function call operator is a static member function, then the value returned by this conversion function is a pointer to the function call operator.
Otherwise, the value returned by this conversion function is a pointer to a function F that, when invoked, has the same effect as invoking the closure type's function call operator on a default-constructed instance of the closure type.
F is a constexpr function if the function call operator is a constexpr function and is an immediate function if the function call operator is an immediate function.
For a generic lambda with no lambda-capture and no explicit object parameter ([dcl.fct]), the closure type has a conversion function template to pointer to function.
The conversion function template has the same invented template parameter list, and the pointer to function has the same parameter types, as the function call operator template.
The return type of the pointer to function shall behave as if it were a decltype-specifier denoting the return type of the corresponding function call operator template specialization.
[Note 4: 
If the generic lambda has no trailing-return-type or the trailing-return-type contains a placeholder type, return type deduction of the corresponding function call operator template specialization has to be done.
The corresponding specialization is that instantiation of the function call operator template with the same template arguments as those deduced for the conversion function template.
Consider the following: auto glambda = [](auto a) { return a; }; int (*fp)(int) = glambda;
The behavior of the conversion function of glambda above is like that of the following conversion function: struct Closure { template<class T> auto operator()(T t) const { /* ... */ } template<class T> static auto lambda_call_operator_invoker(T a) { // forwards execution to operator()(a) and therefore has // the same return type deduced /* ... */ } template<class T> using fptr_t = decltype(lambda_call_operator_invoker(declval<T>())) (*)(T); template<class T> operator fptr_t<T>() const { return &lambda_call_operator_invoker; } };
— end note]
[Example 6: void f1(int (*)(int)) { } void f2(char (*)(int)) { } void g(int (*)(int)) { } // #1 void g(char (*)(char)) { } // #2 void h(int (*)(int)) { } // #3 void h(char (*)(int)) { } // #4 auto glambda = [](auto a) { return a; }; 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 int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK — end example]
If the function call operator template is a static member function template, then the value returned by any given specialization of this conversion function template is a pointer to the corresponding function call operator template specialization.
Otherwise, the value returned by any given specialization of this conversion function template is a pointer to a function F that, when invoked, has the same effect as invoking the generic lambda's corresponding function call operator template specialization on a default-constructed instance of the closure type.
F is a constexpr function if the corresponding specialization is a constexpr function and F is an immediate function if the function call operator template specialization is an immediate function.
[Note 5: 
This will result in the implicit instantiation of the generic lambda's body.
The instantiated generic lambda's return type and parameter types need to match the return type and parameter types of the pointer to function.
— end note]
[Example 7: 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 GL(3) — end example]
The conversion function or conversion function template is public, constexpr, non-virtual, non-explicit, const, and has a non-throwing exception specification.
[Example 8: auto Fwd = [](int (*fp)(int), auto a) { return fp(a); }; auto C = [](auto a) { return a; }; static_assert(Fwd(C,3) == 3); // OK // No specialization of the function call operator template can be constexpr (due to the local static). auto NC = [](auto a) { static int s; return a; }; static_assert(Fwd(NC,3) == 3); // error — end example]
The lambda-expression's compound-statement yields the function-body ([dcl.fct.def]) of the function call operator, but it is not within the scope of the closure type.
[Example 9: struct S1 { int x, y; int operator()(int); void f() { [=]()->int { return operator()(this->x + y); // equivalent to S1​::​operator()(this->x + (*this).y) // this has type S1* }; } }; — end example]
Further, a variable __func__ is implicitly defined at the beginning of the compound-statement of the lambda-expression, with semantics as described in [dcl.fct.def.general].
The closure type associated with a lambda-expression has no default constructor if the lambda-expression has a lambda-capture and a defaulted default constructor otherwise.
It has a defaulted copy constructor and a defaulted move constructor ([class.copy.ctor]).
It has a deleted copy assignment operator if the lambda-expression has a lambda-capture and defaulted copy and move assignment operators otherwise ([class.copy.assign]).
[Note 6: 
These special member functions are implicitly defined as usual, which can result in them being defined as deleted.
— end note]
The closure type associated with a lambda-expression has an implicitly-declared destructor ([class.dtor]).
A member of a closure type shall not be explicitly instantiated, explicitly specialized, or named in a friend declaration.

7.5.6.3 Captures [expr.prim.lambda.capture]

simple-capture:
identifier ...
& identifier ...
this
* this
The body of a lambda-expression may refer to local entities of enclosing block scopes by capturing those entities, as described below.
If a lambda-capture includes a capture-default that is &, no identifier in a simple-capture of that lambda-capture shall be preceded by &.
If a lambda-capture includes a capture-default that is =, each simple-capture of that lambda-capture shall be of the form “& identifier ...”, “this”, or “* this.
[Note 1: 
The form [&,this] is redundant but accepted for compatibility with C++ 2014.
— end note]
Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture.
[Example 1: struct S2 { void f(int i); }; void S2::f(int i) { [&, i]{ }; // OK [&, this, i]{ }; // OK, equivalent to [&, i] [&, &i]{ }; // error: i preceded by & when & is the default [=, *this]{ }; // OK [=, this]{ }; // OK, equivalent to [=] [i, i]{ }; // error: i repeated [this, *this]{ }; // error: this appears twice } — end example]
A lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer unless its innermost enclosing scope is a block scope ([basic.scope.block]) or it appears within a default member initializer and its innermost enclosing scope is the corresponding class scope ([basic.scope.class]).
The identifier in a simple-capture shall denote a local entity ([basic.lookup.unqual], [basic.pre]).
The simple-captures this and * this denote the local entity *this.
An entity that is designated by a simple-capture is said to be explicitly captured.
If an identifier in a capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause or as the name of a template parameter of the lambda-expression's template-parameter-list, the program is ill-formed.
[Example 2: void f() { int x = 0; auto g = [x](int x) { return 0; }; // error: parameter and capture have the same name auto h = [y = 0]<typename y>(y) { return 0; }; // error: template parameter and capture // have the same name } — end example]
An init-capture inhabits the lambda scope ([basic.scope.lambda]) of the lambda-expression.
An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;”, except that:
  • if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways of referring to the same object, which has the lifetime of the non-static data member, and no additional copy and destruction is performed, and
  • if the capture is by reference, the variable's lifetime ends when the closure object's lifetime ends.
[Note 2: 
This enables an init-capture like “x = std​::​move(x)”; the second “x” must bind to a declaration in the surrounding context.
— end note]
[Example 3: int x = 4; auto y = [&r = x, x = x+1]()->int { r += 2; return x+2; }(); // Updates ​::​x to 6, and initializes y to 7. auto z = [a = 42](int a) { return 1; }; // error: parameter and conceptual local variable have the same name auto counter = [i=0]() mutable -> decltype(i) { // OK, returns int return i++; }; — end example]
For the purposes of lambda capture, an expression potentially references local entities as follows:
If an expression potentially references a local entity within a scope in which it is odr-usable ([basic.def.odr]), and the expression would be potentially evaluated if the effect of any enclosing typeid expressions ([expr.typeid]) were ignored, the entity is said to be implicitly captured by each intervening lambda-expression with an associated capture-default that does not explicitly capture it.
The implicit capture of *this is deprecated when the capture-default is =; see [depr.capture.this].
[Example 4: void f(int, const int (&)[2] = {}); // #1 void f(const int&, const int (&)[1]); // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK, calls #1, does not capture x }; auto g1 = [=](auto a) { f(x); // OK, calls #1, captures x }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; f(x, selector); // OK, captures x, can call #1 or #2 }; auto g3 = [=](auto a) { typeid(a + x); // captures x regardless of whether a + x is an unevaluated operand }; }
Within g1, an implementation can optimize away the capture of x as it is not odr-used.
— end example]
[Note 4: 
The set of captured entities is determined syntactically, and entities are implicitly captured even if the expression denoting a local entity is within a discarded statement ([stmt.if]).
[Example 5: template<bool B> void f(int n) { [=](auto a) { if constexpr (B && sizeof(a) > 4) { (void)n; // captures n regardless of the value of B and sizeof(int) } }(0); } — end example]
— end note]
An entity is captured if it is captured explicitly or implicitly.
An entity captured by a lambda-expression is odr-used ([basic.def.odr]) by the lambda-expression.
[Note 5: 
As a consequence, if a lambda-expression explicitly captures an entity that is not odr-usable, the program is ill-formed ([basic.def.odr]).
— end note]
[Example 6: void f1(int i) { int const N = 20; auto m1 = [=]{ int const M = 30; auto m2 = [i]{ int x[N][M]; // OK, N and M are not odr-used x[0][0] = i; // OK, i is explicitly captured by m2 and implicitly captured by m1 }; }; struct s1 { int f; void work(int n) { int m = n*n; int j = 40; auto m3 = [this,m] { auto m4 = [&,j] { // error: j not odr-usable due to intervening lambda m3 int x = n; // error: n is odr-used but not odr-usable due to intervening lambda m3 x += m; // OK, m implicitly captured by m4 and explicitly captured by m3 x += i; // error: i is odr-used but not odr-usable // due to intervening function and class scopes x += f; // OK, this captured implicitly by m4 and explicitly by m3 }; }; } }; } struct s2 { double ohseven = .007; auto f() { return [this] { return [*this] { return ohseven; // OK }; }(); } auto g() { return [] { return [*this] { }; // error: *this not captured by outer lambda-expression }(); } }; — end example]
[Note 6: 
Because local entities are not odr-usable within a default argument ([basic.def.odr]), a lambda-expression appearing in a default argument cannot implicitly or explicitly capture any local entity.
Such a lambda-expression can still have an init-capture if any full-expression in its initializer satisfies the constraints of an expression appearing in a default argument ([dcl.fct.default]).
— end note]
[Example 7: void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // error void g2(int = ([i]{ return 0; })()); // error void g3(int = ([=]{ return i; })()); // error void g4(int = ([=]{ return 0; })()); // OK void g5(int = ([]{ return sizeof i; })()); // OK void g6(int = ([x=1]{ return x; })()); // OK void g7(int = ([x=i]{ return x; })()); // error } — end example]
An entity is captured by copy if
For each entity captured by copy, an unnamed non-static data member is declared in the closure type.
The declaration order of these members is unspecified.
The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise.
A member of an anonymous union shall not be captured by copy.
Every id-expression within the compound-statement of a lambda-expression that is an odr-use ([basic.def.odr]) of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type.
[Note 7: 
An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type.
However, such an id-expression can still cause the implicit capture of the entity.
— end note]
If *this is captured by copy, each expression that odr-uses *this is transformed to instead refer to the corresponding unnamed data member of the closure type.
[Example 8: void f(const int*); void g() { const int N = 10; [=] { int arr[N]; // OK, not an odr-use, refers to variable with automatic storage duration f(&N); // OK, causes N to be captured; &N points to // the corresponding member of the closure type }; } — end example]
An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy.
It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference.
If declared, such non-static data members shall be of literal type.
[Example 9: // The inner closure type must be a literal type regardless of how reference captures are represented. static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4); — end example]
A bit-field or a member of an anonymous union shall not be captured by reference.
An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.
[Note 8: 
The validity of such captures is determined by the lifetime of the object to which the reference refers, not by the lifetime of the reference itself.
— end note]
[Example 10: auto h(int &r) { return [&] { ++r; // Valid after h returns if the lifetime of the // object to which r is bound has not ended }; } — end example]
If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambda-expression m1, then m2's capture is transformed as follows:
  • If m1 captures the entity by copy, m2 captures the corresponding non-static data member of m1's closure type; if m1 is not mutable, the non-static data member is considered to be const-qualified.
  • If m1 captures the entity by reference, m2 captures the same entity captured by m1.
[Example 11: 
The nested lambda-expressions and invocations below will output 123234.
int a = 1, b = 1, c = 1; auto m1 = [a, &b, &c]() mutable { auto m2 = [a, b, &c]() mutable { std::cout << a << b << c; a = 4; b = 4; c = 4; }; a = 3; b = 3; c = 3; m2(); }; a = 2; b = 2; c = 2; m1(); std::cout << a << b << c; — end example]
When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and the non-static data members corresponding to the init-captures are initialized as indicated by the corresponding initializer (which may be copy- or direct-initialization).
(For array members, the array elements are direct-initialized in increasing subscript order.)
These initializations are performed in the (unspecified) order in which the non-static data members are declared.
[Note 9: 
This ensures that the destructions will occur in the reverse order of the constructions.
— end note]
[Note 10: 
If a non-reference entity is implicitly or explicitly captured by reference, invoking the function call operator of the corresponding lambda-expression after the lifetime of the entity has ended is likely to result in undefined behavior.
— end note]
A simple-capture containing an ellipsis is a pack expansion ([temp.variadic]).
An init-capture containing an ellipsis is a pack expansion that declares an init-capture pack ([temp.variadic]).
[Example 12: template<class... Args> void f(Args... args) { auto lm = [&, args...] { return g(args...); }; lm(); auto lm2 = [...xs=std::move(args)] { return g(xs...); }; lm2(); } — end example]

7.5.7 Fold expressions [expr.prim.fold]

A fold expression performs a fold of a pack ([temp.variadic]) over a binary operator.
fold-operator: one of
+   -   *   /   %   ^   &   |   <<   >>
+=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=  =
==  !=  <   >   <=  >=  &&  ||  ,   .*   ->*
An expression of the form (... op e) where op is a fold-operator is called a unary left fold.
An expression of the form (e op ...) where op is a fold-operator is called a unary right fold.
Unary left folds and unary right folds are collectively called unary folds.
In a unary fold, the cast-expression shall contain an unexpanded pack ([temp.variadic]).
An expression of the form (e1 op1 ... op2 e2) where op1 and op2 are fold-operators is called a binary fold.
In a binary fold, op1 and op2 shall be the same fold-operator, and either e1 shall contain an unexpanded pack or e2 shall contain an unexpanded pack, but not both.
If e2 contains an unexpanded pack, the expression is called a binary left fold.
If e1 contains an unexpanded pack, the expression is called a binary right fold.
[Example 1: template<typename ...Args> bool f(Args ...args) { return (true && ... && args); // OK } template<typename ...Args> bool f(Args ...args) { return (args + ... + args); // error: both operands contain unexpanded packs } — end example]
A fold expression is a pack expansion.

7.5.8 Requires expressions [expr.prim.req]

7.5.8.1 General [expr.prim.req.general]

A requires-expression is a prvalue of type bool whose value is described below.
[Example 1: 
A common use of requires-expressions is to define requirements in concepts such as the one below: template<typename T> concept R = requires (T i) { typename T::type; {*i} -> std::convertible_to<const typename T::type&>; };
A requires-expression can also be used in a requires-clause ([temp.pre]) as a way of writing ad hoc constraints on template arguments such as the one below: template<typename T> requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }
The first requires introduces the requires-clause, and the second introduces the requires-expression.
— end example]
A requires-expression may introduce local parameters using a parameter-declaration-clause.
A local parameter of a requires-expression shall not have a default argument.
The type of such a parameter is determined as specified for a function parameter in [dcl.fct].
These parameters have no linkage, storage, or lifetime; they are only used as notation for the purpose of defining requirements.
The parameter-declaration-clause of a requirement-parameter-list shall not terminate with an ellipsis.
[Example 2: template<typename T> concept C = requires(T t, ...) { // error: terminates with an ellipsis t; }; template<typename T> concept C2 = requires(T p[2]) { (decltype(p))nullptr; // OK, p has type “pointer to T'' }; — end example]
The substitution of template arguments into a requires-expression can result in the formation of invalid types or expressions in the immediate context of its requirements ([temp.deduct.general]) or the violation of the semantic constraints of those requirements.
In such cases, the requires-expression evaluates to false; it does not cause the program to be ill-formed.
The substitution and semantic constraint checking proceeds in lexical order and stops when a condition that determines the result of the requires-expression is encountered.
If substitution (if any) and semantic constraint checking succeed, the requires-expression evaluates to true.
[Note 1: 
If a requires-expression contains invalid types or expressions in its requirements, and it does not appear within the declaration of a templated entity, then the program is ill-formed.
— end note]
If the substitution of template arguments into a requirement would always result in a substitution failure, the program is ill-formed; no diagnostic required.
[Example 3: template<typename T> concept C = requires { new decltype((void)T{}); // ill-formed, no diagnostic required }; — end example]

7.5.8.2 Simple requirements [expr.prim.req.simple]

A simple-requirement asserts the validity of an expression.
The expression is an unevaluated operand.
[Note 1: 
The enclosing requires-expression will evaluate to false if substitution of template arguments into the expression fails.
— end note]
[Example 1: template<typename T> concept C = requires (T a, T b) { a + b; // C<T> is true if a + b is a valid expression }; — end example]
A requirement that starts with a requires token is never interpreted as a simple-requirement.
[Note 2: 
This simplifies distinguishing between a simple-requirement and a nested-requirement.
— end note]

7.5.8.3 Type requirements [expr.prim.req.type]

A type-requirement asserts the validity of a type.
The component names of a type-requirement are those of its nested-name-specifier (if any) and type-name.
[Note 1: 
The enclosing requires-expression will evaluate to false if substitution of template arguments fails.
— end note]
[Example 1: template<typename T, typename T::type = 0> struct S; template<typename T> using Ref = T&; template<typename T> concept C = requires { typename T::inner; // required nested member name typename S<T>; // required valid ([temp.names]) template-id; // fails if T​::​type does not exist as a type to which 0 can be implicitly converted typename Ref<T>; // required alias template substitution, fails if T is void }; — end example]
A type-requirement that names a class template specialization does not require that type to be complete ([basic.types.general]).

7.5.8.4 Compound requirements [expr.prim.req.compound]

A compound-requirement asserts properties of the expression E.
The expression is an unevaluated operand.
Substitution of template arguments (if any) and verification of semantic properties proceed in the following order:
  • Substitution of template arguments (if any) into the expression is performed.
  • If the noexcept specifier is present, E shall not be a potentially-throwing expression ([except.spec]).
  • If the return-type-requirement is present, then:
    [Example 1: 
    Given concepts C and D, requires { { E1 } -> C; { E2 } -> D<A, , A>; }; is equivalent to requires { E1; requires C<decltype((E1))>; E2; requires D<decltype((E2)), A, , A>; }; (including in the case where n is zero).
    — end example]
[Example 2: template<typename T> concept C1 = requires(T x) { {x++}; };
The compound-requirement in C1 requires that x++ is a valid expression.
It is equivalent to the simple-requirement x++;.
template<typename T> concept C2 = requires(T x) { {*x} -> std::same_as<typename T::inner>; };
The compound-requirement in C2 requires that *x is a valid expression, that typename T​::​inner is a valid type, and that std​::​same_as<decltype((*x)), typename T​::​inner> is satisfied.
template<typename T> concept C3 = requires(T x) { {g(x)} noexcept; };
The compound-requirement in C3 requires that g(x) is a valid expression and that g(x) is non-throwing.
— end example]

7.5.8.5 Nested requirements [expr.prim.req.nested]

A nested-requirement can be used to specify additional constraints in terms of local parameters.
The constraint-expression shall be satisfied ([temp.constr.decl]) by the substituted template arguments, if any.
Substitution of template arguments into a nested-requirement does not result in substitution into the constraint-expression other than as specified in [temp.constr.constr].
[Example 1: 
template<typename U> concept C = sizeof(U) == 1; template<typename T> concept D = requires (T t) { requires C<decltype (+t)>; }; D<T> is satisfied if sizeof(decltype (+t)) == 1 ([temp.constr.atomic]).
— end example]

7.6 Compound expressions [expr.compound]

7.6.1 Postfix expressions [expr.post]

7.6.1.1 General [expr.post.general]

[Note 1: 
The > token following the type-id in a dynamic_cast, static_cast, reinterpret_cast, or const_cast can be the product of replacing a >> token by two consecutive > tokens ([temp.names]).
— end note]

7.6.1.2 Subscripting [expr.sub]

A subscript expression is a postfix expression followed by square brackets containing a possibly empty, comma-separated list of initializer-clauses that constitute the arguments to the subscript operator.
The postfix-expression and the initialization of the object parameter of any applicable subscript operator function is sequenced before each expression in the expression-list and also before any default argument.
The initialization of a non-object parameter of a subscript operator function S ([over.sub]), including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other non-object parameter of S.
With the built-in subscript operator, an expression-list shall be present, consisting of a single assignment-expression.
One of the expressions shall be a glvalue of type “array of T” or a prvalue of type “pointer to T” and the other shall be a prvalue of unscoped enumeration or integral type.
The result is of type “T.
The type “T” shall be a completely-defined object type.48
The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.
[Note 1: 
Despite its asymmetric appearance, subscripting is a commutative operation except for sequencing.
See [expr.unary] and [expr.add] for details of * and + and [dcl.array] for details of array types.
— end note]
48)48)
This is true even if the subscript operator is used in the following common idiom: &x[0].

7.6.1.3 Function call [expr.call]

A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of initializer-clauses which constitute the arguments to the function.
[Note 1: 
If the postfix expression is a function or member function name, the appropriate function and the validity of the call are determined according to the rules in [over.match].
— end note]
The postfix expression shall have function type or function pointer type.
For a call to a non-member function or to a static member function, the postfix expression shall be either an lvalue that refers to a function (in which case the function-to-pointer standard conversion ([conv.func]) is suppressed on the postfix expression), or a prvalue of function pointer type.
If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function is called.
Otherwise, its final overrider in the dynamic type of the object expression is called; such a call is referred to as a virtual function call.
[Note 2: 
The dynamic type is the type of the object referred to by the current value of the object expression.
[class.cdtor] describes the behavior of virtual function calls when the object expression refers to an object under construction or destruction.
— end note]
[Note 3: 
If a function or member function name is used, and name lookup does not find a declaration of that name, the program is ill-formed.
No function is implicitly declared by such a call.
— end note]
If the postfix-expression names a destructor or pseudo-destructor ([expr.prim.id.dtor]), the type of the function call expression is void; otherwise, the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different.
If the postfix-expression names a pseudo-destructor (in which case the postfix-expression is a possibly-parenthesized class member access), the function call destroys the object of scalar type denoted by the object expression of the class member access ([expr.ref], [basic.life]).
A type is call-compatible with a function type if is the same type as or if the type “pointer to ” can be converted to type “pointer to ” via a function pointer conversion ([conv.fctptr]).
Calling a function through an expression whose function type is not call-compatible with the type of the called function's definition results in undefined behavior.
[Note 4: 
This requirement allows the case when the expression has the type of a potentially-throwing function, but the called function has a non-throwing exception specification, and the function types are otherwise the same.
— end note]
When a function is called, each parameter ([dcl.fct]) is initialized ([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 ([over.call.func]), the list of provided arguments is preceded by the implied object argument for the purposes of this correspondence.
If there is no corresponding argument, the default argument for the parameter is used.
[Example 1: template<typename ...T> int f(int n = 0, T ...t); int x = f<int>(); // error: no argument for second function parameter — end example]
If the function is an implicit object member function, the object expression of the class member access shall be a glvalue and the implicit object parameter of the function ([over.match.funcs]) is initialized with that glvalue, converted as if by an explicit type conversion.
[Note 5: 
There is no access or ambiguity checking on this conversion; the access checking and disambiguation are done as part of the (possibly implicit) class member access operator.
— end note]
When a function is called, the type of any parameter shall not be a class type that is either incomplete or abstract.
[Note 6: 
This still allows a parameter to be a pointer or reference to such a type.
However, it prevents a passed-by-value parameter to have an incomplete or abstract class type.
— end note]
It is implementation-defined whether a parameter is destroyed when the function in which it is defined exits ([stmt.return], [except.ctor]) or at the end of the enclosing full-expression; parameters are always destroyed in the reverse order of their construction.
The initialization and destruction of each parameter occurs within the context of the full-expression ([intro.execution]) where the function call appears.
[Example 2: 
The access ([class.access.general]) of the constructor, conversion functions, or destructor is checked at the point of call.
If a constructor or destructor for a function parameter throws an exception, any function-try-block ([except.pre]) of the called function with a handler that can handle the exception is not considered.
— end example]
The postfix-expression is sequenced before each expression in the expression-list and any default argument.
The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.
[Note 7: 
All side effects of argument evaluations are sequenced before the function is entered (see [intro.execution]).
— end note]
[Example 3: void f() { std::string s = "but I have heard it works even if you don't believe in it"; s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, ""); assert(s == "I have heard it works only if you believe in it"); // OK } — end example]
[Note 8: 
If an operator function is invoked using operator notation, argument evaluation is sequenced as specified for the built-in operator; see [over.match.oper].
— end note]
[Example 4: struct S { S(int); }; int operator<<(S, int); int i, j; int x = S(i=1) << (i=2); int y = operator<<(S(j=1), j=2);
After performing the initializations, the value of i is 2 (see [expr.shift]), but it is unspecified whether the value of j is 1 or 2.
— end example]
The result of a function call is the result of the possibly-converted operand of the return statement ([stmt.return]) that transferred control out of the called function (if any), except in a virtual function call if the return type of the final overrider is different from the return type of the statically chosen function, the value returned from the final overrider is converted to the return type of the statically chosen function.
[Note 9: 
A function can change the values of its non-const parameters, but these changes cannot affect the values of the arguments except where a parameter is of a reference type ([dcl.ref]); if the reference is to a const-qualified type, const_cast needs to be used to cast away the constness in order to modify the argument's value.
Where a parameter is of const reference type a temporary object is introduced if needed ([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]
A function can be declared to accept fewer arguments (by declaring default arguments) or more arguments (by using the ellipsis, ..., or a function parameter pack ([dcl.fct])) than the number of parameters in the function definition.
[Note 10: 
This implies that, except where the ellipsis (...) or a function parameter pack is used, a parameter is available for each argument.
— end note]
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg.
[Note 11: 
This paragraph does not apply to arguments passed to a function parameter pack.
Function parameter packs are expanded during template instantiation ([temp.variadic]), thus each such argument has a corresponding parameter when a function template specialization is actually called.
— end note]
The lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the argument expression.
An argument that has type cv std​::​nullptr_t is converted to type void* ([conv.ptr]).
After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer-to-member, or class type, the program is ill-formed.
Passing a potentially-evaluated argument of a scoped enumeration type ([dcl.enum]) or of a class type ([class]) having an eligible non-trivial copy constructor ([special], [class.copy.ctor]), an eligible non-trivial move constructor, or a non-trivial destructor ([class.dtor]), with no corresponding parameter, is conditionally-supported with implementation-defined semantics.
If the argument has integral or enumeration type that is subject to the integral promotions, or a floating-point type that is subject to the floating-point promotion, the value of the argument is converted to the promoted type before the call.
These promotions are referred to as the default argument promotions.
Recursive calls are permitted, except to the main function.
A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.
If it is a non-void prvalue, the type of the function call expression shall be complete, except as specified in [dcl.type.decltype].

7.6.1.4 Explicit type conversion (functional notation) [expr.type.conv]

A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by overload resolution for class template deduction for the remainder of this subclause.
Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction ([dcl.type.auto.deduct]).
Let T denote the resulting type.
Then:
  • If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression ([expr.cast]).
  • Otherwise, if T is cv void, the initializer shall be () or {} (after pack expansion, if any), and the expression is a prvalue of type void that performs no initialization.
  • Otherwise, if T is a reference type, the expression has the same effect as direct-initializing an invented variable t of type T from the initializer and then using t as the result of the expression; the result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue otherwise.
  • Otherwise, the expression is a prvalue of type T whose result object is direct-initialized ([dcl.init]) with the initializer.
If the initializer is a parenthesized optional expression-list, T shall not be an array type.
[Example 1: struct A {}; void f(A&); // #1 void f(A&&); // #2 A& g(); void h() { f(g()); // calls #1 f(A(g())); // calls #2 with a temporary object f(auto(g())); // calls #2 with a temporary object } — end example]

7.6.1.5 Class member access [expr.ref]

A postfix expression followed by a dot . or an arrow ->, optionally followed by the keyword template, and then followed by an id-expression, is a postfix expression.
[Note 1: 
If the keyword template is used, the following unqualified name is considered to refer to a template ([temp.names]).
If a simple-template-id results and is followed by a ​::​, the id-expression is a qualified-id.
— end note]
For the first option (dot), if the id-expression names a static member or an enumerator, the first expression is a discarded-value expression ([expr.context]); if the id-expression names a non-static data member, the first expression shall be a glvalue.
For the second option (arrow), the first expression shall be a prvalue having pointer type.
The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of [expr.ref] will address only the first option (dot).49
The postfix expression before the dot is evaluated;50 the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.
Abbreviating postfix-expression.id-expression as E1.E2, E1 is called the object expression.
If the object expression is of scalar type, E2 shall name the pseudo-destructor of that same type (ignoring cv-qualifications) and E1.E2 is a prvalue of type “function of () returning void.
[Note 2: 
This value can only be used for a notional function call ([expr.prim.id.dtor]).
— end note]
Otherwise, the object expression shall be of class type.
The class type shall be complete unless the class member access appears in the definition of that class.
[Note 3: 
The program is ill-formed if the result differs from that when the class is complete ([class.member.lookup]).
— end note]
[Note 4: 
[basic.lookup.qual] describes how names are looked up after the . and -> operators.
— end note]
If E2 is a bit-field, E1.E2 is a bit-field.
The type and value category of E1.E2 are determined as follows.
In the remainder of [expr.ref], cq represents either const or the absence of const and vq represents either volatile or the absence of volatile.
cv represents an arbitrary set of cv-qualifiers, as defined in [basic.type.qualifier].
If E2 is declared to have type “reference to T”, then E1.E2 is an lvalue of type T.
If E2 is a static data member, E1.E2 designates the object or function to which the reference is bound, otherwise E1.E2 designates the object or function to which the corresponding reference member of E1 is bound.
Otherwise, one of the following rules applies.
  • If E2 is a static data member and the type of E2 is T, then E1.E2 is an lvalue; the expression designates the named member of the class.
    The type of E1.E2 is T.
  • If E2 is a non-static data member and the type of E1 is “cq1 vq1 X”, and the type of E2 is “cq2 vq2 T”, the expression designates the corresponding member subobject of the object designated by the first expression.
    If E1 is an lvalue, then E1.E2 is an lvalue; otherwise E1.E2 is an xvalue.
    Let the notation vq12 stand for the “union” of vq1 and vq2; that is, if vq1 or vq2 is volatile, then vq12 is volatile.
    Similarly, let the notation cq12 stand for the “union” of cq1 and cq2; that is, if cq1 or cq2 is const, then cq12 is const.
    If E2 is declared to be a mutable member, then the type of E1.E2 is “vq12 T.
    If E2 is not declared to be a mutable member, then the type of E1.E2 is “cq12 vq12 T.
  • If E2 is an overload set, the expression shall be the (possibly-parenthesized) left-hand operand of a member function call ([expr.call]), and function overload resolution ([over.match]) is used to select the function to which E2 refers.
    The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2.
    • If E2 refers to a static member function, E1.E2 is an lvalue.
    • Otherwise (when E2 refers to a non-static member function), E1.E2 is a prvalue.
      [Note 5: 
      Any redundant set of parentheses surrounding the expression is ignored ([expr.prim.paren]).
      — end note]
  • If E2 is a nested type, the expression E1.E2 is ill-formed.
  • If E2 is a member enumerator and the type of E2 is T, the expression E1.E2 is a prvalue of type T whose value is the value of the enumerator.
If E2 is a non-static member, the program is ill-formed if the class of which E2 is directly a member is an ambiguous base ([class.member.lookup]) of the naming class ([class.access.base]) of E2.
[Note 6: 
The program is also ill-formed if the naming class is an ambiguous base of the class type of the object expression; see [class.access.base].
— end note]
If E2 is a non-static member and the result of E1 is an object whose type is not similar ([conv.qual]) to the type of E1, the behavior is undefined.
[Example 1: struct A { int i; }; struct B { int j; }; struct D : A, B {}; void f() { D d; static_cast<B&>(d).j; // OK, object expression designates the B subobject of d reinterpret_cast<B&>(d).j; // undefined behavior } — end example]
49)49)
Note that (*(E1)) is an lvalue.
50)50)
If the class member access expression is evaluated, the subexpression evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.

7.6.1.6 Increment and decrement [expr.post.incr]

The value of a postfix ++ expression is the value obtained by applying the lvalue-to-rvalue conversion ([conv.lval]) to its operand.
[Note 1: 
The value obtained is a copy of the original value.
— end note]
The operand shall be a modifiable lvalue.
The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a complete object type.
An operand with volatile-qualified type is deprecated; see [depr.volatile.type].
The value of the operand object is modified ([defns.access]) as if it were the operand of the prefix ++ operator ([expr.pre.incr]).
The value computation of the ++ expression is sequenced before the modification of the operand object.
With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation.
[Note 2: 
Therefore, a function call cannot intervene between the lvalue-to-rvalue conversion and the side effect associated with any single postfix ++ operator.
— end note]
The result is a prvalue.
The type of the result is the cv-unqualified version of the type of the operand.
The operand of postfix -- is decremented analogously to the postfix ++ operator.
[Note 3: 
For prefix increment and decrement, see [expr.pre.incr].
— end note]

7.6.1.7 Dynamic cast [expr.dynamic.cast]

The result of the expression dynamic_cast<T>(v) is the result of converting the expression v to type T.
T shall be a pointer or reference to a complete class type, or “pointer to cv void.
The dynamic_cast operator shall not cast away constness ([expr.const.cast]).
If T is a pointer type, v shall be a prvalue of a pointer to complete class type, and the result is a prvalue of type T.
If T is an lvalue reference type, v shall be an lvalue of a complete class type, and the result is an lvalue of the type referred to by T.
If T is an rvalue reference type, v shall be a glvalue having a complete class type, and the result is an xvalue of the type referred to by T.
If the type of v is the same as T (ignoring cv-qualifications), the result is v (converted if necessary).
If T is “pointer to cv1 B” and v has type “pointer to cv2 D” such that B is a base class of D, the result is a pointer to the unique B subobject of the D object pointed to by v, or a null pointer value if v is a null pointer value.
Similarly, if T is “reference to cv1 B” and v has type cv2 D such that B is a base class of D, the result is the unique B subobject of the D object referred to by v.51
In both the pointer and reference cases, the program is ill-formed if B is an inaccessible or ambiguous base class of D.
[Example 1: struct B { }; struct D : B { }; void foo(D* dp) { B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp; } — end example]
Otherwise, v shall be a pointer to or a glvalue of a polymorphic type.
If v is a null pointer value, the result is a null pointer value.
If v has type “pointer to cv U” and v does not point to an object whose type is similar ([conv.qual]) to U and that is within its lifetime or within its period of construction or destruction ([class.cdtor]), the behavior is undefined.
If v is a glvalue of type U and v does not refer to an object whose type is similar to U and that is within its lifetime or within its period of construction or destruction, the behavior is undefined.
If T is “pointer to cv void”, then the result is a pointer to the most derived object pointed to by v.
Otherwise, a runtime check is applied to see if the object pointed or referred to by v can be converted to the type pointed or referred to by T.
Let C be the class type to which T points or refers.
The runtime check logically executes as follows:
  • If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class subobject of a C object, and if only one object of type C is derived from the subobject pointed (referred) to by v, the result points (refers) to that C object.
  • Otherwise, if v points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has a base class, of type C, that is unambiguous and public, the result points (refers) to the C subobject of the most derived object.
  • Otherwise, the runtime check fails.
The value of a failed cast to pointer type is the null pointer value of the required result type.
A failed cast to reference type throws an exception of a type that would match a handler of type std​::​bad_cast.
[Example 2: class A { virtual void f(); }; class B { virtual void g(); }; class D : public virtual A, private B { }; void g() { D d; B* bp = (B*)&d; // cast needed to break protection A* ap = &d; // public derivation, no cast needed D& dr = dynamic_cast<D&>(*bp); // fails ap = dynamic_cast<A*>(bp); // fails bp = dynamic_cast<B*>(ap); // fails ap = dynamic_cast<A*>(&d); // succeeds bp = dynamic_cast<B*>(&d); // ill-formed (not a runtime check) } class E : public D, public B { }; class F : public E, public D { }; void h() { F f; A* ap = &f; // succeeds: finds unique A D* dp = dynamic_cast<D*>(ap); // fails: yields null; f has two D subobjects E* ep = (E*)ap; // error: cast from virtual base E* ep1 = dynamic_cast<E*>(ap); // succeeds } — end example]
[Note 1: 
Subclause [class.cdtor] describes the behavior of a dynamic_cast applied to an object under construction or destruction.
— end note]
51)51)
The most derived object ([intro.object]) pointed or referred to by v can contain other B objects as base classes, but these are ignored.

7.6.1.8 Type identification [expr.typeid]

The result of a typeid expression is an lvalue of static type const std​::​type_info ([type.info]) and dynamic type const std​::​type_info or const name where name is an implementation-defined class publicly derived from std​::​type_info which preserves the behavior described in [type.info].52
The lifetime of the object referred to by the lvalue extends to the end of the program.
Whether or not the destructor is called for the std​::​type_info object at the end of the program is unspecified.
If the type of the expression or type-id operand is a (possibly cv-qualified) class type or a reference to (possibly cv-qualified) class type, that class shall be completely defined.
If an expression operand of typeid is a possibly-parenthesized unary-expression whose unary-operator is * and whose operand evaluates to a null pointer value ([basic.compound]), the typeid expression throws an exception ([except.throw]) of a type that would match a handler of type std​::​bad_typeid ([bad.typeid]).
[Note 1: 
In other contexts, evaluating such a unary-expression results in undefined behavior ([expr.unary.op]).
— end note]
When typeid is applied to a glvalue whose type is a polymorphic class type ([class.virtual]), the result refers to a std​::​type_info object representing the type of the most derived object ([intro.object]) (that is, the dynamic type) to which the glvalue refers.
When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std​::​type_info object representing the static type of the expression.
Lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions are not applied to the expression.
If the expression is a prvalue, the temporary materialization conversion is applied.
The expression is an unevaluated operand.
When typeid is applied to a type-id, the result refers to a std​::​type_info object representing the type of the type-id.
If the type of the type-id is a reference to a possibly cv-qualified type, the result of the typeid expression refers to a std​::​type_info object representing the cv-unqualified referenced type.
[Note 2: 
The type-id cannot denote a function type with a cv-qualifier-seq or a ref-qualifier ([dcl.fct]).
— end note]
If the type of the expression or type-id is a cv-qualified type, the result of the typeid expression refers to a std​::​type_info object representing the cv-unqualified type.
[Example 1: class D { /* ... */ }; D d1; const D d2; typeid(d1) == typeid(d2); // yields true typeid(D) == typeid(const D); // yields true typeid(D) == typeid(d2); // yields true typeid(D) == typeid(const D&); // yields true — end example]
The type std​::​type_info ([type.info]) is not predefined; if a standard library declaration ([typeinfo.syn], [std.modules]) of std​::​type_info does not precede ([basic.lookup.general]) a typeid expression, the program is ill-formed.
[Note 3: 
Subclause [class.cdtor] describes the behavior of typeid applied to an object under construction or destruction.
— end note]
52)52)
The recommended name for such a class is extended_type_info.

7.6.1.9 Static cast [expr.static.cast]

The result of the expression static_cast<T>(v) is the result of converting the expression v to type T.
If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue.
The static_cast operator shall not cast away constness ([expr.const.cast]).
An lvalue of type “cv1 B”, where B is a class type, can be cast to type “reference to cv2 D”, where D is a complete class derived ([class.derived]) from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from “pointer to D” to “pointer to B” exists ([conv.ptr]), the program is ill-formed.
An xvalue of type “cv1 B” can be cast to type “rvalue reference to cv2 D” with the same constraints as for an lvalue of type “cv1 B.
If the object of type “cv1 B” is actually a base class subobject of an object of type D, the result refers to the enclosing object of type D.
Otherwise, the behavior is undefined.
[Example 1: struct B { }; struct D : public B { }; D d; B &br = d; static_cast<D&>(br); // produces lvalue denoting the original d object — end example]
An lvalue of type T1 can be cast to type “rvalue reference to T2” if T2 is reference-compatible with T1 ([dcl.init.ref]).
If the value is not a bit-field, the result refers to the object or the specified base class subobject thereof; otherwise, the lvalue-to-rvalue conversion is applied to the bit-field and the resulting prvalue is used as the operand of the static_cast for the remainder of this subclause.
If T2 is an inaccessible ([class.access]) or ambiguous ([class.member.lookup]) base class of T1, a program that necessitates such a cast is ill-formed.
Any expression can be explicitly converted to type cv void, in which case the operand is a discarded-value expression ([expr.prop]).
[Note 1: 
Such a static_cast has no result as it is a prvalue of type void; see [basic.lval].
— end note]
[Note 2: 
However, if the value is in a temporary object ([class.temporary]), the destructor for that object is not executed until the usual time, and the value of the object is preserved for the purpose of executing the destructor.
— end note]
Otherwise, an expression E can be explicitly converted to a type T if there is an implicit conversion sequence ([over.best.ics]) from E to T, if overload resolution for a direct-initialization ([dcl.init]) of an object or reference of type T from E would find at least one viable function ([over.match.viable]), or if T is an aggregate type ([dcl.init.aggr]) having a first element x and there is an implicit conversion sequence from E to the type of x.
If T is a reference type, the effect is the same as performing the declaration and initialization T t(E); for some invented temporary variable t ([dcl.init]) and then using the temporary variable as the result of the conversion.
Otherwise, the result object is direct-initialized from E.
[Note 3: 
The conversion is ill-formed when attempting to convert an expression of class type to an inaccessible or ambiguous base class.
— end note]
[Note 4: 
If T is “array of unknown bound of U”, this direct-initialization defines the type of the expression as U[1].
— end note]
Otherwise, the inverse of a standard conversion sequence ([conv]) not containing an lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), function-to-pointer ([conv.func]), null pointer ([conv.ptr]), null member pointer ([conv.mem]), boolean ([conv.bool]), or function pointer ([conv.fctptr]) conversion, can be performed explicitly using static_cast.
A program is ill-formed if it uses static_cast to perform the inverse of an ill-formed standard conversion sequence.
[Example 2: struct B { }; struct D : private B { }; void f() { static_cast<D*>((B*)0); // error: B is a private base of D static_cast<int B::*>((int D::*)0); // error: B is a private base of D } — end example]
The lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) conversions are applied to the operand.
Such a static_cast is subject to the restriction that the explicit conversion does not cast away constness ([expr.const.cast]), and the following additional rules for specific cases:
A value of a scoped enumeration type ([dcl.enum]) can be explicitly converted to an integral type; the result is the same as that of converting to the enumeration's underlying type and then to the destination type.
A value of a scoped enumeration type can also be explicitly converted to a floating-point type; the result is the same as that of converting from the original value to the floating-point type.
A value of integral or enumeration type can be explicitly converted to a complete enumeration type.
If the enumeration type has a fixed underlying type, the value is first converted to that type by integral promotion ([conv.prom]) or integral conversion ([conv.integral]), if necessary, and then to the enumeration type.
If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values ([dcl.enum]), and otherwise, the behavior is undefined.
A value of floating-point type can also be explicitly converted to an enumeration type.
The resulting value is the same as converting the original value to the underlying type of the enumeration ([conv.fpint]), and subsequently to the enumeration type.
A prvalue of floating-point type can be explicitly converted to any other floating-point type.
If the source value can be exactly represented in the destination type, the result of the conversion has that exact representation.
If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values.
Otherwise, the behavior is undefined.
A prvalue of type “pointer to cv1 B”, where B is a class type, can be converted to a prvalue of type “pointer to cv2 D”, where D is a complete class derived from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from “pointer to D” to “pointer to B” exists ([conv.ptr]), the program is ill-formed.
The null pointer value ([basic.compound]) is converted to the null pointer value of the destination type.
If the prvalue of type “pointer to cv1 B” points to a B that is actually a base class subobject of an object of type D, the resulting pointer points to the enclosing object of type D.
Otherwise, the behavior is undefined.
A prvalue of type “pointer to member of D of type cv1 T” can be converted to a prvalue of type “pointer to member of B of type cv2 T”, where D is a complete class type and B is a base class of D, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
[Note 5: 
Function types (including those used in pointer-to-member-function types) are never cv-qualified ([dcl.fct]).
— end note]
If no valid standard conversion from “pointer to member of B of type T” to “pointer to member of D of type T” exists ([conv.mem]), the program is ill-formed.
The null member pointer value is converted to the null member pointer value of the destination type.
If class B contains the original member, or is a base class of the class containing the original member, the resulting pointer to member points to the original member.
Otherwise, the behavior is undefined.
[Note 6: 
Although class B need not contain the original member, the dynamic type of the object with which indirection through the pointer to member is performed must contain the original member; see [expr.mptr.oper].
— end note]
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value ([basic.compound]) is unspecified.
Otherwise, if the original pointer value points to an object a, and there is an object b of type similar to T that is pointer-interconvertible with a, the result is a pointer to b.
Otherwise, the pointer value is unchanged by the conversion.
[Example 3: T* p1 = new T; const T* p2 = static_cast<const T*>(static_cast<void*>(p1)); bool b = p1 == p2; // b will have the value true. — end example]
No other conversion can be performed using static_cast.

7.6.1.10 Reinterpret cast [expr.reinterpret.cast]

The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the expression v.
Conversions that can be performed explicitly using reinterpret_cast are listed below.
No other conversion can be performed explicitly using reinterpret_cast.
The reinterpret_cast operator shall not cast away constness ([expr.const.cast]).
An expression of integral, enumeration, pointer, or pointer-to-member type can be explicitly converted to its own type; such a cast yields the value of its operand.
[Note 1: 
The mapping performed by reinterpret_cast might, or might not, produce a representation different from the original value.
— end note]
A pointer can be explicitly converted to any integral type large enough to hold all values of its type.
The mapping function is implementation-defined.
[Note 2: 
It is intended to be unsurprising to those who know the addressing structure of the underlying machine.
— end note]
A value of type std​::​nullptr_t can be converted to an integral type; the conversion has the same meaning and validity as a conversion of (void*)0 to the integral type.
[Note 3: 
A reinterpret_cast cannot be used to convert a value of any type to the type std​::​nullptr_t.
— end note]
A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value ([basic.compound]); mappings between pointers and integers are otherwise implementation-defined.
A function pointer can be explicitly converted to a function pointer of a different type.
[Note 4: 
The effect of calling a function through a pointer to a function type ([dcl.fct]) that is not the same as the type used in the definition of the function is undefined ([expr.call]).
— end note]
Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
An object pointer can be explicitly converted to an object pointer of a different type.53
When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v)).
[Note 5: 
Converting a pointer of type “pointer to T1” that points to an object of type T1 to the type “pointer to T2” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value.
— end note]
Converting a function pointer to an object pointer type or vice versa is conditionally-supported.
The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.
The null pointer value ([basic.compound]) is converted to the null pointer value of the destination type.
[Note 6: 
A null pointer constant of type std​::​nullptr_t cannot be converted to a pointer type, and a null pointer constant of integral type is not necessarily converted to a null pointer value.
— end note]
A prvalue of type “pointer to member of X of type T1” can be explicitly converted to a prvalue of a different type “pointer to member of Y of type T2” if T1 and T2 are both function types or both object types.54
The null member pointer value ([conv.mem]) is converted to the null member pointer value of the destination type.
The result of this conversion is unspecified, except in the following cases:
  • Converting a prvalue of type “pointer to member function” to a different pointer-to-member-function type and back to its original type yields the original pointer-to-member value.
  • Converting a prvalue of type “pointer to data member of X of type T1” to the type “pointer to data member of Y of type T2” (where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer-to-member value.
If v is a glvalue of type T1, designating an object or function x, it can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast.
The result is that of *reinterpret_cast<T2 *>(p) where p is a pointer to x of type “pointer to T1.
[Note 7: 
No temporary is materialized ([conv.rval]) or created, no copy is made, and no constructors ([class.ctor]) or conversion functions ([class.conv]) are called.55
— end note]
53)53)
The types can have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness.
54)54)
T1 and T2 can have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness.
55)55)
This is sometimes referred to as a type pun when the result refers to the same object as the source glvalue.

7.6.1.11 Const cast [expr.const.cast]

The result of the expression const_cast<T>(v) is of type T.
If T is an lvalue reference to object type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are performed on the expression v.
The temporary materialization conversion is not performed on v, other than as specified below.
Conversions that can be performed explicitly using const_cast are listed below.
No other conversion shall be performed explicitly using const_cast.
[Note 1: 
Subject to the restrictions in this subclause, an expression can be cast to its own type using a const_cast operator.
— end note]
For two similar object pointer or pointer to data member types T1 and T2 ([conv.qual]), a prvalue of type T1 can be explicitly converted to the type T2 using a const_cast if, considering the qualification-decompositions of both types, each is the same as for all i.
If v is a null pointer or null member pointer, the result is a null pointer or null member pointer, respectively.
Otherwise, the result points to or past the end of the same object, or points to the same member, respectively, as v.
For two object types T1 and T2, if a pointer to T1 can be explicitly converted to the type “pointer to T2” using a const_cast, then the following conversions can also be made:
  • an lvalue of type T1 can be explicitly converted to an lvalue of type T2 using the cast const_cast<T2&>;
  • a glvalue of type T1 can be explicitly converted to an xvalue of type T2 using the cast const_cast<T2&&>; and
  • if T1 is a class or array type, a prvalue of type T1 can be explicitly converted to an xvalue of type T2 using the cast const_cast<T2&&>.
    The temporary materialization conversion is performed on v.
The result refers to the same object as the (possibly converted) operand.
[Example 1: typedef int *A[3]; // array of 3 pointer to int typedef const int *const CA[3]; // array of 3 const pointer to const int auto &&r2 = const_cast<A&&>(CA{}); // OK, temporary materialization conversion is performed — end example]
[Note 2: 
Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier56 can produce undefined behavior ([dcl.type.cv]).
— end note]
A conversion from a type T1 to a type T2 casts away constness if T1 and T2 are different, there is a qualification-decomposition ([conv.qual]) of T1 yielding n such that T2 has a qualification-decomposition of the form , and there is no qualification conversion that converts T1 to .
Casting from an lvalue of type T1 to an lvalue of type T2 using an lvalue reference cast or casting from an expression of type T1 to an xvalue of type T2 using an rvalue reference cast casts away constness if a cast from a prvalue of type “pointer to T1” to the type “pointer to T2” casts away constness.
[Note 3: 
Some conversions which involve only changes in cv-qualification cannot be done using const_cast.
For instance, conversions between pointers to functions are not covered because such conversions lead to values whose use causes undefined behavior.
For the same reasons, conversions between pointers to member functions, and in particular, the conversion from a pointer to a const member function to a pointer to a non-const member function, are not covered.
— end note]
56)56)
const_cast is not limited to conversions that cast away a const-qualifier.

7.6.2 Unary expressions [expr.unary]

7.6.2.2 Unary operators [expr.unary.op]

The unary * operator performs indirection.
Its operand shall be a prvalue of type “pointer to T”, where T is an object or function type.
The operator yields an lvalue of type T.
If the operand points to an object or function, the result denotes that object or function; otherwise, the behavior is undefined except as specified in [expr.typeid].
[Note 1: 
Indirection through a pointer to an incomplete type (other than cv void) is valid.
The lvalue thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to a prvalue, see [conv.lval].
— end note]
Each of the following unary operators yields a prvalue.
The operand of the unary & operator shall be an lvalue of some type T.
  • If the operand is a qualified-id naming a non-static or variant member m of some class C, other than an explicit object member function, the result has type “pointer to member of class C of type T” and designates C​::​m.
  • Otherwise, the result has type “pointer to T” and points to the designated object ([intro.memory]) or function ([basic.compound]).
    If the operand names an explicit object member function ([dcl.fct]), the operand shall be a qualified-id.
    [Note 2: 
    In particular, taking the address of a variable of type “cv T” yields a pointer of type “pointer to cv T.
    — end note]
[Example 1: struct A { int i; }; struct B : A { }; ... &B::i ... // has type int A​::​* int a; int* p1 = &a; int* p2 = p1 + 1; // defined behavior bool b = p2 > p1; // defined behavior, with value true — end example]
[Note 3: 
A pointer to member formed from a mutable non-static data member ([dcl.stc]) does not reflect the mutable specifier associated with the non-static data member.
— end note]
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses.
[Note 4: 
That is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member”.
Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” ([conv.func]).
Nor is &unqualified-id a pointer to member, even within the scope of the unqualified-id's class.
— end note]
If & is applied to an lvalue of incomplete class type and the complete type declares operator&(), it is unspecified whether the operator has the built-in meaning or the operator function is called.
The operand of & shall not be a bit-field.
[Note 5: 
The address of an overload set ([over]) can be taken only in a context that uniquely determines which function is referred to (see [over.over]).
Since the context can affect whether the operand is a static or non-static member function, the context can also affect whether the expression has type “pointer to function” or “pointer to member function”.
— end note]
The operand of the unary + operator shall be a prvalue of arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument.
Integral promotion is performed on integral or enumeration operands.
The type of the result is the type of the promoted operand.
The operand of the unary - operator shall be a prvalue of arithmetic or unscoped enumeration type and the result is the negative of its operand.
Integral promotion is performed on integral or enumeration operands.
The negative of an unsigned quantity is computed by subtracting its value from , where n is the number of bits in the promoted operand.
The type of the result is the type of the promoted operand.
[Note 6: 
The result is the two's complement of the operand (where operand and result are considered as unsigned).
— end note]
The operand of the logical negation operator ! is contextually converted to bool ([conv]); its value is true if the converted operand is false and false otherwise.
The type of the result is bool.
The operand of the ~ operator shall be a prvalue of integral or unscoped enumeration type.
Integral promotions are performed.
The type of the result is the type of the promoted operand.
Given the coefficients of the base-2 representation ([basic.fundamental]) of the promoted operand x, the coefficient of the base-2 representation of the result r is 1 if is 0, and 0 otherwise.
[Note 7: 
The result is the ones' complement of the operand (where operand and result are considered as unsigned).
— end note]
There is an ambiguity in the grammar when ~ is followed by a type-name or computed-type-specifier.
The ambiguity is resolved by treating ~ as the operator rather than as the start of an unqualified-id naming a destructor.
[Note 8: 
Because the grammar does not permit an operator to follow the ., ->, or ​::​ tokens, a ~ followed by a type-name or computed-type-specifier in a member access expression or qualified-id is unambiguously parsed as a destructor name.
— end note]

7.6.2.3 Increment and decrement [expr.pre.incr]

The operand of prefix ++ or -- shall not be of type cv bool.
An operand with volatile-qualified type is deprecated; see [depr.volatile.type].
The expression ++x is otherwise equivalent to x+=1 and the expression --x is otherwise equivalent to x-=1 ([expr.ass]).
[Note 1: 
For postfix increment and decrement, see [expr.post.incr].
— end note]

7.6.2.4 Await [expr.await]

The co_await expression is used to suspend evaluation of a coroutine ([dcl.fct.def.coroutine]) while awaiting completion of the computation represented by the operand expression.
Suspending the evaluation of a coroutine transfers control to its caller or resumer.
An await-expression shall appear only as a potentially-evaluated expression within the compound-statement of a function-body or lambda-expression, in either case outside of a handler ([except.pre]).
An await-expression shall not appear in a default argument ([dcl.fct.default]).
An await-expression shall not appear in the initializer of a block variable with static or thread storage duration.
A context within a function where an await-expression can appear is called a suspension context of the function.
Evaluation of an await-expression involves the following auxiliary types, expressions, and objects:
  • p is an lvalue naming the promise object ([dcl.fct.def.coroutine]) of the enclosing coroutine and P is the type of that object.
  • Unless the await-expression was implicitly produced by a yield-expression ([expr.yield]), an initial await expression, or a final await expression ([dcl.fct.def.coroutine]), a search is performed for the name await_transform in the scope of P ([class.member.lookup]).
    If this search is performed and finds at least one declaration, then a is p.await_transform(cast-expression); otherwise, a is the cast-expression.
  • o is determined by enumerating the applicable operator co_await functions for an argument a ([over.match.oper]), and choosing the best one through overload resolution ([over.match]).
    If overload resolution is ambiguous, the program is ill-formed.
    If no viable functions are found, o is a.
    Otherwise, o is a call to the selected function with the argument a.
    If o would be a prvalue, the temporary materialization conversion ([conv.rval]) is applied.
  • e is an lvalue referring to the result of evaluating the (possibly-converted) o.
  • h is an object of type std​::​coroutine_handle<P> referring to the enclosing coroutine.
  • await-ready is the expression e.await_ready(), contextually converted to bool.
  • await-suspend is the expression e.await_suspend(h), which shall be a prvalue of type void, bool, or std​::​coroutine_handle<Z> for some type Z.
  • await-resume is the expression e.await_resume().
The await-expression has the same type and value category as the await-resume expression.
The await-expression evaluates the (possibly-converted) o expression and the await-ready expression, then:
  • If the result of await-ready is false, the coroutine is considered suspended.
    Then:
    • If the type of await-suspend is std​::​coroutine_handle<Z>, await-suspend.resume() is evaluated.
      [Note 1: 
      This resumes the coroutine referred to by the result of await-suspend.
      Any number of coroutines can be successively resumed in this fashion, eventually returning control flow to the current coroutine caller or resumer ([dcl.fct.def.coroutine]).
      — end note]
    • Otherwise, if the type of await-suspend is bool, await-suspend is evaluated, and the coroutine is resumed if the result is false.
    • Otherwise, await-suspend is evaluated.
    If the evaluation of await-suspend exits via an exception, the exception is caught, the coroutine is resumed, and the exception is immediately rethrown ([except.throw]).
    Otherwise, control flow returns to the current coroutine caller or resumer ([dcl.fct.def.coroutine]) without exiting any scopes ([stmt.jump]).
    The point in the coroutine immediately prior to control returning to its caller or resumer is a coroutine suspend point.
  • If the result of await-ready is true, or when the coroutine is resumed other than by rethrowing an exception from await-suspend, the await-resume expression is evaluated, and its result is the result of the await-expression.
[Note 2: 
With respect to sequencing, an await-expression is indivisible ([intro.execution]).
— end note]
[Example 1: template <typename T> struct my_future { /* ... */ bool await_ready(); void await_suspend(std::coroutine_handle<>); T await_resume(); }; template <class Rep, class Period> auto operator co_await(std::chrono::duration<Rep, Period> d) { struct awaiter { std::chrono::system_clock::duration duration; /* ... */ awaiter(std::chrono::system_clock::duration d) : duration(d) {} bool await_ready() const { return duration.count() <= 0; } void await_resume() {} void await_suspend(std::coroutine_handle<> h) { /* ... */ } }; return awaiter{d}; } using namespace std::chrono; my_future<int> h(); my_future<void> g() { std::cout << "just about to go to sleep...\n"; co_await 10ms; std::cout << "resumed\n"; co_await h(); } auto f(int x = co_await h()); // error: await-expression outside of function suspension context int a[] = { co_await h() }; // error: await-expression outside of function suspension context — end example]

7.6.2.5 Sizeof [expr.sizeof]

The sizeof operator yields the number of bytes occupied by a non-potentially-overlapping object of the type of its operand.
The operand is either an expression, which is an unevaluated operand, or a parenthesized type-id.
The sizeof operator shall not be applied to an expression that has function or incomplete type, to the parenthesized name of such types, or to a glvalue that designates a bit-field.
The result of sizeof applied to any of the narrow character types is 1.
The result of sizeof applied to any other fundamental type ([basic.fundamental]) is implementation-defined.
[Note 1: 
In particular, the values of sizeof(bool), sizeof(char16_t), sizeof(char32_t), and sizeof(wchar_t) are implementation-defined.57
— end note]
[Note 2: 
See [intro.memory] for the definition of byte and [basic.types.general] for the definition of object representation.
— end note]
When applied to a reference type, the result is the size of the referenced type.
When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array.
The result of applying sizeof to a potentially-overlapping subobject is the size of the type, not the size of the subobject.58
When applied to an array, the result is the total number of bytes in the array.
This implies that the size of an array of n elements is n times the size of an element.
The lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) standard conversions are not applied to the operand of sizeof.
If the operand is a prvalue, the temporary materialization conversion is applied.
The identifier in a sizeof... expression shall name a pack.
The sizeof... operator yields the number of elements in the pack ([temp.variadic]).
A sizeof... expression is a pack expansion ([temp.variadic]).
[Example 1: template<class... Types> struct count { static constexpr std::size_t value = sizeof...(Types); }; — end example]
The result of sizeof and sizeof... is a prvalue of type std​::​size_t.
[Note 3: 
A sizeof expression is an integral constant expression ([expr.const]).
The type std​::​size_t is defined in the standard header <cstddef> ([cstddef.syn], [support.types.layout]).
— end note]
57)57)
sizeof(bool) is not required to be 1.
58)58)
The actual size of a potentially-overlapping subobject can be less than the result of applying sizeof to the subobject, due to virtual base classes and less strict padding requirements on potentially-overlapping subobjects.

7.6.2.6 Alignof [expr.alignof]

An alignof expression yields the alignment requirement of its operand type.
The operand shall be a type-id representing a complete object type, or an array thereof, or a reference to one of those types.
The result is a prvalue of type std​::​size_t.
[Note 1: 
An alignof expression is an integral constant expression ([expr.const]).
The type std​::​size_t is defined in the standard header <cstddef> ([cstddef.syn], [support.types.layout]).
— end note]
When alignof is applied to a reference type, the result is the alignment of the referenced type.
When alignof is applied to an array type, the result is the alignment of the element type.

7.6.2.7 noexcept operator [expr.unary.noexcept]

The operand of the noexcept operator is an unevaluated operand ([expr.context]).
If the operand is a prvalue, the temporary materialization conversion ([conv.rval]) is applied.
The result of the noexcept operator is a prvalue of type bool.
The result is false if the full-expression of the operand is potentially-throwing ([except.spec]), and true otherwise.
[Note 1: 
A noexcept-expression is an integral constant expression ([expr.const]).
— end note]

7.6.2.8 New [expr.new]

The new-expression attempts to create an object of the type-id or new-type-id ([dcl.name]) to which it is applied.
The type of that object is the allocated type.
This type shall be a complete object type ([basic.types.general]), but not an abstract class type ([class.abstract]) or array thereof ([intro.object]).
[Note 1: 
Because references are not objects, references cannot be created by new-expressions.
— end note]
[Note 2: 
The type-id can be a cv-qualified type, in which case the object created by the new-expression has a cv-qualified type.
— end note]
If a placeholder type or a placeholder for a deduced class type ([dcl.type.class.deduct]) appears in the type-specifier-seq of a new-type-id or type-id of a new-expression, the allocated type is deduced as follows: Let init be the new-initializer, if any, and T be the new-type-id or type-id of the new-expression, then the allocated type is the type deduced for the variable x in the invented declaration ([dcl.spec.auto]): T x init ;
[Example 1: new auto(1); // allocated type is int auto x = new auto('a'); // allocated type is char, x is of type char* template<class T> struct A { A(T, T); }; auto y = new A{1, 2}; // allocated type is A<int> — end example]
The new-type-id in a new-expression is the longest possible sequence of new-declarators.
[Note 3: 
This prevents ambiguities between the declarator operators &, &&, *, and [] and their expression counterparts.
— end note]
[Example 2: new int * i; // syntax error: parsed as (new int*) i, not as (new int)*i
The * is the pointer declarator and not the multiplication operator.
— end example]
[Note 4: 
Parentheses in a new-type-id of a new-expression can have surprising effects.
[Example 3: 
new int(*[10])(); // error is ill-formed because the binding is (new int) (*[10])(); // error
Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound types ([basic.compound]):
new (int (*[10])()); allocates an array of 10 pointers to functions (taking no argument and returning int).
— end example]
— end note]
The attribute-specifier-seq in a noptr-new-declarator appertains to the associated array type.
Every constant-expression in a noptr-new-declarator shall be a converted constant expression ([expr.const]) of type std​::​size_t and its value shall be greater than zero.
[Example 4: 
Given the definition int n = 42, new float[n][5] is well-formed (because n is the expression of a noptr-new-declarator), but new float[5][n] is ill-formed (because n is not a constant expression).
Furthermore, new float[0] is well-formed (because 0 is the expression of a noptr-new-declarator, where a value of zero results in the allocation of an array with no elements), but new float[n][0] is ill-formed (because 0 is the constant-expression of a noptr-new-declarator, where only values greater than zero are allowed).
— end example]
If the type-id or new-type-id denotes an array type of unknown bound ([dcl.array]), the new-initializer shall not be omitted; the allocated object is an array with n elements, where n is determined from the number of initial elements supplied in the new-initializer ([dcl.init.aggr], [dcl.init.string]).
If the expression in a noptr-new-declarator is present, it is implicitly converted to std​::​size_t.
The value of the expression is invalid if
  • the expression is of non-class type and its value before converting to std​::​size_t is less than zero;
  • the expression is of class type and its value before application of the second standard conversion ([over.ics.user])59 is less than zero;
  • its value is such that the size of the allocated object would exceed the implementation-defined limit; or
  • the new-initializer is a braced-init-list and the number of array elements for which initializers are provided (including the terminating '\0' in a string-literal ([lex.string])) exceeds the number of elements to initialize.
If the value of the expression is invalid after converting to std​::​size_t:
When the value of the expression is zero, the allocation function is called to allocate an array with no elements.
If the allocated type is an array, the new-initializer is a braced-init-list, and the expression is potentially-evaluated and not a core constant expression, the semantic constraints of copy-initializing a hypothetical element of the array from an empty initializer list are checked ([dcl.init.list]).
[Note 5: 
The array can contain more elements than there are elements in the braced-init-list, requiring initialization of the remainder of the array elements from an empty initializer list.
— end note]
Objects created by a new-expression have dynamic storage duration ([basic.stc.dynamic]).
[Note 6: 
The lifetime of such an object is not necessarily restricted to the scope in which it is created.
— end note]
When the allocated type is “array of N T” (that is, the noptr-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a prvalue of type “pointer to T” that points to the initial element (if any) of the array.
Otherwise, let T be the allocated type; the new-expression is a prvalue of type “pointer to T” that points to the object created.
[Note 7: 
Both new int and new int[10] have type int* and the type of new int[i][10] is int (*)[10].
— end note]
A new-expression may obtain storage for the object by calling an allocation function ([basic.stc.dynamic.allocation]).
If the new-expression terminates by throwing an exception, it may release storage by calling a deallocation function.
If the allocated type is a non-array type, the allocation function's name is operator new and the deallocation function's name is operator delete.
If the allocated type is an array type, the allocation function's name is operator new[] and the deallocation function's name is operator delete[].
[Note 8: 
An implementation is expected to provide default definitions for the global allocation functions ([basic.stc.dynamic], [new.delete.single], [new.delete.array]).
A C++ program can provide alternative definitions of these functions ([replacement.functions]) and/or class-specific versions ([class.free]).
The set of allocation and deallocation functions that can be called by a new-expression can include functions that do not perform allocation or deallocation; for example, see [new.delete.placement].
— end note]
If the new-expression does not begin with a unary ​::​ operator and the allocated type is a class type T or array thereof, a search is performed for the allocation function's name in the scope of T ([class.member.lookup]).
Otherwise, or if nothing is found, the allocation function's name is looked up by searching for it in the global scope.
An implementation is allowed to omit a call to a replaceable global allocation function ([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 new-expression.
During an evaluation of a constant expression, a call to a replaceable allocation function is always omitted ([expr.const]).
The implementation may extend the allocation of a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended:
  • the evaluation of e1 is sequenced before the evaluation of e2, and
  • e2 is evaluated whenever e1 obtains storage, and
  • both e1 and e2 invoke the same replaceable global allocation function, and
  • if the allocation function invoked by e1 and e2 is throwing, any exceptions thrown in the evaluation of either e1 or e2 would be first caught in the same handler, and
  • the pointer values produced by e1 and e2 are operands to evaluated delete-expressions, and
  • the evaluation of e2 is sequenced before the evaluation of the delete-expression whose operand is the pointer value produced by e1.
[Example 5: void can_merge(int x) { // These allocations are safe for merging: std::unique_ptr<char[]> a{new (std::nothrow) char[8]}; std::unique_ptr<char[]> b{new (std::nothrow) char[8]}; std::unique_ptr<char[]> c{new (std::nothrow) char[x]}; g(a.get(), b.get(), c.get()); } void cannot_merge(int x) { std::unique_ptr<char[]> a{new char[8]}; try { // Merging this allocation would change its catch handler. std::unique_ptr<char[]> b{new char[x]}; } catch (const std::bad_alloc& e) { std::cerr << "Allocation failed: " << e.what() << std::endl; throw; } } — end example]
When a new-expression calls an allocation function and that allocation has not been extended, the new-expression passes the amount of space requested to the allocation function as the first argument of type std​::​size_t.
That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array and the allocation function is not a non-allocating form ([new.delete.placement]).
For arrays of char, unsigned char, and std​::​byte, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement of any object type whose size is no greater than the size of the array being created.
[Note 9: 
Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type with fundamental alignment, this constraint on array allocation overhead permits the common idiom of allocating character arrays into which objects of other types will later be placed.
— end note]
When a new-expression calls an allocation function and that allocation has been extended, the size argument to the allocation call shall be no greater than the sum of the sizes for the omitted calls as specified above, plus the size for the extended call had it not been extended, plus any padding necessary to align the allocated objects within the allocated memory.
The new-placement syntax is used to supply additional arguments to an allocation function; such an expression is called a placement new-expression.
Overload resolution is performed on a function call created by assembling an argument list.
The first argument is the amount of space requested, and has type std​::​size_t.
If the type of the allocated object has new-extended alignment, the next argument is the type's alignment, and has type std​::​align_val_t.
If the new-placement syntax is used, the initializer-clauses in its expression-list are the succeeding arguments.
If no matching function is found then
  • if the allocated object type has new-extended alignment, the alignment argument is removed from the argument list;
  • otherwise, an argument that is the type's alignment and has type std​::​align_val_t is added into the argument list immediately after the first argument;
and then overload resolution is performed again.
[Example 6: 
  • new T results in one of the following calls: operator new(sizeof(T)) operator new(sizeof(T), std::align_val_t(alignof(T)))
  • new(2,f) T results in one of the following calls: operator new(sizeof(T), 2, f) operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)
  • new T[5] results in one of the following calls: operator new[](sizeof(T) * 5 + x) operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)))
  • new(2,f) T[5] results in one of the following calls: operator new[](sizeof(T) * 5 + x, 2, f) operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)), 2, f)
Here, each instance of x is a non-negative unspecified value representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[].
This overhead may be applied in all array new-expressions, including those referencing a placement allocation function, except when referencing the library function operator new[](std​::​size_t, void*).
The amount of overhead may vary from one invocation of new to another.
— end example]
[Note 10: 
Unless an allocation function has a non-throwing exception specification, it indicates failure to allocate storage by throwing a std​::​bad_alloc exception ([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 and a non-null pointer otherwise.
— end note]
If the allocation function is a non-allocating form ([new.delete.placement]) that returns null, the behavior is undefined.
Otherwise, if the allocation function returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.
[Note 11: 
When the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved.
The block of storage is assumed to be appropriately aligned ([basic.align]) and of the requested size.
The address of the created object will not necessarily be the same as that of the block if the object is an array.
— end note]
A new-expression that creates an object of type T initializes that object as follows:
The invocation of the allocation function is sequenced before the evaluations of expressions in the new-initializer.
Initialization of the allocated object is sequenced before the value computation of the new-expression.
If the new-expression creates an array of objects of class type, the destructor is potentially invoked ([class.dtor]).
If any part of the object initialization described above60 terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression.
If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object's memory to be freed.
[Note 13: 
This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak.
— end note]
If the new-expression does not begin with a unary ​::​ operator and the allocated type is a class type T or an array thereof, a search is performed for the deallocation function's name in the scope of T.
Otherwise, or if nothing is found, the deallocation function's name is looked up by searching for it in the global scope.
A declaration of a placement deallocation function matches the declaration of a placement allocation function if it has the same number of parameters and, after parameter transformations ([dcl.fct]), all parameter types except the first are identical.
If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called.
If the lookup finds a usual deallocation function and that function, considered as a placement deallocation function, would have been selected as a match for the allocation function, the program is ill-formed.
For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function ([expr.delete]).
In any case, the matching deallocation function (if any) shall be non-deleted and accessible from the point where the new-expression appears.
[Example 7: struct S { // Placement allocation function: static void* operator new(std::size_t, std::size_t); // Usual (non-placement) deallocation function: static void operator delete(void*, std::size_t); }; S* p = new (0) S; // error: non-placement deallocation function matches // placement allocation function — end example]
If a new-expression calls a deallocation function, it passes the value returned from the allocation function call as the first argument of type void*.
If a placement deallocation function is called, it is passed the same additional arguments as were passed to the placement allocation function, that is, the same arguments as those specified with the new-placement syntax.
If the implementation is allowed to introduce a temporary object or make a copy of any argument as part of the call to the allocation function, it is unspecified whether the same object is used in the call to both the allocation and deallocation functions.
59)59)
If the conversion function returns a signed integer type, the second standard conversion converts to the unsigned type std​::​size_t and thus thwarts any attempt to detect a negative value afterwards.
60)60)
This can include evaluating a new-initializer and/or calling a constructor.

7.6.2.9 Delete [expr.delete]

The delete-expression operator destroys a most derived object or array created by a new-expression.
delete-expression:
:: delete cast-expression
:: delete [ ] cast-expression
The first alternative is a single-object delete expression, and the second is an array delete expression.
Whenever the delete keyword is immediately followed by empty square brackets, it shall be interpreted as the second alternative.61
If the operand is of class type, it is contextually implicitly converted ([conv]) to a pointer to object type and the converted operand is used in place of the original operand for the remainder of this subclause.
Otherwise, it shall be a prvalue of pointer to object type.
The delete-expression has type void.
In a single-object delete expression, the value of the operand of delete may be a null pointer value, a pointer value that resulted from a previous non-array new-expression, or a pointer to a base class subobject of an object created by such a new-expression.
If not, the behavior is undefined.
In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression whose allocation function was not a non-allocating form ([new.delete.placement]).62
If not, the behavior is undefined.
[Note 1: 
This means that the syntax of the delete-expression must match the type of the object allocated by new, not the syntax of the new-expression.
— end note]
[Note 2: 
A pointer to a const type can be the operand of a delete-expression; it is not necessary to cast away the constness ([expr.const.cast]) of the pointer expression before it is used as the operand of the delete-expression.
— end note]
In a single-object delete expression, if the static type of the object to be deleted is not similar ([conv.qual]) to its dynamic type and the selected deallocation function (see below) is not a destroying operator delete, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.
In an array delete expression, if the dynamic type of the object to be deleted is not similar to its static type, the behavior is undefined.
If the object being deleted has incomplete class type at the point of deletion, the program is ill-formed.
If the value of the operand of the delete-expression is not a null pointer value and the selected deallocation function (see below) is not a destroying operator delete, evaluating the delete-expression invokes the destructor (if any) for the object or the elements of the array being deleted.
The destructor shall be accessible from the point where the delete-expression appears.
In the case of an array, the elements are destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see [class.base.init]).
If the value of the operand of the delete-expression is not a null pointer value, then:
[Note 3: 
The deallocation function is called regardless of whether the destructor for the object or some element of the array throws an exception.
— end note]
If the value of the operand of the delete-expression is a null pointer value, it is unspecified whether a deallocation function will be called as described above.
If a deallocation function is called, it is operator delete for a single-object delete expression or operator delete[] for an array delete expression.
[Note 4: 
An implementation provides default definitions of the global deallocation functions ([new.delete.single], [new.delete.array]).
A C++ program can provide alternative definitions of these functions ([replacement.functions]), and/or class-specific versions ([class.free]).
— end note]
If the keyword delete in a delete-expression is not preceded by the unary ​::​ operator and the type of the operand is a pointer to a (possibly cv-qualified) class type T or (possibly multidimensional) array thereof:
  • For a single-object delete expression, if the operand is a pointer to cv T and T has a virtual destructor, the deallocation function is the one selected at the point of definition of the dynamic type's virtual destructor ([class.dtor]).
  • Otherwise, a search is performed for the deallocation function's name in the scope of T.
Otherwise, or if nothing is found, the deallocation function's name is looked up by searching for it in the global scope.
In any case, any declarations other than of usual deallocation functions ([basic.stc.dynamic.deallocation]) are discarded.
[Note 5: 
If only a placement deallocation function is found in a class, the program is ill-formed because the lookup set is empty ([basic.lookup]).
— end note]
The deallocation function to be called is selected as follows:
  • If any of the deallocation functions is a destroying operator delete, all deallocation functions that are not destroying operator deletes are eliminated from further consideration.
  • If the type has new-extended alignment, a function with a parameter of type std​::​align_val_t is preferred; otherwise a function without such a parameter is preferred.
    If any preferred functions are found, all non-preferred functions are eliminated from further consideration.
  • If exactly one function remains, that function is selected and the selection process terminates.
  • If the deallocation functions belong to a class scope, the one without a parameter of type std​::​size_t is selected.
  • If the type is complete and if, for an array delete expression only, the operand is a pointer to a class type with a non-trivial destructor or a (possibly multidimensional) array thereof, the function with a parameter of type std​::​size_t is selected.
  • Otherwise, it is unspecified whether a deallocation function with a parameter of type std​::​size_t is selected.
Unless the deallocation function is selected at the point of definition of the dynamic type's virtual destructor, the selected deallocation function shall be accessible from the point where the delete-expression appears.
For a single-object delete expression, the deleted object is the object A pointed to by the operand if the static type of A does not have a virtual destructor, and the most-derived object of A otherwise.
[Note 6: 
If the deallocation function is not a destroying operator delete and the deleted object is not the most derived object in the former case, the behavior is undefined, as stated above.
— end note]
For an array delete expression, the deleted object is the array object.
When a delete-expression is executed, the selected deallocation function shall be called with the address of the deleted object in a single-object delete expression, or the address of the deleted object suitably adjusted for the array allocation overhead ([expr.new]) in an array delete expression, as its first argument.
[Note 7: 
Any cv-qualifiers in the type of the deleted object are ignored when forming this argument.
— end note]
If a destroying operator delete is used, an unspecified value is passed as the argument corresponding to the parameter of type std​::​destroying_delete_t.
If a deallocation function with a parameter of type std​::​align_val_t is used, the alignment of the type of the deleted object is passed as the corresponding argument.
If a deallocation function with a parameter of type std​::​size_t is used, the size of the deleted object in a single-object delete expression, or of the array plus allocation overhead in an array delete expression, is passed as the corresponding argument.
[Note 8: 
If this results in a call to a replaceable deallocation function, and either 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 ([new.delete.single], [new.delete.array]).
— end note]
61)61)
A lambda-expression with a lambda-introducer that consists of empty square brackets can follow the delete keyword if the lambda-expression is enclosed in parentheses.
62)62)
For nonzero-length arrays, this is the same as a pointer to the first element of the array created by that new-expression.
Zero-length arrays do not have a first element.

7.6.3 Explicit type conversion (cast notation) [expr.cast]

The result of the expression (T) cast-expression is of type T.
The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue.
[Note 1: 
If T is a non-class type that is cv-qualified, the cv-qualifiers are discarded when determining the type of the resulting prvalue; see [expr.prop].
— end note]
An explicit type conversion can be expressed using functional notation ([expr.type.conv]), a type conversion operator (dynamic_cast, static_cast, reinterpret_cast, const_cast), or the cast notation.
Any type conversion not mentioned below and not explicitly defined by the user ([class.conv]) is ill-formed.
The conversions performed by can be performed using the cast notation of explicit type conversion.
The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:
  • a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;
  • a pointer to member of derived class type may be explicitly converted to a pointer to member of an unambiguous non-virtual base class type;
  • a pointer to an object of an unambiguous non-virtual base class type, a glvalue of an unambiguous non-virtual base class type, or a pointer to member of an unambiguous non-virtual base class type may be explicitly converted to a pointer, a reference, or a pointer to member of a derived class type, respectively.
If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is ill-formed.
If a static_cast followed by a const_cast is used and the conversion can be interpreted in more than one way as such, the conversion is ill-formed.
[Example 1: struct A { }; struct I1 : A { }; struct I2 : A { }; struct D : I1, I2 { }; A* foo( D* p ) { return (A*)( p ); // ill-formed static_cast interpretation } int*** ptr = 0; auto t = (int const*const*const*)ptr; // OK, const_cast interpretation struct S { operator const int*(); operator volatile int*(); }; int *p = (int*)S(); // error: two possible interpretations using static_cast followed by const_cast — end example]
The operand of a cast using the cast notation can be a prvalue of type “pointer to incomplete class type”.
The destination type of a cast using the cast notation can be “pointer to incomplete class type”.
If both the operand and destination types are class types and one or both are incomplete, it is unspecified whether the static_cast or the reinterpret_cast interpretation is used, even if there is an inheritance relationship between the two classes.
[Note 2: 
For example, if the classes were defined later in the translation unit, a multi-pass compiler could validly interpret a cast between pointers to the classes as if the class types were complete at the point of the cast.
— end note]

7.6.4 Pointer-to-member operators [expr.mptr.oper]

The pointer-to-member operators ->* and .* group left-to-right.
The binary operator .* binds its second operand, which shall be a prvalue of type “pointer to member of T” to its first operand, which shall be a glvalue of class T or of a class of which T is an unambiguous and accessible base class.
The result is an object or a function of the type specified by the second operand.
The binary operator ->* binds its second operand, which shall be a prvalue of type “pointer to member of T” to its first operand, which shall be of type “pointer to U” where U is either T or a class of which T is an unambiguous and accessible base class.
The expression E1->*E2 is converted into the equivalent form (*(E1)).*E2.
Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression.
If the result of E1 is an object whose type is not similar to the type of E1, or whose most derived object does not contain the member to which E2 refers, the behavior is undefined.
The expression E1 is sequenced before the expression E2.
The restrictions on cv-qualification, and the manner in which the cv-qualifiers of the operands are combined to produce the cv-qualifiers of the result, are the same as the rules for E1.E2 given in [expr.ref].
[Note 1: 
It is not possible to use a pointer to member that refers to a mutable member to modify a const class object.
For example, struct S { S() : i(0) { } mutable int i; }; void f() { const S cs; int S::* pm = &S::i; // pm refers to mutable member S​::​i cs.*pm = 88; // error: cs is a const object }
— end note]
If the result of .* or ->* is a function, then that result can be used only as the operand for the function call operator ().
[Example 1: 
(ptr_to_obj->*ptr_to_mfct)(10); calls the member function denoted by ptr_to_mfct for the object pointed to by ptr_to_obj.
— end example]
In a .* expression whose object expression is an rvalue, the program is ill-formed if the second operand is a pointer to member function whose ref-qualifier is &, unless its cv-qualifier-seq is const.
In a .* expression whose object expression is an lvalue, the program is ill-formed if the second operand is a pointer to member function whose ref-qualifier is &&.
The result of a .* expression whose second operand is a pointer to a data member is an lvalue if the first operand is an lvalue and an xvalue otherwise.
The result of a .* expression whose second operand is a pointer to a member function is a prvalue.
If the second operand is the null member pointer value, the behavior is undefined.

7.6.5 Multiplicative operators [expr.mul]

The operands of * and / shall have arithmetic or unscoped enumeration type; the operands of % shall have integral or unscoped enumeration type.
The usual arithmetic conversions are performed on the operands and determine the type of the result.
The binary * operator indicates multiplication.
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second.
If the second operand of / or % is zero, the behavior is undefined.
For integral operands, the / operator yields the algebraic quotient with any fractional part discarded;63 if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a; otherwise, the behavior of both a/b and a%b is undefined.
63)63)
This is often called truncation towards zero.

7.6.6 Additive operators [expr.add]

The additive operators + and - group left-to-right.
Each operand shall be a prvalue.
If both operands have arithmetic or unscoped enumeration type, the usual arithmetic conversions ([expr.arith.conv]) are performed.
Otherwise, if one operand has arithmetic or unscoped enumeration type, integral promotion is applied ([conv.prom]) to that operand.
A converted or promoted operand is used in place of the corresponding original operand for the remainder of this section.
For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a completely-defined object type and the other shall have integral type.
For subtraction, one of the following shall hold:
  • both operands have arithmetic type; or
  • both operands are pointers to cv-qualified or cv-unqualified versions of the same completely-defined object type; or
  • the left operand is a pointer to a completely-defined object type and the right operand has integral type.
The result of the binary + operator is the sum of the operands.
The result of the binary - operator is the difference resulting from the subtraction of the second operand from the first.
When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
  • If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
  • Otherwise, if P points to a (possibly-hypothetical) array element i of an array object x with n elements ([dcl.array]),64 the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element of x if and the expression P - J points to the (possibly-hypothetical) array element of x if .
  • Otherwise, the behavior is undefined.
[Note 1: 
Adding a value other than 0 or 1 to a pointer to a base class subobject, a member subobject, or a complete object results in undefined behavior.
— end note]
When two pointer expressions P and Q are subtracted, the type of the result is an implementation-defined signed integral type; this type shall be the same type that is defined as std​::​ptrdiff_t in the <cstddef> header ([support.types.layout]).
  • If P and Q both evaluate to null pointer values, the result is 0.
  • Otherwise, if P and Q point to, respectively, array elements i and j of the same array object x, the expression P - Q has the value .
    [Note 2: 
    If the value is not in the range of representable values of type std​::​ptrdiff_t, the behavior is undefined ([expr.pre]).
    — end note]
  • Otherwise, the behavior is undefined.
For addition or subtraction, if the expressions P or Q have type “pointer to cv T”, where T and the array element type are not similar, the behavior is undefined.
[Example 1: int arr[5] = {1, 2, 3, 4, 5}; unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1); unsigned int k = *p; // OK, value of k is 2 ([conv.lval]) unsigned int *q = p + 1; // undefined behavior: p points to an int, not an unsigned int object — end example]
64)64)
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose and a pointer past the last element of an array of n elements is considered to be equivalent to a pointer to a hypothetical array element n for this purpose.

7.6.7 Shift operators [expr.shift]

The shift operators << and >> group left-to-right.
The operands shall be prvalues of integral or unscoped enumeration type and integral promotions are performed.
The type of the result is that of the promoted left operand.
The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.
The value of E1 << E2 is the unique value congruent to modulo , where N is the width of the type of the result.
[Note 1: 
E1 is left-shifted E2 bit positions; vacated bits are zero-filled.
— end note]
The value of E1 >> E2 is , rounded towards negative infinity.
[Note 2: 
E1 is right-shifted E2 bit positions.
Right-shift on signed integral types is an arithmetic right shift, which performs sign-extension.
— end note]
The expression E1 is sequenced before the expression E2.

7.6.8 Three-way comparison operator [expr.spaceship]

The three-way comparison operator groups left-to-right.
The expression p <=> q is a prvalue indicating whether p is less than, equal to, greater than, or incomparable with q.
If one of the operands is of type bool and the other is not, the program is ill-formed.
If both operands have arithmetic types, or one operand has integral type and the other operand has unscoped enumeration type, the usual arithmetic conversions are applied to the operands.
Then:
  • If a narrowing conversion is required, other than from an integral type to a floating-point type, the program is ill-formed.
  • Otherwise, if the operands have integral type, the result is of type std​::​strong_ordering.
    The result is std​::​strong_ordering​::​equal if both operands are arithmetically equal, std​::​strong_ordering​::​less if the first operand is arithmetically less than the second operand, and std​::​strong_ordering​::​greater otherwise.
  • Otherwise, the operands have floating-point type, and the result is of type std​::​partial_ordering.
    The expression a <=> b yields std​::​partial_ordering​::​less if a is less than b, std​::​partial_ordering​::​greater if a is greater than b, std​::​partial_ordering​::​equivalent if a is equivalent to b, and std​::​partial_ordering​::​unordered otherwise.
If both operands have the same enumeration type E, the operator yields the result of converting the operands to the underlying type of E and applying <=> to the converted operands.
If at least one of the operands is of object pointer type and the other operand is of object pointer or array type, array-to-pointer conversions ([conv.array]), pointer conversions ([conv.ptr]), and qualification conversions are performed on both operands to bring them to their composite pointer type ([expr.type]).
After the conversions, the operands shall have the same type.
[Note 1: 
If both of the operands are arrays, array-to-pointer conversions are not applied.
— end note]
In this case, p <=> q is of type std​::​strong_ordering and the result is defined by the following rules:
  • If two pointer operands p and q compare equal ([expr.eq]), p <=> q yields std​::​strong_ordering​::​equal;
  • otherwise, if p and q compare unequal, p <=> q yields std​::​strong_ordering​::​less if q compares greater than p and std​::​strong_ordering​::​greater if p compares greater than q ([expr.rel]);
  • otherwise, the result is unspecified.
Otherwise, the program is ill-formed.
The three comparison category types ([cmp.categories]) (the types std​::​strong_ordering, std​::​weak_ordering, and std​::​partial_ordering) are not predefined; if a standard library declaration ([compare.syn], [std.modules]) of such a class type does not precede ([basic.lookup.general]) a use of that type — even an implicit use in which the type is not named (e.g., via the auto specifier ([dcl.spec.auto]) in a defaulted three-way comparison ([class.spaceship]) or use of the built-in operator) — the program is ill-formed.

7.6.9 Relational operators [expr.rel]

The relational operators group left-to-right.
[Example 1: 
a<b<c means (a<b)<c and not (a<b)&&(b<c).
— end example]
If one of the operands is a pointer, the array-to-pointer conversion ([conv.array]) is performed on the other operand.
The converted operands shall have arithmetic, enumeration, or pointer type.
The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true.
The type of the result is bool.
The usual arithmetic conversions ([expr.arith.conv]) are performed on operands of arithmetic or enumeration type.
If both converted operands are pointers, pointer conversions ([conv.ptr]), function pointer conversions ([conv.fctptr]), and qualification conversions ([conv.qual]) are performed to bring them to their composite pointer type.
After conversions, the operands shall have the same type.
The result of comparing unequal pointers to objects65 is defined in terms of a partial order consistent with the following rules:
  • If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater.
  • If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided neither member is a subobject of zero size and their class is not a union.
  • Otherwise, neither pointer is required to compare greater than the other.
If two operands p and q compare equal ([expr.eq]), p<=q and p>=q both yield true and p<q and p>q both yield false.
Otherwise, if a pointer to object p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false.
Otherwise, the result of each of the operators is unspecified.
[Note 1: 
A relational operator applied to unequal function pointers yields an unspecified result.
A pointer value of type “pointer to cv void” can point to an object ([basic.compound]).
— end note]
If both operands (after conversions) are of arithmetic or enumeration type, each of the operators shall yield true if the specified relationship is true and false if it is false.
65)65)
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose and a pointer past the last element of an array of n elements is considered to be equivalent to a pointer to a hypothetical array element n for this purpose.

7.6.10 Equality operators [expr.eq]

The == (equal to) and the != (not equal to) operators group left-to-right.
The lvalue-to-rvalue ([conv.lval]) and function-to-pointer ([conv.func]) standard conversions are performed on the operands.
If one of the operands is a pointer or a null pointer constant ([conv.ptr]), the array-to-pointer conversion ([conv.array]) is performed on the other operand.
The converted operands shall have scalar type.
The operators == and != both yield true or false, i.e., a result of type bool.
In each case below, the operands shall have the same type after the specified conversions have been applied.
If at least one of the converted operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type.
Comparing pointers is defined as follows:
  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,66 the result of the comparison is unspecified.
  • Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal.
  • Otherwise, the pointers compare unequal.
If at least one of the operands is a pointer to member, pointer-to-member conversions ([conv.mem]), function pointer conversions ([conv.fctptr]), and qualification conversions ([conv.qual]) are performed on both operands to bring them to their composite pointer type ([expr.type]).
Comparing pointers to members is defined as follows:
  • If two pointers to members are both the null member pointer value, they compare equal.
  • If only one of two pointers to members is the null member pointer value, they compare unequal.
  • If either is a pointer to a virtual member function, the result is unspecified.
  • If one refers to a member of class C1 and the other refers to a member of a different class C2, where neither is a base class of the other, the result is unspecified.
    [Example 1: struct A {}; struct B : A { int x; }; struct C : A { int x; }; int A::*bx = (int(A::*))&B::x; int A::*cx = (int(A::*))&C::x; bool b1 = (bx == cx); // unspecified — end example]
  • If both refer to (possibly different) members of the same union, they compare equal.
  • Otherwise, two pointers to members compare equal if they would refer to the same member of the same most derived object or the same subobject if indirection with a hypothetical object of the associated class type were performed, otherwise they compare unequal.
    [Example 2: struct B { int f(); }; struct L : B { }; struct R : B { }; struct D : L, R { }; int (B::*pb)() = &B::f; int (L::*pl)() = pb; int (R::*pr)() = pb; int (D::*pdl)() = pl; int (D::*pdr)() = pr; bool x = (pdl == pdr); // false bool y = (pb == pl); // true — end example]
Two operands of type std​::​nullptr_t or one operand of type std​::​nullptr_t and the other a null pointer constant compare equal.
If two operands compare equal, the result is true for the == operator and false for the != operator.
If two operands compare unequal, the result is false for the == operator and true for the != operator.
Otherwise, the result of each of the operators is unspecified.
If both operands are of arithmetic or enumeration type, the usual arithmetic conversions ([expr.arith.conv]) are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.
66)66)
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose.

7.6.11 Bitwise AND operator [expr.bit.and]

The & operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions ([expr.arith.conv]) are performed.
Given the coefficients and of the base-2 representation ([basic.fundamental]) of the converted operands x and y, the coefficient of the base-2 representation of the result r is 1 if both and are 1, and 0 otherwise.
[Note 1: 
The result is the bitwise and function of the operands.
— end note]

7.6.12 Bitwise exclusive OR operator [expr.xor]

The ^ operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions ([expr.arith.conv]) are performed.
Given the coefficients and of the base-2 representation ([basic.fundamental]) of the converted operands x and y, the coefficient of the base-2 representation of the result r is 1 if either (but not both) of and is 1, and 0 otherwise.
[Note 1: 
The result is the bitwise exclusive or function of the operands.
— end note]

7.6.13 Bitwise inclusive OR operator [expr.or]

The | operator groups left-to-right.
The operands shall be of integral or unscoped enumeration type.
The usual arithmetic conversions ([expr.arith.conv]) are performed.
Given the coefficients and of the base-2 representation ([basic.fundamental]) of the converted operands x and y, the coefficient of the base-2 representation of the result r is 1 if at least one of and is 1, and 0 otherwise.
[Note 1: 
The result is the bitwise inclusive or function of the operands.
— end note]

7.6.14 Logical AND operator [expr.log.and]

The && operator groups left-to-right.
The operands are both contextually converted to bool ([conv]).
The result is true if both operands are true and false otherwise.
Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.
The result is a bool.
If the second expression is evaluated, the first expression is sequenced before the second expression ([intro.execution]).

7.6.15 Logical OR operator [expr.log.or]

The || operator groups left-to-right.
The operands are both contextually converted to bool ([conv]).
The result is true if either of its operands is true, and false otherwise.
Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.
The result is a bool.
If the second expression is evaluated, the first expression is sequenced before the second expression ([intro.execution]).

7.6.16 Conditional operator [expr.cond]

Conditional expressions group right-to-left.
The first expression is contextually converted to bool ([conv]).
It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression.
Only one of the second and third expressions is evaluated.
The first expression is sequenced before the second or third expression ([intro.execution]).
If either the second or the third operand has type void, one of the following shall hold:
  • The second or the third operand (but not both) is a (possibly parenthesized) throw-expression ([expr.throw]); the result is of the type and value category of the other.
    The conditional-expression is a bit-field if that operand is a bit-field.
  • Both the second and the third operands have type void; the result is of type void and is a prvalue.
    [Note 1: 
    This includes the case where both operands are throw-expressions.
    — end note]
Otherwise, if the second and third operand are glvalue bit-fields of the same value category and of types cv1 T and cv2 T, respectively, the operands are considered to be of type cv T for the remainder of this subclause, where cv is the union of cv1 and cv2.
Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to form an implicit conversion sequence from each of those operands to the type of the other.
[Note 2: 
Properties such as access, whether an operand is a bit-field, or whether a conversion function is deleted are ignored for that determination.
— end note]
Attempts are made to form an implicit conversion sequence from an operand expression E1 of type T1 to a target type related to the type T2 of the operand expression E2 as follows:
  • If E2 is an lvalue, the target type is “lvalue reference to T2”, but an implicit conversion sequence can only be formed if the reference would bind directly ([dcl.init.ref]) to a glvalue.
  • If E2 is an xvalue, the target type is “rvalue reference to T2”, but an implicit conversion sequence can only be formed if the reference would bind directly.
  • If E2 is a prvalue or if neither of the conversion sequences above can be formed and at least one of the operands has (possibly cv-qualified) class type:
    • if T1 and T2 are the same class type (ignoring cv-qualification):
      • if T2 is at least as cv-qualified as T1, the target type is T2,
      • otherwise, no conversion sequence is formed for this operand;
    • otherwise, if T2 is a base class of T1, the target type is cv1 T2, where cv1 denotes the cv-qualifiers of T1;
    • otherwise, the target type is the type that E2 would have after applying the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions.
Using this process, it is determined whether an implicit conversion sequence can be formed from the second operand to the target type determined for the third operand, and vice versa, with the following outcome:
  • If both sequences can be formed, or one can be formed but it is the ambiguous conversion sequence, the program is ill-formed.
  • If no conversion sequence can be formed, the operands are left unchanged and further checking is performed as described below.
  • Otherwise, if exactly one conversion sequence can be formed, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this subclause.
    [Note 3: 
    The conversion might be ill-formed even if an implicit conversion sequence could be formed.
    — end note]
If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.
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 ([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 subclause.
Array-to-pointer and function-to-pointer standard conversions are performed on the second and third operands.
After those conversions, one of the following shall hold:
  • The second and third operands have the same type; the result is of that type and the result is copy-initialized using the selected operand.
  • The second and third operands have arithmetic or enumeration type; the usual arithmetic conversions are performed to bring them to a common type, and the result is of that type.
  • One or both of the second and third operands have pointer type; lvalue-to-rvalue, pointer, function pointer, and qualification conversions are performed to bring them to their composite pointer type.
    The result is of the composite pointer type.
  • One or both of the second and third operands have pointer-to-member type; lvalue-to-rvalue ([conv.lval]), pointer to member ([conv.mem]), function pointer ([conv.fctptr]), and qualification conversions ([conv.qual]) are performed to bring them to their composite pointer type ([expr.type]).
    The result is of the composite pointer type.
  • Both the second and third operands have type std​::​nullptr_t or one has that type and the other is a null pointer constant.
    The result is of type std​::​nullptr_t.

7.6.17 Yielding a value [expr.yield]

A yield-expression shall appear only within a suspension context of a function ([expr.await]).
Let e be the operand of the yield-expression and p be an lvalue naming the promise object of the enclosing coroutine ([dcl.fct.def.coroutine]), then the yield-expression is equivalent to the expression co_await p.yield_value(e).
[Example 1: template <typename T> struct my_generator { struct promise_type { T current_value; /* ... */ auto yield_value(T v) { current_value = std::move(v); return std::suspend_always{}; } }; struct iterator { /* ... */ }; iterator begin(); iterator end(); }; my_generator<pair<int,int>> g1() { for (int i = 0; i < 10; ++i) co_yield {i,i}; } my_generator<pair<int,int>> g2() { for (int i = 0; i < 10; ++i) co_yield make_pair(i,i); } auto f(int x = co_yield 5); // error: yield-expression outside of function suspension context int a[] = { co_yield 1 }; // error: yield-expression outside of function suspension context int main() { auto r1 = g1(); auto r2 = g2(); assert(std::equal(r1.begin(), r1.end(), r2.begin(), r2.end())); } — end example]

7.6.18 Throwing an exception [expr.throw]

A throw-expression is of type void.
A throw-expression with an operand throws an exception ([except.throw]).
The array-to-pointer ([conv.array]) and function-to-pointer ([conv.func]) standard conversions are performed on the operand.
The type of the exception object is determined by removing any top-level cv-qualifiers from the type of the (possibly converted) operand.
The exception object is copy-initialized ([dcl.init.general]) from the (possibly converted) operand.
A throw-expression with no operand rethrows the currently handled exception ([except.handle]).
If no exception is presently being handled, the function std​::​terminate is invoked ([except.terminate]).
Otherwise, the exception is reactivated with the existing exception object; no new exception object is created.
The exception is no longer considered to be caught.
[Example 1: 
An exception handler that cannot completely handle the exception itself can be written like this: try { // ... } catch (...) { // catch all exceptions // respond (partially) to exception throw; // pass the exception to some other handler }
— end example]

7.6.19 Assignment and compound assignment operators [expr.ass]

The assignment operator (=) and the compound assignment operators all group right-to-left.
All require a modifiable lvalue as their left operand; their result is an lvalue of the type of the left operand, referring to the left operand.
The result in all cases is a bit-field if the left operand is a bit-field.
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
The right operand is sequenced before the left operand.
With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.
[Note 1: 
Therefore, a function call cannot intervene between the lvalue-to-rvalue conversion and the side effect associated with any single compound assignment operator.
— end note]
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=
In simple assignment (=), let V be the result of the right operand; the object referred to by the left operand is modified ([defns.access]) by replacing its value with V or, if the object is of integer type, with the value congruent ([basic.fundamental]) to V.
If the right operand is an expression, it is implicitly converted to the cv-unqualified type of the left operand.
When the left operand of an assignment operator is a bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.
An assignment whose left operand is of a volatile-qualified type is deprecated ([depr.volatile.type]) unless the (possibly parenthesized) assignment is a discarded-value expression or an unevaluated operand.
The behavior of an expression of the form E1 op= E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
[Note 2: 
The object designated by E1 is accessed twice.
— end note]
For += and -=, E1 shall either have arithmetic type or be a pointer to a possibly cv-qualified completely-defined object type.
In all other cases, E1 shall have arithmetic type.
If the value being stored in an object is read via another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have the same type, otherwise the behavior is undefined.
[Note 3: 
This restriction applies to the relationship between the left and right sides of the assignment operation; it is not a statement about how the target of the assignment can be aliased in general.
— end note]
A braced-init-list B may appear on the right-hand side of
  • an assignment to a scalar of type T, in which case B shall have at most a single element.
    The meaning of x = B is x = t, where t is an invented temporary variable declared and initialized as T t = B.
  • an assignment to an object of class type, in which case B is passed as the argument to the assignment operator function selected by overload resolution ([over.ass], [over.match]).
[Example 1: complex<double> z; z = { 1,2 }; // meaning z.operator=({1,2}) z += { 1, 2 }; // meaning z.operator+=({1,2}) int a, b; a = b = { 1 }; // meaning a=b=1; a = { 1 } = b; // syntax error — end example]

7.6.20 Comma operator [expr.comma]

The comma operator groups left-to-right.
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-value expression.
The left expression is sequenced before the right expression ([intro.execution]).
The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a bit-field.
[Note 1: 
In contexts where the comma token is given special meaning (e.g., function calls ([expr.call]), subscript expressions ([expr.sub]), lists of initializers ([dcl.init]), or template-argument-lists ([temp.names])), the comma operator as described in this subclause can appear only in parentheses.
[Example 1: 
f(a, (t=3, t+2), c); has three arguments, the second of which has the value 5.
— end example]
— end note]

7.7 Constant expressions [expr.const]

Certain contexts require expressions that satisfy additional requirements as detailed in this subclause; other contexts have different semantics depending on whether or not an expression satisfies these requirements.
Expressions that satisfy these requirements, assuming that copy elision is not performed, are called constant expressions.
[Note 1: 
Constant expressions can be evaluated during translation.
— end note]
The constituent values of an object o are
  • if o has scalar type, the value of o;
  • otherwise, the constituent values of any direct subobjects of o other than inactive union members.
The constituent references of an object o are
  • any direct members of o that have reference type, and
  • the constituent references of any direct subobjects of o other than inactive union members.
The constituent values and constituent references of a variable x are defined as follows:
  • If x declares an object, the constituent values and references of that object are constituent values and references of x.
  • If x declares a reference, that reference is a constituent reference of x.
For any constituent reference r of a variable x, if r is bound to a temporary object or subobject thereof whose lifetime is extended to that of r, the constituent values and references of that temporary object are also constituent values and references of x, recursively.
An object o is constexpr-referenceable from a point P if
  • o has static storage duration, or
  • o has automatic storage duration, and, letting v denote
    • the variable corresponding to o's complete object or
    • the variable to whose lifetime that of o is extended,
    the smallest scope enclosing v and the smallest scope enclosing P that are neither are the same function parameter scope.
[Example 1: struct A { int m; const int& r; }; void f() { static int sx; thread_local int tx; // tx is never constexpr-referenceable int ax; A aa = {1, 2}; static A sa = {3, 4}; // The objects sx, ax, and aa.m, sa.m, and the temporaries to which aa.r and sa.r are bound, are constexpr-referenceable. auto lambda = [] { int ay; // The objects sx, sa.m, and ay (but not ax or aa), and the // temporary to which sa.r is bound, are constexpr-referenceable. }; } — end example]
An object or reference x is constexpr-representable at a point P if, for each constituent value of x that points to or past an object o, and for each constituent reference of x that refers to an object o, o is constexpr-referenceable from P.
A variable v is constant-initializable if
  • the full-expression of its initialization is a constant expression when interpreted as a constant-expression,
    [Note 2: 
    Within this evaluation, std​::​is_constant_evaluated() ([meta.const.eval]) returns true.
    — end note]
    and
  • immediately after the initializing declaration of v, the object or reference x declared by v is constexpr-representable, and
  • if x has static or thread storage duration, x is constexpr-representable at the nearest point whose immediate scope is a namespace scope that follows the initializing declaration of v.
A constant-initializable variable is constant-initialized if either it has an initializer or its default-initialization results in some initialization being performed.
[Example 2: void f() { int ax = 0; // ax is constant-initialized thread_local int tx = 0; // tx is constant-initialized static int sx; // sx is not constant-initialized static int& rss = sx; // rss is constant-initialized static int& rst = tx; // rst is not constant-initialized static int& rsa = ax; // rsa is not constant-initialized thread_local int& rts = sx; // rts is constant-initialized thread_local int& rtt = tx; // rtt is not constant-initialized thread_local int& rta = ax; // rta is not constant-initialized int& ras = sx; // ras is constant-initialized int& rat = tx; // rat is not constant-initialized int& raa = ax; // raa is constant-initialized } — end example]
A variable is potentially-constant if it is constexpr or it has reference or non-volatile const-qualified integral or enumeration type.
A constant-initialized potentially-constant variable V is usable in constant expressions at a point P if V's initializing declaration D is reachable from P and
  • V is constexpr,
  • V is not initialized to a TU-local value, or
  • P is in the same translation unit as D.
An object or reference is potentially usable in constant expressions at point P if it is
  • the object or reference declared by a variable that is usable in constant expressions at P,
  • a temporary object of non-volatile const-qualified literal type whose lifetime is extended ([class.temporary]) to that of a variable that is usable in constant expressions at P,
  • a template parameter object,
  • a string literal object,
  • a non-mutable subobject of any of the above, or
  • a reference member of any of the above.
An object or reference is usable in constant expressions at point P if it is an object or reference that is potentially usable in constant expressions at P and is constexpr-representable at P.
[Example 3: struct A { int* const & r; }; void f(int x) { constexpr A a = {&x}; static_assert(a.r == &x); // OK [&] { static_assert(a.r != nullptr); // error: a.r is not usable in constant expressions at this point }(); } — end example]
An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
  • this ([expr.prim.this]), except
  • a control flow that passes through a declaration of a block variable ([basic.scope.block]) with static ([basic.stc.static]) or thread ([basic.stc.thread]) storage duration, unless that variable is usable in constant expressions;
    [Example 4: constexpr char test() { static const int x = 5; static constexpr char c[] = "Hello World"; return *(c + x); } static_assert(' ' == test()); — end example]
  • an invocation of a non-constexpr function;67
  • an invocation of an undefined constexpr function;
  • an invocation of an instantiated constexpr function that is not constexpr-suitable;
  • an invocation of a virtual function ([class.virtual]) for an object whose dynamic type is constexpr-unknown;
  • an expression that would exceed the implementation-defined limits (see [implimits]);
  • an operation that would have undefined or erroneous behavior as specified in [intro] through [cpp];68
  • an lvalue-to-rvalue conversion unless it is applied to
    • a glvalue of type cvstd​::​nullptr_t,
    • a non-volatile glvalue that refers to an object that is usable in constant expressions, or
    • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of E;
  • an lvalue-to-rvalue conversion that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;
  • an lvalue-to-rvalue conversion that is applied to an object with an indeterminate value;
  • an invocation of an implicitly-defined copy/move constructor or copy/move assignment operator for a union whose active member (if any) is mutable, unless the lifetime of the union object began within the evaluation of E;
  • in a lambda-expression, a reference to this or to a variable with automatic storage duration defined outside that lambda-expression, where the reference would be an odr-use ([basic.def.odr], [expr.prim.lambda]);
    [Example 5: void g() { const int n = 0; [=] { constexpr int i = n; // OK, n is not odr-used here constexpr int j = *&n; // error: &n would be an odr-use of n }; } — end example]
    [Note 3: 
    If the odr-use occurs in an invocation of a function call operator of a closure type, it no longer refers to this or to an enclosing variable with automatic storage duration due to the transformation ([expr.prim.lambda.capture]) of the id-expression into an access of the corresponding data member.
    [Example 6: auto monad = [](auto v) { return [=] { return v; }; }; auto bind = [](auto m) { return [=](auto fvm) { return fvm(m()); }; }; // OK to capture objects with automatic storage duration created during constant expression evaluation. static_assert(bind(monad(2))(monad)() == monad(2)()); — end example]
    — end note]
  • a conversion from a prvalue P of type “pointer to cv void” to a type “cv1 pointer to T”, where T is not cv2 void, unless P is a null pointer value or points to an object whose type is similar to T;
  • a reinterpret_cast ([expr.reinterpret.cast]);
  • a modification of an object ([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;
  • an invocation of a destructor ([class.dtor]) or a function call whose postfix-expression names a pseudo-destructor ([expr.call]), in either case for an object whose lifetime did not begin within the evaluation of E;
  • a new-expression ([expr.new]), unless either
    • the selected allocation function is a replaceable global allocation function ([new.delete.single], [new.delete.array]) and the allocated storage is deallocated within the evaluation of E, or
    • the selected allocation function is a non-allocating form ([new.delete.placement]) with an allocated type T, where
      • the placement argument to the new-expression points to an object whose type is similar to T ([conv.qual]) or, if T is an array type, to the first element of an object of a type similar to T, and
      • the placement argument points to storage whose duration began within the evaluation of E;
  • a delete-expression ([expr.delete]), unless it deallocates a region of storage allocated within the evaluation of E;
  • a call to an instance of std​::​allocator<T>​::​allocate ([allocator.members]), unless the allocated storage is deallocated within the evaluation of E;
  • a call to an instance of std​::​allocator<T>​::​deallocate ([allocator.members]), unless it deallocates a region of storage allocated within the evaluation of E;
  • a construction of an exception object, unless the exception object and all of its implicit copies created by invocations of std​::​current_exception or std​::​rethrow_exception ([propagation]) are destroyed within the evaluation of E;
  • an await-expression ([expr.await]);
  • a yield-expression ([expr.yield]);
  • a three-way comparison ([expr.spaceship]), relational ([expr.rel]), or equality ([expr.eq]) operator where the result is unspecified;
  • a dynamic_cast ([expr.dynamic.cast]) or typeid ([expr.typeid]) expression on a glvalue that refers to an object whose dynamic type is constexpr-unknown;
  • a dynamic_cast ([expr.dynamic.cast]) expression, typeid ([expr.typeid]) expression, or new-expression ([expr.new]) that would throw an exception where no definition of the exception type is reachable;
  • an asm-declaration ([dcl.asm]);
  • an invocation of the va_arg macro ([cstdarg.syn]);
  • a non-constant library call ([defns.nonconst.libcall]); or
  • a goto statement ([stmt.goto]).
    [Note 4: 
    A goto statement introduced by equivalence ([stmt.stmt]) is not in scope.
    For example, a while statement ([stmt.while]) can be executed during constant evaluation.
    — end note]
It is implementation-defined whether E is a core constant expression if E satisfies the constraints of a core constant expression, but evaluation of E has runtime-undefined behavior.
It is unspecified whether E is a core constant expression if E satisfies the constraints of a core constant expression, but evaluation of E would evaluate
[Example 7: int x; // not constant struct A { constexpr A(bool b) : m(b?42:x) { } int m; }; constexpr int v = A(true).m; // OK, constructor call initializes m with the value 42 constexpr int w = A(false).m; // error: initializer for m is x, which is non-constant constexpr int f1(int k) { constexpr int x = k; // error: x is not initialized by a constant expression // because lifetime of k began outside the initializer of x return x; } constexpr int f2(int k) { int x = k; // OK, not required to be a constant expression // because x is not constexpr return x; } constexpr int incr(int &n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k); // error: incr(k) is not a core constant expression // because lifetime of k began outside the expression incr(k) return x; } constexpr int h(int k) { int x = incr(k); // OK, incr(k) is not required to be a core constant expression return x; } constexpr int y = h(1); // OK, initializes y with the value 2 // h(1) is a core constant expression because // the lifetime of k begins inside h(1) — end example]
For the purposes of determining whether an expression E is a core constant expression, the evaluation of the body of a member function of std​::​allocator<T> as defined in [allocator.members], where T is a literal type, is ignored.
For the purposes of determining whether E is a core constant expression, the evaluation of a call to a trivial copy/move constructor or copy/move assignment operator of a union is considered to copy/move the active member of the union, if any.
[Note 5: 
The copy/move of the active member is trivial.
— end note]
For the purposes of determining whether E is a core constant expression, the evaluation of an id-expression that names a structured binding v ([dcl.struct.bind]) has the following semantics:
  • If v is an lvalue referring to the object bound to an invented reference r, the behavior is as if r were nominated.
  • Otherwise, if v names an array element or class member, the behavior is that of evaluating e[i] or e.m, respectively, where e is the name of the variable initialized from the initializer of the structured binding declaration, and i is the index of the element referred to by v or m is the name of the member referred to by v, respectively.
[Example 8: #include <tuple> struct S { mutable int m; constexpr S(int m): m(m) {} virtual int g() const; }; void f(std::tuple<S&> t) { auto [r] = t; static_assert(r.g() >= 0); // error: dynamic type is constexpr-unknown constexpr auto [m] = S(1); static_assert(m == 1); // error: lvalue-to-rvalue conversion on mutable // subobject e.m, where e is a constexpr object of type S using A = int[2]; constexpr auto [v0, v1] = A{2, 3}; static_assert(v0 + v1 == 5); // OK, equivalent to e[0] + e[1] where e is a constexpr array } — end example]
During the evaluation of an expression E as a core constant expression, all id-expressions and uses of *this that refer to an object or reference whose lifetime did not begin with the evaluation of E are treated as referring to a specific instance of that object or reference whose lifetime and that of all subobjects (including all union members) includes the entire constant evaluation.
For such an object that is not usable in constant expressions, the dynamic type of the object is constexpr-unknown.
For such a reference that is not usable in constant expressions, the reference is treated as binding to an unspecified object of the referenced type whose lifetime and that of all subobjects includes the entire constant evaluation and whose dynamic type is constexpr-unknown.
[Example 9: template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) { return N; } void use_array(int const (&gold_medal_mel)[2]) { constexpr auto gold = array_size(gold_medal_mel); // OK } constexpr auto olympic_mile() { const int ledecky = 1500; return []{ return ledecky; }; } static_assert(olympic_mile()() == 1500); // OK struct Swim { constexpr int phelps() { return 28; } virtual constexpr int lochte() { return 12; } int coughlin = 12; }; constexpr int how_many(Swim& swam) { Swim* p = &swam; return (p + 1 - 1)->phelps(); } void splash(Swim& swam) { static_assert(swam.phelps() == 28); // OK static_assert((&swam)->phelps() == 28); // OK Swim* pswam = &swam; static_assert(pswam->phelps() == 28); // error: lvalue-to-rvalue conversion on a pointer // not usable in constant expressions static_assert(how_many(swam) == 28); // OK static_assert(Swim().lochte() == 12); // OK static_assert(swam.lochte() == 12); // error: invoking virtual function on reference // with constexpr-unknown dynamic type static_assert(swam.coughlin == 12); // error: lvalue-to-rvalue conversion on an object // not usable in constant expressions } extern Swim dc; extern Swim& trident; constexpr auto& sandeno = typeid(dc); // OK, can only be typeid(Swim) constexpr auto& gallagher = typeid(trident); // error: constexpr-unknown dynamic type — end example]
An object a is said to have constant destruction if
  • it is not of class type nor (possibly multidimensional) array thereof, or
  • it is of class type or (possibly multidimensional) array thereof, that class type has a constexpr destructor, and for a hypothetical expression E whose only effect is to destroy a, E would be a core constant expression if the lifetime of a and its non-mutable subobjects (but not its mutable subobjects) were considered to start within E.
An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression.
[Note 6: 
Such expressions can be used as bit-field lengths ([class.bit]), as enumerator initializers if the underlying type is not fixed ([dcl.enum]), and as alignments.
— end note]
If an expression of literal class type is used in a context where an integral constant expression is required, then that expression is contextually implicitly converted ([conv]) to an integral or unscoped enumeration type and the selected conversion function shall be constexpr.
[Example 10: struct A { constexpr A(int i) : val(i) { } constexpr operator int() const { return val; } constexpr operator long() const { return 42; } private: int val; }; constexpr A a = alignof(int); alignas(a) int n; // error: ambiguous conversion struct B { int n : a; }; // error: ambiguous conversion — end example]
A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only and where the reference binding (if any) binds directly.
[Note 7: 
Such expressions can be used in new expressions ([expr.new]), as case expressions ([stmt.switch]), as enumerator initializers if the underlying type is fixed, as array bounds, and as non-type template arguments.
— end note]
A contextually converted constant expression of type bool is an expression, contextually converted to bool ([conv]), where the converted expression is a constant expression and the conversion sequence contains only the conversions above.
A constant expression is either a glvalue core constant expression that refers to an object or a non-immediate function, or a prvalue core constant expression whose value satisfies the following constraints:
  • each constituent reference refers to an object or a non-immediate function,
  • no constituent value of scalar type is an indeterminate value ([basic.indet]),
  • no constituent value of pointer type is a pointer to an immediate function or an invalid pointer value ([basic.compound]), and
  • no constituent value of pointer-to-member type designates an immediate function.
[Note 8: 
A glvalue core constant expression that either refers to or points to an unspecified object is not a constant expression.
— end note]
[Example 11: consteval int f() { return 42; } consteval auto g() { return f; } consteval int h(int (*p)() = g()) { return p(); } constexpr int r = h(); // OK constexpr auto e = g(); // error: a pointer to an immediate function is // not a permitted result of a constant expression struct S { int x; constexpr S() {} }; int i() { constexpr S s; // error: s.x has erroneous value } — end example]
Recommended practice: Implementations should provide consistent results of floating-point evaluations, irrespective of whether the evaluation is performed during translation or during program execution.
[Note 9: 
Since this document imposes no restrictions on the accuracy of floating-point operations, it is unspecified whether the evaluation of a floating-point expression during translation yields the same result as the evaluation of the same expression (or the same operations on the same values) during program execution.
[Example 12: bool f() { char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime return sizeof(array) == size; }
It is unspecified whether the value of f() will be true or false.
— end example]
— end note]
An expression or conversion is in an immediate function context if it is potentially evaluated and either:
  • its innermost enclosing non-block scope is a function parameter scope of an immediate function,
  • it is a subexpression of a manifestly constant-evaluated expression or conversion, or
  • its enclosing statement is enclosed ([stmt.pre]) by the compound-statement of a consteval if statement ([stmt.if]).
An invocation is an immediate invocation if it is a potentially-evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context.
An aggregate initialization is an immediate invocation if it evaluates a default member initializer that has a subexpression that is an immediate-escalating expression.
An expression or conversion is immediate-escalating if it is not initially in an immediate function context and it is either
  • a potentially-evaluated id-expression that denotes an immediate function that is not a subexpression of an immediate invocation, or
  • an immediate invocation that is not a constant expression and is not a subexpression of an immediate invocation.
An immediate-escalating function is
  • the call operator of a lambda that is not declared with the consteval specifier,
  • a defaulted special member function that is not declared with the consteval specifier, or
  • a function that results from the instantiation of a templated entity defined with the constexpr specifier.
An immediate-escalating expression shall appear only in an immediate-escalating function.
An immediate function is a function or constructor that is
  • declared with the consteval specifier, or
  • an immediate-escalating function F whose function body contains an immediate-escalating expression E such that E's innermost enclosing non-block scope is F's function parameter scope.
    [Note 10: 
    Default member initializers used to initialize a base or member subobject ([class.base.init]) are considered to be part of the function body ([dcl.fct.def.general]).
    — end note]
[Example 13: consteval int id(int i) { return i; } constexpr char id(char c) { return c; } template<class T> constexpr int f(T t) { return t + id(t); } auto a = &f<char>; // OK, f<char> is not an immediate function auto b = &f<int>; // error: f<int> is an immediate function static_assert(f(3) == 6); // OK template<class T> constexpr int g(T t) { // g<int> is not an immediate function return t + id(42); // because id(42) is already a constant } template<class T, class F> constexpr bool is_not(T t, F f) { return not f(t); } consteval bool is_even(int i) { return i % 2 == 0; } static_assert(is_not(5, is_even)); // OK int x = 0; template<class T> constexpr T h(T t = id(x)) { // h<int> is not an immediate function // id(x) is not evaluated when parsing the default argument ([dcl.fct.default], [temp.inst]) return t; } template<class T> constexpr T hh() { // hh<int> is an immediate function because of the invocation return h<T>(); // of the immediate function id in the default argument of h<int> } int i = hh<int>(); // error: hh<int>() is an immediate-escalating expression // outside of an immediate-escalating function struct A { int x; int y = id(x); }; template<class T> constexpr int k(int) { // k<int> is not an immediate function because A(42) is a return A(42).y; // constant expression and thus not immediate-escalating } — end example]
An expression or conversion is manifestly constant-evaluated if it is:
  • a constant-expression, or
  • the condition of a constexpr if statement ([stmt.if]), or
  • an immediate invocation, or
  • the result of substitution into an atomic constraint expression to determine whether it is satisfied ([temp.constr.atomic]), or
  • the initializer of a variable that is usable in constant expressions or has constant initialization ([basic.start.static]).69
    [Example 14: template<bool> struct X {}; X<std::is_constant_evaluated()> x; // type X<true> int y; const int a = std::is_constant_evaluated() ? y : 1; // dynamic initialization to 1 double z[a]; // error: a is not usable // in constant expressions const int b = std::is_constant_evaluated() ? 2 : y; // static initialization to 2 int c = y + (std::is_constant_evaluated() ? 2 : y); // dynamic initialization to y+y constexpr int f() { const int n = std::is_constant_evaluated() ? 13 : 17; // n is 13 int m = std::is_constant_evaluated() ? 13 : 17; // m can be 13 or 17 (see below) char arr[n] = {}; // char[13] return m + sizeof(arr); } int p = f(); // m is 13; initialized to 26 int q = p + f(); // m is 17 for this call; initialized to 56 — end example]
[Note 11: 
Except for a static_assert-message, a manifestly constant-evaluated expression is evaluated even in an unevaluated operand ([expr.context]).
— end note]
An expression or conversion is potentially constant evaluated if it is:
A function or variable is needed for constant evaluation if it is:
  • a constexpr function that is named by an expression that is potentially constant evaluated, or
  • a potentially-constant variable named by a potentially constant evaluated expression.
67)67)
Overload resolution ([over.match]) is applied as usual.
68)68)
This includes, for example, signed integer overflow ([expr.pre]), certain pointer arithmetic ([expr.add]), division by zero ([expr.mul]), or certain shift operations ([expr.shift]).
69)69)
Testing this condition can involve a trial evaluation of its initializer as described above.
70)70)
In some cases, constant evaluation is needed to determine whether a narrowing conversion is performed ([dcl.init.list]).
71)71)
In some cases, constant evaluation is needed to determine whether such an expression is value-dependent ([temp.dep.constexpr]).

8 Statements [stmt.stmt]

8.1 Preamble [stmt.pre]

[Note 1: 
The compound-statement of a lambda-expression is not a substatement of the statement (if any) in which the lambda-expression lexically appears.
— end note]
A statement S1 encloses a statement S2 if
A statement S1 is enclosed by a statement S2 if S2 encloses S1.
The rules for conditions apply both to selection-statements ([stmt.select]) and to the for and while statements ([stmt.iter]).
If a structured-binding-declaration appears in a condition, the condition is a structured binding declaration ([dcl.pre]).
A condition that is neither an expression nor a structured binding declaration is a declaration ([dcl.dcl]).
The declarator shall not specify a function or an array.
The decl-specifier-seq shall not define a class or enumeration.
If the auto type-specifier appears in the decl-specifier-seq, the type of the identifier being declared is deduced from the initializer as described in [dcl.spec.auto].
The decision variable of a condition that is neither an expression nor a structured binding declaration is the declared variable.
The decision variable of a condition that is a structured binding declaration is specified in [dcl.struct.bind].
The value of a condition that is not an expression in a statement other than a switch statement is the value of the decision variable contextually converted to bool ([conv]).
If that conversion is ill-formed, the program is ill-formed.
The value of a condition that is an expression is the value of the expression, contextually converted to bool for statements other than switch; if that conversion is ill-formed, the program is ill-formed.
The value of the condition will be referred to as simply “the condition” where the usage is unambiguous.
If a condition can be syntactically resolved as either an expression or a declaration, it is interpreted as the latter.
In the decl-specifier-seq of a condition, including that of any structured-binding-declaration of the condition, each decl-specifier shall be either a type-specifier or constexpr.

8.2 Label [stmt.label]

A label can be added to a statement or used anywhere in a compound-statement.
The optional attribute-specifier-seq appertains to the label.
The only use of a label with an identifier is as the target of a goto.
No two labels in a function shall have the same identifier.
A label can be used in a goto statement before its introduction.
A labeled-statement whose label is a case or default label shall be enclosed by ([stmt.pre]) a switch statement ([stmt.switch]).
A control-flow-limited statement is a statement S for which:
  • a case or default label appearing within S shall be associated with a switch statement ([stmt.switch]) within S, and
  • a label declared in S shall only be referred to by a statement ([stmt.goto]) in S.

8.3 Expression statement [stmt.expr]

Expression statements have the form
The expression is a discarded-value expression.
All side effects from an expression statement are completed before the next statement is executed.
An expression statement with the expression missing is called a null statement.
[Note 1: 
Most statements are expression statements — usually assignments or function calls.
A null statement is useful to supply a null body to an iteration statement such as a while statement ([stmt.while]).
— end note]

8.4 Compound statement or block [stmt.block]

A compound statement (also known as a block) groups a sequence of statements into a single statement.
A label at the end of a compound-statement is treated as if it were followed by a null statement.
[Note 1: 
A compound statement defines a block scope ([basic.scope]).
A declaration is a statement ([stmt.dcl]).
— end note]

8.5 Selection statements [stmt.select]

8.5.1 General [stmt.select.general]

Selection statements choose one of several flows of control.
selection-statement:
if constexpr ( init-statement condition ) statement
if constexpr ( init-statement condition ) statement else statement
if ! consteval compound-statement
if ! consteval compound-statement else statement
switch ( init-statement condition ) statement
See [dcl.meaning] for the optional attribute-specifier-seq in a condition.
[Note 1: 
An init-statement ends with a semicolon.
— end note]
[Note 2: 
Each selection-statement and each substatement of a selection-statement has a block scope ([basic.scope.block]).
— end note]

8.5.2 The if statement [stmt.if]

If the condition ([stmt.pre]) yields true, the first substatement is executed.
If the else part of the selection statement is present and the condition yields false, the second substatement is executed.
If the first substatement is reached via a label, the condition is not evaluated and the second substatement is not executed.
In the second form of if statement (the one including else), if the first substatement is also an if statement then that inner if statement shall contain an else part.72
If the if statement is of the form if constexpr, the value of the condition is contextually converted to bool and the converted expression shall be a constant expression ([expr.const]); this form is called a constexpr if statement.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement.
During the instantiation of an enclosing templated entity ([temp.pre]), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
Each substatement of a constexpr if statement is a control-flow-limited statement ([stmt.label]).
[Example 1: if constexpr (sizeof(int[2])) {} // OK, narrowing allowed — end example]
[Note 1: 
Odr-uses ([basic.def.odr]) in a discarded statement do not require an entity to be defined.
— end note]
[Example 2: template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) { // ... handle p if constexpr (sizeof...(rs) > 0) g(rs...); // never instantiated with an empty argument list } extern int x; // no definition of x required int f() { if constexpr (true) return 0; else if (x) return x; else return -x; } — end example]
An if statement of the form
if constexpr ( init-statement condition ) statement
is equivalent to
{
   init-statement
   if constexpr ( condition ) statement
}
and an if statement of the form
if constexpr ( init-statement condition ) statement else statement
is equivalent to
{
   init-statement
   if constexpr ( condition ) statement else statement
}
except that the init-statement is in the same scope as the condition.
An if statement of the form if consteval is called a consteval if statement.
The statement, if any, in a consteval if statement shall be a compound-statement.
[Example 3: constexpr void f(bool b) { if (true) if consteval { } else ; // error: not a compound-statement; else not associated with outer if } — end example]
If a consteval if statement is evaluated in a context that is manifestly constant-evaluated ([expr.const]), the first substatement is executed.
[Note 2: 
The first substatement is an immediate function context.
— end note]
Otherwise, if the else part of the selection statement is present, then the second substatement is executed.
Each substatement of a consteval if statement is a control-flow-limited statement ([stmt.label]).
An if statement of the form
if ! consteval compound-statement
is not itself a consteval if statement, but is equivalent to the consteval if statement
if consteval { } else compound-statement
An if statement of the form
if ! consteval compound-statement else statement
is not itself a consteval if statement, but is equivalent to the consteval if statement
if consteval statement else compound-statement
72)72)
In other words, the else is associated with the nearest un-elsed if.

8.5.3 The switch statement [stmt.switch]

The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
If the condition is an expression, the value of the condition is the value of the expression; otherwise, it is the value of the decision variable.
The value of the condition shall be of integral type, enumeration type, or class type.
If of class type, the condition is contextually implicitly converted to an integral or enumeration type.
If the (possibly converted) type is subject to integral promotions, the condition is converted to the promoted type.
Any statement within the switch statement can be labeled with one or more case labels as follows: where the constant-expression shall be a converted constant expression of the adjusted type of the switch condition.
No two of the case constants in the same switch shall have the same value after conversion.
There shall be at most one label of the form default : within a switch statement.
Switch statements can be nested; a case or default label is associated with the smallest switch enclosing it.
When the switch statement is executed, its condition is evaluated.
If one of the case constants has the same value as the condition, control is passed to the statement following the matched case label.
If no case constant matches the condition, and if there is a default label, control passes to the statement labeled by the default label.
If no case matches and if there is no default then none of the statements in the switch is executed.
case and default labels in themselves do not alter the flow of control, which continues unimpeded across such labels.
To exit from a switch, see break, [stmt.break].
[Note 1: 
Usually, the substatement that is the subject of a switch is compound and case and default labels appear on the top-level statements contained within the (compound) substatement, but this is not required.
Declarations can appear in the substatement of a switch statement.
— end note]
A switch statement of the form is equivalent to
{
   init-statement
   switch ( condition ) statement
}
except that the init-statement is in the same scope as the condition.

8.6 Iteration statements [stmt.iter]

8.6.1 General [stmt.iter.general]

The substatement in an iteration-statement implicitly defines a block scope which is entered and exited each time through the loop.
If the substatement in an iteration-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original statement.
[Example 1: 
while (--x >= 0) int i; can be equivalently rewritten as while (--x >= 0) { int i; }
Thus after the while statement, i is no longer in scope.
— end example]
A trivially empty iteration statement is an iteration statement matching one of the following forms: The controlling expression of a trivially empty iteration statement is the expression of a while, do, or for statement (or true, if the for statement has no expression).
A trivial infinite loop is a trivially empty iteration statement for which the converted controlling expression is a constant expression, when interpreted as a constant-expression ([expr.const]), and evaluates to true.
The statement of a trivial infinite loop is replaced with a call to the function std​::​this_thread​::​yield ([thread.thread.this]); it is implementation-defined whether this replacement occurs on freestanding implementations.
[Note 2: 
In a freestanding environment, concurrent forward progress is not guaranteed; such systems therefore require explicit cooperation.
A call to yield can add implicit cooperation where none is otherwise intended.
— end note]

8.6.2 The while statement [stmt.while]

In the while statement, the substatement is executed repeatedly until the value of the condition ([stmt.pre]) becomes false.
The test takes place before each execution of the substatement.
A while statement is equivalent to
label :
{
   if ( condition ) {
      statement
      goto label ;
   }
}
[Note 1: 
The variable created in the condition is destroyed and created with each iteration of the loop.
[Example 1: struct A { int val; A(int i) : val(i) { } ~A() { } operator bool() { return val != 0; } }; int i = 1; while (A a = i) { // ... i = 0; }
In the while-loop, the constructor and destructor are each called twice, once for the condition that succeeds and once for the condition that fails.
— end example]
— end note]

8.6.3 The do statement [stmt.do]

The expression is contextually converted to bool; if that conversion is ill-formed, the program is ill-formed.
In the do statement, the substatement is executed repeatedly until the value of the expression becomes false.
The test takes place after each execution of the statement.

8.6.4 The for statement [stmt.for]

The for statement is equivalent to
{
   init-statement
   while ( condition ) {
      statement
      expression ;
   }
}
except that the init-statement is in the same scope as the condition, and except that a continue in statement (not enclosed in another iteration statement) will execute expression before re-evaluating condition.
[Note 1: 
Thus the first statement specifies initialization for the loop; the condition ([stmt.pre]) specifies a test, sequenced before each iteration, such that the loop is exited when the condition becomes false; the expression often specifies incrementing that is sequenced after each iteration.
— end note]
Either or both of the condition and the expression can be omitted.
A missing condition makes the implied while clause equivalent to while(true).

8.6.5 The range-based for statement [stmt.ranged]

The range-based for statement is equivalent to
{
   init-statement
   auto &&range = for-range-initializer ;
   auto begin = begin-expr ;
   auto end = end-expr ;
   for ( ; begin != end; ++begin ) {
      for-range-declaration = * begin ;
      statement
   }
}
where
  • if the for-range-initializer is an expression, it is regarded as if it were surrounded by parentheses (so that a comma operator cannot be reinterpreted as delimiting two init-declarators);
  • range, begin, and end are variables defined for exposition only; and
  • begin-expr and end-expr are determined as follows:
    • if the type of range is a reference to an array type R, begin-expr and end-expr are range and range + N, respectively, where N is the array bound.
      If R is an array of unknown bound or an array of incomplete type, the program is ill-formed;
    • if the type of range is a reference to a class type C, and searches in the scope of C ([class.member.lookup]) for the names begin and end each find at least one declaration, begin-expr and end-expr are range.begin() and range.end(), respectively;
    • otherwise, begin-expr and end-expr are begin(range) and end(range), respectively, where begin and end undergo argument-dependent lookup ([basic.lookup.argdep]).
      [Note 1: 
      Ordinary unqualified lookup ([basic.lookup.unqual]) is not performed.
      — end note]
[Example 1: int array[5] = { 1, 2, 3, 4, 5 }; for (int& x : array) x *= 2; — end example]
[Note 2: 
The lifetime of some temporaries in the for-range-initializer is extended to cover the entire loop ([class.temporary]).
— end note]
[Example 2: using T = std::list<int>; const T& f1(const T& t) { return t; } const T& f2(T t) { return t; } T g(); void foo() { for (auto e : f1(g())) {} // OK, lifetime of return value of g() extended for (auto e : f2(g())) {} // undefined behavior } — end example]
In the decl-specifier-seq of a for-range-declaration, each decl-specifier shall be either a type-specifier or constexpr.
The decl-specifier-seq shall not define a class or enumeration.

8.7 Jump statements [stmt.jump]

8.7.1 General [stmt.jump.general]

Jump statements unconditionally transfer control.
[Note 1: 
On exit from a scope (however accomplished), objects with automatic storage duration that have been constructed in that scope are destroyed in the reverse order of their construction ([stmt.dcl]).
For temporaries, see [class.temporary].
However, the program can be terminated (by calling std​::​exit() or std​::​abort() ([support.start.term]), for example) without destroying objects with automatic storage duration.
— end note]
[Note 2: 
A suspension of a coroutine ([expr.await]) is not considered to be an exit from a scope.
— end note]

8.7.2 The break statement [stmt.break]

A break statement shall be enclosed by ([stmt.pre]) an iteration-statement ([stmt.iter]) or a switch statement ([stmt.switch]).
The break statement causes termination of the smallest such enclosing statement; control passes to the statement following the terminated statement, if any.

8.7.3 The continue statement [stmt.cont]

A continue statement shall be enclosed by ([stmt.pre]) an iteration-statement ([stmt.iter]).
The continue statement causes control to pass to the loop-continuation portion of the smallest such enclosing statement, that is, to the end of the loop.
More precisely, in each of the statements
while (foo) { { // ... } contin: ; }
do { { // ... } contin: ; } while (foo);
for (;;) { { // ... } contin: ; }
a continue not contained in an enclosed iteration statement is equivalent to goto contin.

8.7.4 The return statement [stmt.return]

A function returns control to its caller by the return statement.
The expr-or-braced-init-list of a return statement is called its operand.
A return statement with no operand shall be used only in a function whose return type is cv void, a constructor ([class.ctor]), or a destructor ([class.dtor]).
A return statement with an operand of type void shall be used only in a function that has a cv void return type.
A return statement with any other operand shall be used only in a function that has a return type other than cv void; the return statement initializes the returned reference or prvalue result object of the (explicit or implicit) function call by copy-initialization from the operand.
[Note 1: 
A constructor or destructor does not have a return type.
— end note]
[Note 2: 
A 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.
A copy operation associated with a return statement can be elided or converted to a move operation if an automatic storage duration variable is returned ([class.copy.elision]).
— end note]
The destructor for the result object is potentially invoked ([class.dtor], [except.ctor]).
[Example 1: class A { ~A() {} }; A f() { return A(); } // error: destructor of A is private (even though it is never invoked) — end example]
Flowing off the end of a constructor, a destructor, or a non-coroutine function with a cv void return type is equivalent to a return with no operand.
Otherwise, flowing off the end of a function that is neither main ([basic.start.main]) nor a coroutine ([dcl.fct.def.coroutine]) results in undefined behavior.
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables ([stmt.jump]) of the block enclosing the return statement.
In a function whose return type is a reference, other than an invented function for std​::​is_convertible ([meta.rel]), a return statement that binds the returned reference to a temporary expression ([class.temporary]) is ill-formed.
[Example 2: auto&& f1() { return 42; // ill-formed } const double& f2() { static int x = 42; return x; // ill-formed } auto&& id(auto&& r) { return static_cast<decltype(r)&&>(r); } auto&& f3() { return id(42); // OK, but probably a bug } — end example]

8.7.5 The co_return statement [stmt.return.coroutine]

A co_return statement transfers control to the caller or resumer of a coroutine ([dcl.fct.def.coroutine]).
A coroutine shall not enclose a return statement ([stmt.return]).
[Note 1: 
For this determination, it is irrelevant whether the return statement is enclosed by a discarded statement ([stmt.if]).
— end note]
The expr-or-braced-init-list of a co_return statement is called its operand.
Let p be an lvalue naming the coroutine promise object ([dcl.fct.def.coroutine]).
A co_return statement is equivalent to:
{ S; goto final-suspend; }
where final-suspend is the exposition-only label defined in [dcl.fct.def.coroutine] and S is defined as follows:
If a search for the name return_void in the scope of the promise type finds any declarations, flowing off the end of a coroutine's function-body is equivalent to a co_return with no operand; otherwise flowing off the end of a coroutine's function-body results in undefined behavior.

8.7.6 The goto statement [stmt.goto]

The goto statement unconditionally transfers control to the statement labeled by the identifier.
The identifier shall be a label located in the current function.

8.8 Declaration statement [stmt.dcl]

A declaration statement introduces one or more new names into a block; it has the form
[Note 1: 
If an identifier introduced by a declaration was previously declared in an outer block, the outer declaration is hidden for the remainder of the block ([basic.lookup.unqual]), after which it resumes its force.
— end note]
A block variable with automatic storage duration ([basic.stc.auto]) is active everywhere in the scope to which it belongs after its init-declarator.
Upon each transfer of control (including sequential execution of statements) within a function from point P to point Q, all block variables with automatic storage duration that are active at P and not at Q are destroyed in the reverse order of their construction.
Then, all block variables with automatic storage duration that are active at Q but not at P are initialized in declaration order; unless all such variables have vacuous initialization ([basic.life]), the transfer of control shall not be a jump.73
When a declaration-statement is executed, P and Q are the points immediately before and after it; when a function returns, Q is after its body.
[Example 1: void f() { // ... goto lx; // error: jump into scope of a // ... ly: X a = 1; // ... lx: goto ly; // OK, jump implies destructor call for a followed by // construction again immediately following label ly } — end example]
Dynamic initialization of a block variable with static storage duration or thread storage duration is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization.
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
[Note 2: 
A conforming implementation cannot introduce any deadlock around execution of the initializer.
Deadlocks might still be caused by the program logic; the implementation need only avoid deadlocks due to its own synchronization operations.
— end note]
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
[Example 2: int foo(int i) { static int s = foo(2*i); // undefined behavior: recursive call return i+1; } — end example]
An object associated with a block variable with static or thread storage duration will be destroyed if and only if it was constructed.
[Note 3: 
[basic.start.term] describes the order in which such objects are destroyed.
— end note]
73)73)
The transfer from the condition of a switch statement to a case label is considered a jump in this respect.

8.9 Ambiguity resolution [stmt.ambig]

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (.
In those cases the statement is considered a declaration, except as specified below.
[Note 1: 
If the statement cannot syntactically be a declaration, there is no ambiguity, so this rule does not apply.
In some cases, the whole statement needs to be examined to determine whether this is the case.
This resolves the meaning of many examples.
[Example 1: 
T(a)->m = 7; // expression-statement T(a)++; // expression-statement T(a,5)<<c; // expression-statement T(*d)(int); // declaration T(e)[5]; // declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
In the last example above, g, which is a pointer to T, is initialized to double(3).
This is of course ill-formed for semantic reasons, but that does not affect the syntactic analysis.
— end example]
The remaining cases are declarations.
[Example 2: class T { // ... public: T(); T(int); T(int, int); }; T(a); // declaration T(*b)(); // declaration T(c)=7; // declaration T(d),e,f=3; // declaration extern int h; T(g)(h,2); // declaration — end example]
— end note]
The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation.
Class templates are instantiated as necessary to determine if a qualified name is a type-name.
Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration.
If, during parsing, lookup finds that a name in a template argument is bound to (part of) the declaration being parsed, the program is ill-formed.
No diagnostic is required.
[Example 3: struct T1 { T1 operator()(int x) { return T1(x); } int operator=(int x) { return x; } T1(int) { } }; struct T2 { T2(int) { } }; int a, (*(*b)(T2))(int), c, d; void f() { // disambiguation requires this to be parsed as a declaration: T1(a) = 3, T2(4), // T2 will be declared as a variable of type T1, but this will not (*(*b)(T2(c)))(int(d)); // allow the last part of the declaration to parse properly, // since it depends on T2 being a type-name } — end example]
A syntactically ambiguous statement that can syntactically be a declaration with an outermost declarator with a trailing-return-type is considered a declaration only if it starts with auto.
[Example 4: struct M; struct S { S* operator()(); int N; int M; void mem(S s) { auto(s)()->M; // expression, S​::​M hides ​::​M } }; void f(S s) { { auto(s)()->N; // expression auto(s)()->M; // function declaration } { S(s)()->N; // expression S(s)()->M; // expression } } — end example]

9 Declarations [dcl.dcl]

9.1 Preamble [dcl.pre]

Declarations generally specify how names are to be interpreted.
Declarations have the form
[Note 1:  — end note]
Certain declarations contain one or more scopes ([basic.scope.scope]).
Unless otherwise stated, utterances in [dcl.dcl] about components in, of, or contained by a declaration or subcomponent thereof refer only to those components of the declaration that are not nested within scopes nested within the declaration.
If a name-declaration matches the syntactic requirements of friend-type-declaration, it is a friend-type-declaration.
Attributes are described in [dcl.attr].
decl-specifiers, the principal components of a decl-specifier-seq, are described in [dcl.spec].
declarators, the components of an init-declarator-list, are described in [dcl.decl].
The attribute-specifier-seq appertains to each of the entities declared by the declarators of the init-declarator-list.
[Note 2: 
In the declaration for an entity, attributes appertaining to that entity can appear at the start of the declaration and after the declarator-id for that declaration.
— end note]
[Example 1: [[noreturn]] void f [[noreturn]] (); // OK — end example]
If a declarator-id is a name, the init-declarator and (hence) the declaration introduce that name.
[Note 3: 
Otherwise, the declarator-id is a qualified-id or names a destructor or its unqualified-id is a template-id and no name is introduced.
— end note]
The defining-type-specifiers ([dcl.type]) in the decl-specifier-seq and the recursive declarator structure describe a type ([dcl.meaning]), which is then associated with the declarator-id.
In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class ([class.pre]) or enumeration ([dcl.enum]), that is, when the decl-specifier-seq contains either a class-specifier, an elaborated-type-specifier with a class-key ([class.name]), or an enum-specifier.
In these cases and whenever a class-specifier or enum-specifier is present in the decl-specifier-seq, the identifiers in these specifiers are also declared (as class-names, enum-names, or enumerators, depending on the syntax).
In such cases, the decl-specifier-seq shall (re)introduce one or more names into the program.
[Example 2: enum { }; // error typedef class { }; // error — end example]
Each decl-specifier in the decl-specifier-seq shall be constexpr, constinit, static, thread_local, auto ([dcl.spec.auto]), or a cv-qualifier.
The declaration shall contain at most one sb-identifier whose identifier is preceded by an ellipsis.
If the declaration contains any such sb-identifier, it shall declare a templated entity ([temp.pre]).
[Example 3: template<class T> concept C = true; C auto [x, y] = std::pair{1, 2}; // error: constrained placeholder-type-specifier // not permitted for structured bindings — end example]
The initializer shall be of the form “= assignment-expression”, of the form “{ assignment-expression }”, or of the form “( assignment-expression ).
If the structured-binding-declaration appears as a condition, the assignment-expression shall be of non-union class type.
Otherwise, the assignment-expression shall be of array or non-union class type.
If the decl-specifier-seq contains the typedef specifier, the declaration is a typedef declaration and each declarator-id is declared to be a typedef-name, synonymous with its associated type ([dcl.typedef]).
[Note 4:  — end note]
Otherwise, if the type associated with a declarator-id is a function type ([dcl.fct]), the declaration is a function declaration.
Otherwise, if the type associated with a declarator-id is an object or reference type, the declaration is an object declaration.
Otherwise, the program is ill-formed.
[Example 4: int f(), x; // OK, function declaration for f and object declaration for x extern void g(), // OK, function declaration for g y; // error: void is not an object type — end example]
An object definition causes storage of appropriate size and alignment to be reserved and any appropriate initialization ([dcl.init]) to be done.
Syntactic components beyond those found in the general form of simple-declaration are added to a function declaration to make a function-definition.
A token sequence starting with { or = is treated as a function-body ([dcl.fct.def.general]) if the type of the declarator-id ([dcl.meaning.general]) is a function type, and is otherwise treated as a brace-or-equal-initializer ([dcl.init.general]).
[Note 5: 
If the declaration acquires a function type through template instantiation, the program is ill-formed; see [temp.spec.general].
The function type of a function definition cannot be specified with a typedef-name ([dcl.fct]).
— end note]
A nodeclspec-function-declaration shall declare a constructor, destructor, or conversion function.
[Note 6: 
Because a member function cannot be subject to a non-defining declaration outside of a class definition ([class.mfct]), a nodeclspec-function-declaration can only be used in a template-declaration ([temp.pre]), explicit-instantiation ([temp.explicit]), or explicit-specialization ([temp.expl.spec]).
— end note]
If a static_assert-message matches the syntactic requirements of unevaluated-string, it is an unevaluated-string and the text of the static_assert-message is the text of the unevaluated-string.
Otherwise, a static_assert-message shall be an expression M such that
  • the expression M.size() is implicitly convertible to the type std​::​size_t, and
  • the expression M.data() is implicitly convertible to the type “pointer to const char.
In a static_assert-declaration, the constant-expression E is contextually converted to bool and the converted expression shall be a constant expression ([expr.const]).
If the value of the expression E when so converted is true or the expression is evaluated in the context of a template definition, the declaration has no effect and the static_assert-message is an unevaluated operand ([expr.context]).
Otherwise, the static_assert-declaration fails and
  • the program is ill-formed, and
  • if the static_assert-message is a constant-expression M,
    • M.size() shall be a converted constant expression of type std​::​size_t and let N denote the value of that expression,
    • M.data(), implicitly converted to the type “pointer to const char”, shall be a core constant expression and let D denote the converted expression,
    • for each i where , D[i] shall be an integral constant expression, and
    • the text of the static_assert-message is formed by the sequence of N code units, starting at D, of the ordinary literal encoding ([lex.charset]).
Recommended practice: When a static_assert-declaration fails, the resulting diagnostic message should include the text of the static_assert-message, if one is supplied.
[Example 5: static_assert(sizeof(int) == sizeof(void*), "wrong pointer size"); static_assert(sizeof(int[2])); // OK, narrowing allowed template <class T> void f(T t) { if constexpr (sizeof(T) == sizeof(int)) { use(t); } else { static_assert(false, "must be int-sized"); } } void g(char c) { f(0); // OK f(c); // error on implementations where sizeof(int) > 1: must be int-sized } — end example]
An empty-declaration has no effect.
Except where otherwise specified, the meaning of an attribute-declaration is implementation-defined.

9.2 Specifiers [dcl.spec]

9.2.1 General [dcl.spec.general]

The specifiers that can be used in a declaration are
The optional attribute-specifier-seq in a decl-specifier-seq appertains to the type determined by the preceding decl-specifiers ([dcl.meaning]).
The attribute-specifier-seq affects the type only for the declaration it appears in, not other declarations involving the same type.
At most one of each of the decl-specifiers friend, typedef, or inline shall appear in a decl-specifier-seq.
At most one of the constexpr, consteval, and constinit keywords shall appear in a decl-specifier-seq.
If a type-name is encountered while parsing a decl-specifier-seq, it is interpreted as part of the decl-specifier-seq if and only if there is no previous defining-type-specifier other than a cv-qualifier in the decl-specifier-seq.
The sequence shall be self-consistent as described below.
[Example 1: typedef char* Pc; static Pc; // error: name missing
Here, the declaration static Pc is ill-formed because no name was specified for the static variable of type Pc.
To get a variable called Pc, a type-specifier (other than const or volatile) has to be present to indicate that the typedef-name Pc is the name being (re)declared, rather than being part of the decl-specifier sequence.
For another example, void f(const Pc); // void f(char* const) (not const char*) void g(const int Pc); // void g(const int)
— end example]
[Note 1: 
Since signed, unsigned, long, and short by default imply int, a type-name appearing after one of those specifiers is treated as the name being (re)declared.
[Example 2: void h(unsigned Pc); // void h(unsigned int) void k(unsigned int Pc); // void k(unsigned int) — end example]
— end note]

9.2.2 Storage class specifiers [dcl.stc]

The storage class specifiers are
storage-class-specifier:
static
thread_local
extern
mutable
At most one storage-class-specifier shall appear in a given decl-specifier-seq, except that thread_local may appear with static or extern.
If thread_local appears in any declaration of a variable it shall be present in all declarations of that entity.
If a storage-class-specifier appears in a decl-specifier-seq, there can be no typedef specifier in the same decl-specifier-seq and the init-declarator-list or member-declarator-list of the declaration shall not be empty (except for an anonymous union declared in a namespace scope ([class.union.anon])).
The storage-class-specifier applies to the name declared by each init-declarator in the list and not to any names declared by other specifiers.
[Note 1: 
See [temp.expl.spec] and [temp.explicit] for restrictions in explicit specializations and explicit instantiations, respectively.
— end note]
[Note 2: 
A variable declared without a storage-class-specifier at block scope or declared as a function parameter has automatic storage duration by default.
— end note]
The thread_local specifier indicates that the named entity has thread storage duration ([basic.stc.thread]).
It shall be applied only to the declaration of a variable of namespace or block scope, to a structured binding declaration ([dcl.struct.bind]), or to the declaration of a static data member.
When thread_local is applied to a variable of block scope the storage-class-specifier static is implied if no other storage-class-specifier appears in the decl-specifier-seq.
The static specifier shall be applied only to the declaration of a variable or function, to a structured binding declaration ([dcl.struct.bind]), or to the declaration of an anonymous union ([class.union.anon]).
There can be no static function declarations within a block, nor any static function parameters.
A static specifier used in the declaration of a variable declares the variable to have static storage duration ([basic.stc.static]), unless accompanied by the thread_local specifier, which declares the variable to have thread storage duration ([basic.stc.thread]).
A static specifier can be used in declarations of class members; [class.static] describes its effect.
For the linkage of a name declared with a static specifier, see [basic.link].
The extern specifier shall be applied only to the declaration of a variable or function.
The extern specifier shall not be used in the declaration of a class member or function parameter.
For the linkage of a name declared with an extern specifier, see [basic.link].
[Note 3: 
The extern keyword can also be used in explicit-instantiations and linkage-specifications, but it is not a storage-class-specifier in such contexts.
— end note]
All declarations for a given entity shall give its name the same linkage.
[Note 4: 
The linkage given by some declarations is affected by previous declarations.
Overloads are distinct entities.
— end note]
[Example 1: static char* f(); // f() has internal linkage char* f() // f() still has internal linkage { /* ... */ } char* g(); // g() has external linkage static char* g() // error: inconsistent linkage { /* ... */ } void h(); inline void h(); // external linkage inline void l(); void l(); // external linkage inline void m(); extern void m(); // external linkage static void n(); inline void n(); // internal linkage static int a; // a has internal linkage int a; // error: two definitions static int b; // b has internal linkage extern int b; // b still has internal linkage int c; // c has external linkage static int c; // error: inconsistent linkage extern int d; // d has external linkage static int d; // error: inconsistent linkage — end example]
The name of a declared but undefined class can be used in an extern declaration.
Such a declaration can only be used in ways that do not require a complete class type.
[Example 2: struct S; extern S a; extern S f(); extern void g(S); void h() { g(a); // error: S is incomplete f(); // error: S is incomplete } — end example]
The mutable specifier shall appear only in the declaration of a non-static data member ([class.mem]) whose type is neither const-qualified nor a reference type.
[Example 3: class X { mutable const int* p; // OK mutable int* const q; // error }; — end example]
[Note 5: 
The mutable specifier on a class data member nullifies a 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 ([basic.type.qualifier], [dcl.type.cv]).
— end note]

9.2.3 Function specifiers [dcl.fct.spec]

A function-specifier can be used only in a function declaration.
At most one explicit-specifier and at most one virtual keyword shall appear in a decl-specifier-seq.
The virtual specifier shall be used only in the initial declaration of a non-static member function; see [class.virtual].
An explicit-specifier shall be used only in the declaration of a constructor or conversion function within its class definition; see [class.conv.ctor] and [class.conv.fct].
In an explicit-specifier, the constant-expression, if supplied, shall be a contextually converted constant expression of type bool ([expr.const]).
The explicit-specifier explicit without a constant-expression is equivalent to the explicit-specifier explicit(true).
If the constant expression evaluates to true, the function is explicit.
Otherwise, the function is not explicit.
A ( token that follows explicit is parsed as part of the explicit-specifier.
[Example 1: struct S { explicit(sizeof(char[2])) S(char); // error: narrowing conversion of value 2 to type bool explicit(sizeof(char)) S(bool); // OK, conversion of value 1 to type bool is non-narrowing }; — end example]

9.2.4 The typedef specifier [dcl.typedef]

Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming fundamental ([basic.fundamental]) or compound ([basic.compound]) types.
The typedef specifier shall not be combined in a decl-specifier-seq with any other kind of specifier except a defining-type-specifier, and it shall not be used in the decl-specifier-seq of a parameter-declaration ([dcl.fct]) nor in the decl-specifier-seq of a function-definition ([dcl.fct.def]).
If a typedef specifier appears in a declaration without a declarator, the program is ill-formed.
A name declared with the typedef specifier becomes a typedef-name.
A typedef-name names the type associated with the identifier ([dcl.decl]) or simple-template-id ([temp.pre]); a typedef-name is thus a synonym for another type.
A typedef-name does not introduce a new type the way a class declaration ([class.name]) or enum declaration ([dcl.enum]) does.
[Example 1: 
After typedef int MILES, *KLICKSP; the constructions MILES distance; extern KLICKSP metricp; are all correct declarations; the type of distance is int and that of metricp is “pointer to int.
— end example]
A typedef-name can also be introduced by an alias-declaration.
The identifier following the using keyword is not looked up; it becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name.
Such a typedef-name has the same semantics as if it were introduced by the typedef specifier.
In particular, it does not define a new type.
[Example 2: using handler_t = void (*)(int); extern handler_t ignore; extern void (*ignore)(int); // redeclare ignore template<class T> struct P { }; using cell = P<cell*>; // error: cell not found ([basic.scope.pdecl]) — end example]
The defining-type-specifier-seq of the defining-type-id shall not define a class or enumeration if the alias-declaration is the declaration of a template-declaration.
A simple-template-id is only a typedef-name if its template-name names an alias template or a template template-parameter.
[Note 1: 
A simple-template-id that names a class template specialization is a class-name ([class.name]).
If a typedef-name is used to identify the subject of an elaborated-type-specifier ([dcl.type.elab]), a class definition, a constructor declaration, or a destructor declaration, the program is ill-formed.
— end note]
[Example 3: struct S { S(); ~S(); }; typedef struct S T; S a = T(); // OK struct T * p; // error — end example]
An unnamed class or enumeration C defined in a typedef declaration has the first typedef-name declared by the declaration to be of type C as its typedef name for linkage purposes ([basic.link]).
[Note 2: 
A typedef declaration involving a lambda-expression does not itself define the associated closure type, and so the closure type is not given a typedef name for linkage purposes.
— end note]
[Example 4: typedef struct { } *ps, S; // S is the typedef name for linkage purposes typedef decltype([]{}) C; // the closure type has no typedef name for linkage purposes — end example]
An unnamed class with a typedef name for linkage purposes shall not
  • declare any members other than non-static data members, member enumerations, or member classes,
  • have any base classes or default member initializers, or
  • contain a lambda-expression,
and all member classes shall also satisfy these requirements (recursively).
[Example 5: typedef struct { int f() {} } X; // error: struct with typedef name for linkage has member functions — end example]

9.2.5 The friend specifier [dcl.friend]

The friend specifier is used to specify access to class members; see [class.friend].

9.2.6 The constexpr and consteval specifiers [dcl.constexpr]

The constexpr specifier shall be applied only to the definition of a variable or variable template, a structured binding declaration, or the declaration of a function or function template.
The consteval specifier shall be applied only to the declaration of a function or function template.
A function or static data member declared with the constexpr or consteval specifier on its first declaration is implicitly an inline function or variable ([dcl.inline]).
If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.
[Note 1: 
An explicit specialization can differ from the template declaration with respect to the constexpr or consteval specifier.
— end note]
[Note 2: 
Function parameters cannot be declared constexpr.
— end note]
[Example 1: constexpr void square(int &x); // OK, declaration constexpr int bufsz = 1024; // OK, definition constexpr struct pixel { // error: pixel is a type int x; int y; constexpr pixel(int); // OK, declaration }; constexpr pixel::pixel(int a) : x(a), y(x) // OK, definition { square(x); } constexpr pixel small(2); // error: square not defined, so small(2) // not constant ([expr.const]) so constexpr not satisfied constexpr void square(int &x) { // OK, definition x *= x; } constexpr pixel large(4); // OK, square defined int next(constexpr int x) { // error: not for parameters return x + 1; } extern constexpr int memsz; // error: not a definition — end example]
A constexpr or consteval specifier used in the declaration of a function declares that function to be a constexpr function.
[Note 3: 
A function or constructor declared with the consteval specifier is an immediate function ([expr.const]).
— end note]
A destructor, an allocation function, or a deallocation function shall not be declared with the consteval specifier.
A function is constexpr-suitable if
Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable.
[Example 2: constexpr int square(int x) { return x * x; } // OK constexpr long long_max() { return 2147483647; } // OK constexpr int abs(int x) { if (x < 0) x = -x; return x; // OK } constexpr int constant_non_42(int n) { // OK if (n == 42) { static int value = n; return value; } return n; } constexpr int uninit() { struct { int a; } s; return s.a; // error: uninitialized read of s.a } constexpr int prev(int x) { return --x; } // OK constexpr int g(int x, int n) { // OK int r = 1; while (--n > 0) r *= x; return r; } — end example]
An invocation of a constexpr function in a given context produces the same result as an invocation of an equivalent non-constexpr function in the same context in all respects except that
[Note 4: 
Declaring a function constexpr can change whether an expression is a constant expression.
This can indirectly cause calls to std​::​is_constant_evaluated within an invocation of the function to produce a different value.
— end note]
[Note 5: 
It is possible to write a constexpr function for which no invocation satisfies the requirements of a core constant expression.
— end note]
The constexpr and consteval specifiers have no effect on the type of a constexpr function.
[Example 3: constexpr int bar(int x, int y) // OK { return x + y + x*y; } // ... int bar(int x, int y) // error: redefinition of bar { return x * 2 + 3 * y; } — end example]
A constexpr specifier used in an object declaration declares the object as const.
Such an object shall have literal type and shall be initialized.
A constexpr variable shall be constant-initializable ([expr.const]).
A constexpr variable that is an object, as well as any temporary to which a constexpr reference is bound, shall have constant destruction.
[Example 4: struct pixel { int x, y; }; constexpr pixel ur = { 1294, 1024 }; // OK constexpr pixel origin; // error: initializer missing namespace N { void f() { int x; constexpr int& ar = x; // OK static constexpr int& sr = x; // error: x is not constexpr-representable // at the point indicated below } // immediate scope here is that of N } — end example]

9.2.7 The constinit specifier [dcl.constinit]

The constinit specifier shall be applied only to a declaration of a variable with static or thread storage duration or to a structured binding declaration ([dcl.struct.bind]).
[Note 1: 
A structured binding declaration introduces a uniquely named variable, to which the constinit specifier applies.
— end note]
If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration.
No diagnostic is required if no constinit declaration is reachable at the point of the initializing declaration.
If a variable declared with the constinit specifier has dynamic initialization ([basic.start.dynamic]), the program is ill-formed, even if the implementation would perform that initialization as a static initialization ([basic.start.static]).
[Note 2: 
The constinit specifier ensures that the variable is initialized during static initialization.
— end note]
[Example 1: const char * g() { return "dynamic initialization"; } constexpr const char * f(bool p) { return p ? "constant initializer" : g(); } constinit const char * c = f(true); // OK constinit const char * d = f(false); // error — end example]

9.2.8 The inline specifier [dcl.inline]

The inline specifier shall be applied only to the declaration of a variable or function.
A function declaration ([dcl.fct], [class.mfct], [class.friend]) with an inline specifier declares an 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.
An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions specified in this subclause shall still be respected.
[Note 1: 
The inline keyword has no effect on the linkage of a function.
In certain cases, an inline function cannot use names with internal linkage; see [basic.link].
— end note]
A variable declaration with an inline specifier declares an inline variable.
The inline specifier shall not appear on a block scope declaration or on the declaration of a function parameter.
If the inline specifier is used in a friend function declaration, that declaration shall be a definition or the function shall have previously been declared inline.
If a definition of a function or variable is reachable at the point of its first declaration as inline, the program is ill-formed.
If a function or variable with external or module linkage is declared inline in one definition domain, an inline declaration of it shall be reachable from the end of every definition domain in which it is declared; no diagnostic is required.
[Note 2: 
A call to an inline function or a use of an inline variable can be encountered before its definition becomes reachable in a translation unit.
— end note]
[Note 3: 
An inline function or variable with external or module linkage can be defined in multiple translation units ([basic.def.odr]), but is one entity with one address.
A type or static variable defined in the body of such a function is therefore a single entity.
— end note]
If an inline function or variable that is attached to a named module is declared in a definition domain, it shall be defined in that domain.
[Note 4: 
A constexpr function is implicitly inline.
In the global module, a function defined within a class definition is implicitly inline ([class.mfct], [class.friend]).
— end note]

9.2.9 Type specifiers [dcl.type]

9.2.9.1 General [dcl.type.general]

As a general rule, at most one defining-type-specifier is allowed in the complete decl-specifier-seq of a declaration or in a defining-type-specifier-seq, and at most one type-specifier is allowed in a type-specifier-seq.
The only exceptions to this rule are the following:
  • const can be combined with any type specifier except itself.
  • volatile can be combined with any type specifier except itself.
  • signed or unsigned can be combined with char, long, short, or int.
  • short or long can be combined with int.
  • long can be combined with double.
  • long can be combined with long.
Except in a declaration of a constructor, destructor, or conversion function, at least one defining-type-specifier that is not a cv-qualifier shall appear in a complete type-specifier-seq or a complete decl-specifier-seq.74
[Note 1: 
enum-specifiers, class-specifiers, and typename-specifiers are discussed in [dcl.enum], [class], and [temp.res], respectively.
The remaining type-specifiers are discussed in the rest of [dcl.type].
— end note]
74)74)
There is no special provision for a decl-specifier-seq that lacks a type-specifier or that has a type-specifier that only specifies cv-qualifiers.
The “implicit int” rule of C is no longer supported.

9.2.9.2 The cv-qualifiers [dcl.type.cv]

There are two cv-qualifiers, const and volatile.
Each cv-qualifier shall appear at most once in a cv-qualifier-seq.
If a cv-qualifier appears in a decl-specifier-seq, the init-declarator-list or member-declarator-list of the declaration shall not be empty.
[Note 1: 
[basic.type.qualifier] and [dcl.fct] describe how cv-qualifiers affect object and function types.
— end note]
Redundant cv-qualifications are ignored.
[Note 2: 
For example, these could be introduced by typedefs.
— end note]
[Note 3: 
Declaring a variable const can affect its linkage ([dcl.stc]) and its usability in constant expressions ([expr.const]).
As described in [dcl.init], the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization.
— end note]
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path.
[Note 4: 
Cv-qualifiers are supported by the type system so that they cannot be subverted without casting.
— end note]
Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr]) a const object ([basic.type.qualifier]) during its lifetime ([basic.life]) results in undefined behavior.
[Example 1: const int ci = 3; // cv-qualified (initialized as required) ci = 4; // error: attempt to modify const int i = 2; // not cv-qualified const int* cip; // pointer to const int cip = &i; // OK, cv-qualified access path to unqualified *cip = 4; // error: attempt to modify through ptr to const int* ip; ip = const_cast<int*>(cip); // cast needed to convert const int* to int* *ip = 4; // defined: *ip points to i, a non-const object const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined behavior: modifies a const object
For another example, struct X { mutable int i; int j; }; struct Y { X x; Y(); }; const Y y; y.x.i++; // well-formed: mutable member can be modified y.x.j++; // error: const-qualified member modified Y* p = const_cast<Y*>(&y); // cast away const-ness of y p->x.i = 99; // well-formed: mutable member can be modified p->x.j = 99; // undefined behavior: modifies a const subobject
— end example]
The semantics of an access through a volatile glvalue are implementation-defined.
If an attempt is made to access an object defined with a volatile-qualified type through the use of a non-volatile glvalue, the behavior is undefined.
[Note 5: 
volatile is a hint to the implementation to avoid aggressive optimization involving the object because it is possible for the value of the object to change by means undetectable by an implementation.
Furthermore, for some implementations, volatile can indicate that special hardware instructions are needed to access the object.
See [intro.execution] for detailed semantics.
In general, the semantics of volatile are intended to be the same in C++ as they are in C.
— end note]

9.2.9.3 Simple type specifiers [dcl.type.simple]

The component name of a type-name is the first name in it.
A placeholder-type-specifier is a placeholder for a type to be deduced ([dcl.spec.auto]).
A type-specifier of the form typename nested-name-specifier template-name is a placeholder for a deduced class type ([dcl.type.class.deduct]).
The nested-name-specifier, if any, shall be non-dependent and the template-name shall name a deducible template.
A deducible template is either a class template or is an alias template whose defining-type-id is of the form
typename nested-name-specifier template simple-template-id
where the nested-name-specifier (if any) is non-dependent and the template-name of the simple-template-id names a deducible template.
[Note 1: 
An injected-class-name is never interpreted as a template-name in contexts where class template argument deduction would be performed ([temp.local]).
— end note]
The other simple-type-specifiers specify either a previously-declared type, a type determined from an expression, or one of the fundamental types ([basic.fundamental]).
Table 17 summarizes the valid combinations of simple-type-specifiers and the types they specify.
Table 17simple-type-specifiers and the types they specify [tab:dcl.type.simple]
Specifier(s)
Type
the type named
the type as defined in [temp.names]
the type as defined in [dcl.type.decltype]
the type as defined in [dcl.type.pack.index]
the type as defined in [dcl.spec.auto]
the type as defined in [dcl.type.class.deduct]
char
char
unsigned char
unsigned char
signed char
signed char
char8_t
char8_t
char16_t
char16_t
char32_t
char32_t
bool
bool
unsigned
unsigned int
unsigned int
unsigned int
signed
int
signed int
int
int
int
unsigned short int
unsigned short int
unsigned short
unsigned short int
unsigned long int
unsigned long int
unsigned long
unsigned long int
unsigned long long int
unsigned long long int
unsigned long long
unsigned long long int
signed long int
long int
signed long
long int
signed long long int
long long int
signed long long
long long int
long long int
long long int
long long
long long int
long int
long int
long
long int
signed short int
short int
signed short
short int
short int
short int
short
short int
wchar_t
wchar_t
float
float
double
double
long double
long double
void
void
When multiple simple-type-specifiers are allowed, they can be freely intermixed with other decl-specifiers in any order.
[Note 2: 
It is implementation-defined whether objects of char type are represented as signed or unsigned quantities.
The signed specifier forces char objects to be signed; it is redundant in other contexts.
— end note]

9.2.9.4 Pack indexing specifier [dcl.type.pack.index]

The typedef-name P in a pack-index-specifier shall denote a pack.
The constant-expression shall be a converted constant expression ([expr.const]) of type std​::​size_t whose value V, termed the index, is such that .
[Note 1: 
The pack-index-specifier denotes the type of the element of the pack.
— end note]

9.2.9.5 Elaborated type specifiers [dcl.type.elab]

The component names of an elaborated-type-specifier are its identifier (if any) and those of its nested-name-specifier and simple-template-id (if any).
If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization ([temp.expl.spec]), a partial specialization ([temp.spec.partial]), an explicit instantiation ([temp.explicit]), or it has one of the following forms:
In the first case, the elaborated-type-specifier declares the identifier as a class-name.
The second case shall appear only in an explicit-specialization ([temp.expl.spec]) or in a template-declaration (where it declares a partial specialization).
The attribute-specifier-seq, if any, appertains to the class or template being declared.
Otherwise, an elaborated-type-specifier E shall not have an attribute-specifier-seq.
If E contains an identifier but no nested-name-specifier and (unqualified) lookup for the identifier finds nothing, E shall not be introduced by the enum keyword and declares the identifier as a class-name.
The target scope of E is the nearest enclosing namespace or block scope.
A friend-type-specifier that is an elaborated-type-specifier shall have one of the following forms: Any unqualified lookup for the identifier (in the first case) does not consider scopes that contain the nearest enclosing namespace or block scope; no name is bound.
[Note 1: 
A using-directive in the target scope is ignored if it refers to a namespace not contained by that scope.
— end note]
[Note 2: 
[basic.lookup.elab] describes how name lookup proceeds in an elaborated-type-specifier.
An elaborated-type-specifier can be used to refer to a previously declared class-name or enum-name even if the name has been hidden by a non-type declaration.
— end note]
If the identifier or simple-template-id in an elaborated-type-specifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name ([dcl.type.simple]).
[Note 3: 
This implies that, within a class template with a template type-parameter T, the declaration friend class T; is ill-formed.
However, the similar declaration friend T; is well-formed ([class.friend]).
— end note]
The class-key or enum keyword present in an elaborated-type-specifier shall agree in kind with the declaration to which the name in the elaborated-type-specifier refers.
This rule also applies to the form of elaborated-type-specifier that declares a class-name or friend class since it can be construed as referring to the definition of the class.
Thus, in any elaborated-type-specifier, the enum keyword shall be used to refer to an enumeration ([dcl.enum]), the union class-key shall be used to refer to a union ([class.union]), and either the class or struct class-key shall be used to refer to a non-union class ([class.pre]).
[Example 1: enum class E { a, b }; enum E x = E::a; // OK struct S { } s; class S* p = &s; // OK — end example]

9.2.9.6 Decltype specifiers [dcl.type.decltype]

For an expression E, the type denoted by decltype(E) is defined as follows:
The operand of the decltype specifier is an unevaluated operand.
[Example 1: const int&& foo(); int i; struct A { double x; }; const A* a = new A(); decltype(foo()) x1 = 17; // type is const int&& decltype(i) x2; // type is int decltype(a->x) x3; // type is double decltype((a->x)) x4 = x3; // type is const double& void f() { [](auto ...pack) { decltype(pack...[0]) x5; // type is int decltype((pack...[0])) x6; // type is int& }(0); } — end example]
[Note 1: 
The rules for determining types involving decltype(auto) are specified in [dcl.spec.auto].
— end note]
If the operand of a decltype-specifier is a prvalue and is not a (possibly parenthesized) immediate invocation ([expr.const]), the temporary materialization conversion is not applied ([conv.rval]) and no result object is provided for the prvalue.
The type of the prvalue may be incomplete or an abstract class type.
[Note 2: 
As a result, storage is not allocated for the prvalue and it is not destroyed.
Thus, a class type is not instantiated as a result of being the type of a function call in this context.
In this context, the common purpose of writing the expression is merely to refer to its type.
In that sense, a decltype-specifier is analogous to a use of a typedef-name, so the usual reasons for requiring a complete type do not apply.
In particular, it is not necessary to allocate storage for a temporary object or to enforce the semantic constraints associated with invoking the type's destructor.
— end note]
[Note 3: 
Unlike the preceding rule, parentheses have no special meaning in this context.
— end note]
[Example 2: template<class T> struct A { ~A() = delete; }; template<class T> auto h() -> A<T>; template<class T> auto i(T) // identity -> T; template<class T> auto f(T) // #1 -> decltype(i(h<T>())); // forces completion of A<T> and implicitly uses A<T>​::​~A() // for the temporary introduced by the use of h(). // (A temporary is not introduced as a result of the use of i().) template<class T> auto f(T) // #2 -> void; auto g() -> void { f(42); // OK, calls #2. (#1 is not a viable candidate: type deduction // fails ([temp.deduct]) because A<int>​::​~A() is implicitly used in its // decltype-specifier) } template<class T> auto q(T) -> decltype((h<T>())); // does not force completion of A<T>; A<T>​::​~A() is not implicitly // used within the context of this decltype-specifier void r() { q(42); // error: deduction against q succeeds, so overload resolution selects // the specialization “q(T) -> decltype((h<T>()))'' with Tint; // the return type is A<int>, so a temporary is introduced and its // destructor is used, so the program is ill-formed } — end example]

9.2.9.7 Placeholder type specifiers [dcl.spec.auto]

9.2.9.7.1 General [dcl.spec.auto.general]

A placeholder-type-specifier designates a placeholder type that will be replaced later, typically by deduction from an initializer.
The placeholder type shall appear as one of the decl-specifiers in the decl-specifier-seq or as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a decl-specifier (see below); the placeholder type is a generic parameter type placeholder of the function declaration, lambda-expression, or template-parameter, respectively.
[Note 1: 
Having a generic parameter type placeholder signifies that the function is an abbreviated function template ([dcl.fct]) or the lambda is a generic lambda ([expr.prim.lambda]).
— end note]
A placeholder type can appear in the decl-specifier-seq for a function declarator that includes a trailing-return-type ([dcl.fct]).
A placeholder type can appear in the decl-specifier-seq or type-specifier-seq in the declared return type of a function declarator that declares a function; the return type of the function is deduced from non-discarded return statements, if any, in the body of the function ([stmt.if]).
The type of a variable declared using a placeholder type is deduced from its initializer.
This use is allowed in an initializing declaration ([dcl.init]) of a variable.
The placeholder type shall appear as one of the decl-specifiers in the decl-specifier-seq or as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a decl-specifier; the decl-specifier-seq shall be followed by one or more declarators, each of which shall be followed by a non-empty initializer.
[Example 1: auto x = 5; // OK, x has type int const auto *v = &x, u = 6; // OK, v has type const int*, u has type const int static auto y = 0.0; // OK, y has type double auto int r; // error: auto is not a storage-class-specifier auto f() -> int; // OK, f returns int auto g() { return 0.0; } // OK, g returns double auto (*fp)() -> auto = f; // OK auto h(); // OK, h's return type will be deduced when it is defined — end example]
The auto type-specifier can also be used to introduce a structured binding declaration ([dcl.struct.bind]).
A placeholder type can also be used in the type-specifier-seq of the new-type-id or in the type-id of a new-expression ([expr.new]).
In such a type-id, the placeholder type shall appear as one of the type-specifiers in the type-specifier-seq or as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a type-specifier.
The auto type-specifier can also be used as the simple-type-specifier in an explicit type conversion (functional notation) ([expr.type.conv]).
A program that uses a placeholder type in a context not explicitly allowed in [dcl.spec.auto] is ill-formed.
If the init-declarator-list contains more than one init-declarator, they shall all form declarations of variables.
The type of each declared variable is determined by placeholder type deduction, and if the type that replaces the placeholder type is not the same in each deduction, the program is ill-formed.
[Example 2: auto x = 5, *y = &x; // OK, auto is int auto a = 5, b = { 1, 2 }; // error: different types for auto — end example]
If a function with a declared return type that contains a placeholder type has multiple non-discarded return statements, the return type is deduced for each such return statement.
If the type deduced is not the same in each deduction, the program is ill-formed.
If a function with a declared return type that uses a placeholder type has no non-discarded return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body.
[Example 3: auto f() { } // OK, return type is void auto* g() { } // error: cannot deduce auto* from void() — end example]
An exported function with a declared return type that uses a placeholder type shall be defined in the translation unit containing its exported declaration, outside the private-module-fragment (if any).
[Note 2: 
The deduced return type cannot have a name with internal linkage ([basic.link]).
— end note]
If a variable or function with an undeduced placeholder type is named by an expression ([basic.def.odr]), the program is ill-formed.
Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.
[Example 4: auto n = n; // error: n's initializer refers to n auto f(); void g() { &f; } // error: f's return type is unknown auto sum(int i) { if (i == 1) return i; // sum's return type is int else return sum(i-1)+i; // OK, sum's return type has been deduced } — end example]
Return type deduction for a templated function with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand.
[Note 3: 
Therefore, any use of a specialization of the function template will cause an implicit instantiation.
Any errors that arise from this instantiation are not in the immediate context of the function type and can result in the program being ill-formed ([temp.deduct]).
— end note]
[Example 5: template <class T> auto f(T t) { return t; } // return type deduced at instantiation time typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type template<class T> auto f(T* t) { return *t; } void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types, // chooses second — end example]
If a function or function template F has a declared return type that uses a placeholder type, redeclarations or specializations of F shall use that placeholder type, not a deduced type; otherwise, they shall not use a placeholder type.
[Example 6: auto f(); auto f() { return 42; } // return type is int auto f(); // OK int f(); // error: auto and int don't match decltype(auto) f(); // error: auto and decltype(auto) don't match template <typename T> auto g(T t) { return t; } // #1 template auto g(int); // OK, return type is int template char g(char); // error: no matching template template<> auto g(double); // OK, forward declaration with unknown return type template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1 template char g(char); // OK, now there is a matching template template auto g(float); // still matches #1 void h() { return g(42); } // error: ambiguous template <typename T> struct A { friend T frf(T); }; auto frf(int i) { return i; } // not a friend of A<int> extern int v; auto v = 17; // OK, redeclares v struct S { static int i; }; auto S::i = 23; // OK — end example]
A function declared with a return type that uses a placeholder type shall not be virtual ([class.virtual]).
A function declared with a return type that uses a placeholder type shall not be a coroutine ([dcl.fct.def.coroutine]).
An explicit instantiation declaration does not cause the instantiation of an entity declared using a placeholder type, but it also does not prevent that entity from being instantiated as needed to determine its type.
[Example 7: template <typename T> auto f(T t) { return t; } extern template auto f(int); // does not instantiate f<int> int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit // instantiation definition is still required somewhere in the program — end example]

9.2.9.7.2 Placeholder type deduction [dcl.type.auto.deduct]

Placeholder type deduction is the process by which a type containing a placeholder type is replaced by a deduced type.
A type T containing a placeholder type, and a corresponding initializer-clause E, are determined as follows:
T shall not be an array type.
If the placeholder-type-specifier is of the form type-constraint auto, the deduced type replacing T is determined using the rules for template argument deduction.
If the initialization is copy-list-initialization, a declaration of std​::​initializer_list shall precede ([basic.lookup.general]) the placeholder-type-specifier.
Obtain P from T by replacing the occurrences of type-constraint auto either with a new invented type template parameter U or, if the initialization is copy-list-initialization, with std​::​initializer_list<U>.
Deduce a value for U using the rules of template argument deduction from a function call, where P is a function template parameter type and the corresponding argument is E.
If the deduction fails, the declaration is ill-formed.
Otherwise, is obtained by substituting the deduced U into P.
[Example 1: auto x1 = { 1, 2 }; // decltype(x1) is std​::​initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std​::​initializer_list<int> auto x5{ 3 }; // decltype(x5) is int — end example]
[Example 2: const auto &i = expr;
The type of i is the deduced type of the parameter u in the call f(expr) of the following invented function template: template <class U> void f(const U& u);
— end example]
If the placeholder-type-specifier is of the form type-constraint decltype(auto), T shall be the placeholder alone.
The type deduced for T is determined as described in [dcl.type.decltype], as though E had been the operand of the decltype.
[Example 3: int i; int&& f(); auto x2a(i); // decltype(x2a) is int decltype(auto) x2d(i); // decltype(x2d) is int auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std​::​initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto) auto f1(int x) -> decltype((x)) { return (x); } // return type is int& auto f2(int x) -> decltype(auto) { return (x); } // return type is int&& — end example]
For a placeholder-type-specifier with a type-constraint, the immediately-declared constraint ([temp.param]) of the type-constraint for the type deduced for the placeholder shall be satisfied.

9.2.9.8 Deduced class template specialization types [dcl.type.class.deduct]

If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of an initializing declaration ([dcl.init]) of a variable, the declared type of the variable shall be cv T, where T is the placeholder.
[Example 1: template <class ...T> struct A { A(T...) {} }; A x[29]{}; // error: no declarator operators allowed const A& y{}; // error: no declarator operators allowed — end example]
The placeholder is replaced by the return type of the function selected by overload resolution for class template deduction ([over.match.class.deduct]).
If the decl-specifier-seq is followed by an init-declarator-list or member-declarator-list containing more than one declarator, the type that replaces the placeholder shall be the same in each deduction.
A placeholder for a deduced class type can also be used in the type-specifier-seq in the new-type-id or type-id of a new-expression ([expr.new]), as the simple-type-specifier in an explicit type conversion (functional notation), or as the type-specifier in the parameter-declaration of a template-parameter ([temp.param]).
A placeholder for a deduced class type shall not appear in any other context.
[Example 2: template<class T> struct container { container(T t) {} template<class Iter> container(Iter beg, Iter end); }; template<class Iter> container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>; std::vector<double> v = { /* ... */ }; container c(7); // OK, deduces int for T auto d = container(v.begin(), v.end()); // OK, deduces double for T container e{5, 6}; // error: int is not an iterator — end example]

9.3 Declarators [dcl.decl]

9.3.1 General [dcl.decl.general]

A declarator declares a single variable, function, or type, within a declaration.
The init-declarator-list appearing in a simple-declaration is a comma-separated sequence of declarators, each of which can have an initializer.
In all contexts, a declarator is interpreted as given below.
Where an abstract-declarator can be used (or omitted) in place of a declarator ([dcl.fct], [except.pre]), it is as if a unique identifier were included in the appropriate place ([dcl.name]).
The preceding specifiers indicate the type, storage duration, linkage, or other properties of the entity or entities being declared.
Each declarator specifies one entity and (optionally) names it and/or modifies the type of the specifiers with operators such as * (pointer to) and () (function returning).
[Note 1: 
An init-declarator can also specify an initializer ([dcl.init]).
— end note]
Each init-declarator or member-declarator in a declaration is analyzed separately as if it were in a declaration by itself.
[Note 2: 
A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator.
That is, T D1, D2, ... Dn; is usually equivalent to T D1; T D2; ... T Dn; where T is a decl-specifier-seq and each Di is an init-declarator or member-declarator.
One exception is when a name introduced by one of the declarators hides a type name used by the decl-specifiers, so that when the same decl-specifiers are used in a subsequent declaration, they do not have the same meaning, as in struct S { /* ... */ }; S S, T; // declare two instances of struct S which is not equivalent to struct S { /* ... */ }; S S; S T; // error
Another exception is when T is auto ([dcl.spec.auto]), for example: auto i = 1, j = 2.0; // error: deduced types for i and j do not match as opposed to auto i = 1; // OK, i deduced to have type int auto j = 2.0; // OK, j deduced to have type double
— end note]
The optional requires-clause in an init-declarator or member-declarator shall be present only if the declarator declares a templated function ([temp.pre]).
When present after a declarator, the requires-clause is called the trailing requires-clause.
The trailing requires-clause introduces the constraint-expression that results from interpreting its constraint-logical-or-expression as a constraint-expression.
[Example 1: void f1(int a) requires true; // error: non-templated function template<typename T> auto f2(T a) -> bool requires true; // OK template<typename T> auto f3(T a) requires true -> bool; // error: requires-clause precedes trailing-return-type void (*pf)() requires true; // error: constraint on a variable void g(int (*)() requires true); // error: constraint on a parameter-declaration auto* p = new void(*)(char) requires true; // error: not a function declaration — end example]

9.3.2 Type names [dcl.name]

To specify type conversions explicitly, and as an argument of sizeof, alignof, new, or typeid, the name of a type shall be specified.
This can be done with a type-id or new-type-id ([expr.new]), which is syntactically a declaration for a variable or function of that type that omits the name of the entity.
It is possible to identify uniquely the location in the abstract-declarator where the identifier would appear if the construction were a declarator in a declaration.
The named type is then the same as the type of the hypothetical identifier.
[Example 1: 
int // int i int * // int *pi int *[3] // int *p[3] int (*)[3] // int (*p3i)[3] int *() // int *f() int (*)(double) // int (*pf)(double) name respectively the types “int”, “pointer to int”, “array of 3 pointers to int”, “pointer to array of 3 int”, “function of (no parameters) returning pointer to int”, and “pointer to a function of (double) returning int.
— end example]
[Note 1: 
A type can also be named by a typedef-name, which is introduced by a typedef declaration or alias-declaration ([dcl.typedef]).
— end note]

9.3.3 Ambiguity resolution [dcl.ambig.res]

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration.
In that context, the choice is between an object declaration with a function-style cast as the initializer and a declaration involving a function declarator with a redundant set of parentheses around a parameter name.
Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct, such as the potential parameter declaration, that could possibly be a declaration to be a declaration.
However, a construct that can syntactically be a declaration whose outermost declarator would match the grammar of a declarator with a trailing-return-type is a declaration only if it starts with auto.
[Note 1: 
A declaration can be explicitly disambiguated by adding parentheses around the argument.
The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast.
— end note]
[Example 1: struct S { S(int); }; typedef struct BB { int C[2]; } *B, C; void foo(double a) { S v(int(a)); // function declaration S w(int()); // function declaration S x((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration S a(B()->C); // object declaration S b(auto()->C); // function declaration } — end example]
An ambiguity can arise from the similarity between a function-style cast and a type-id.
The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.
However, a construct that can syntactically be a type-id whose outermost abstract-declarator would match the grammar of an abstract-declarator with a trailing-return-type is considered a type-id only if it starts with auto.
[Example 2: template <class T> struct X {}; template <int N> struct Y {}; X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expression void foo(signed char a) { sizeof(int()); // type-id (ill-formed) sizeof(int(a)); // expression sizeof(int(unsigned(a))); // type-id (ill-formed) (int())+1; // type-id (ill-formed) (int(a))+1; // expression (int(unsigned(a)))+1; // type-id (ill-formed) } typedef struct BB { int C[2]; } *B, C; void g() { sizeof(B()->C[1]); // OK, sizeof(expression) sizeof(auto()->C[1]); // error: sizeof of a function returning an array } — end example]
Another ambiguity arises in a parameter-declaration-clause when a type-name is nested in parentheses.
In this case, the choice is between the declaration of a parameter of type pointer to function and the declaration of a parameter with redundant parentheses around the declarator-id.
The resolution is to consider the type-name as a simple-type-specifier rather than a declarator-id.
[Example 3: class C { }; void f(int(C)) { } // void f(int(*fp)(C c)) { } // not: void f(int C) { } int g(C); void foo() { f(1); // error: cannot convert 1 to function pointer f(g); // OK }
For another example, class C { }; void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10])); // not: void h(int *C[10]);
— end example]

9.3.4 Meaning of declarators [dcl.meaning]

9.3.4.1 General [dcl.meaning.general]

A declarator contains exactly one declarator-id; it names the entity that is declared.
[Note 1: 
An unqualified-id that is not an identifier is used to declare certain functions ([class.conv.fct], [class.dtor], [over.oper], [over.literal]).
— end note]
The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared.
If the declaration is a friend declaration:
  • The declarator does not bind a name.
  • If the id-expression E in the declarator-id of the declarator is a qualified-id or a template-id:
    • If the friend declaration is not a template declaration, then in the lookup for the terminal name of E:
    • The declarator shall correspond to one or more declarations found by the lookup; they shall all have the same target scope, and the target scope of the declarator is that scope.
  • 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 reachable ([module.reach]) declaration that inhabits the innermost block scope.
Otherwise:
  • If the id-expression in the declarator-id of the declarator is a qualified-id Q, let S be its lookup context ([basic.lookup.qual]); the declaration shall inhabit a namespace scope.
  • Otherwise, let S be the entity associated with the scope inhabited by the declarator.
  • If the declarator declares an explicit instantiation or a partial or explicit specialization, the declarator does not bind a name.
    If it declares a class member, the terminal name of the declarator-id is not looked up; otherwise, only those lookup results that are nominable in S are considered when identifying any function template specialization being declared ([temp.deduct.decl]).
    [Example 1: namespace N { inline namespace O { template<class T> void f(T); // #1 template<class T> void g(T) {} } namespace P { template<class T> void f(T*); // #2, more specialized than #1 template<class> int g; } using P::f,P::g; } template<> void N::f(int*) {} // OK, #2 is not nominable template void N::g(int); // error: lookup is ambiguous — end example]
  • Otherwise, the terminal name of the declarator-id is not looked up.
    If it is a qualified name, the declarator shall correspond to one or more declarations nominable in S; all the declarations shall have the same target scope and the target scope of the declarator is that scope.
    [Example 2: namespace Q { namespace V { void f(); } void V::f() { /* ... */ } // OK void V::g() { /* ... */ } // error: g() is not yet a member of V namespace V { void g(); } } namespace R { void Q::V::g() { /* ... */ } // error: R doesn't enclose Q } — end example]
  • If the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S.
    [Example 3: namespace X { void p() { q(); // error: q not yet declared extern void q(); // q is a member of namespace X extern void r(); // r is a member of namespace X } void middle() { q(); // error: q not found } void q() { /* ... */ } // definition of X​::​q } void q() { /* ... */ } // some other, unrelated q void X::r() { /* ... */ } // error: r cannot be declared by qualified-id — end example]
A static, thread_local, extern, mutable, friend, inline, virtual, constexpr, consteval, constinit, or typedef specifier or an explicit-specifier applies directly to each declarator-id in a declaration; the type specified for each declarator-id depends on both the decl-specifier-seq and its declarator.
Thus, (for each declarator) a declaration has the form T D where T is of the form attribute-specifier-seq decl-specifier-seq and D is a declarator.
Following is a recursive procedure for determining the type specified for the contained declarator-id by such a declaration.
First, the decl-specifier-seq determines a type.
In a declaration T D the decl-specifier-seq T determines the type T.
[Example 4: 
In the declaration int unsigned i; the type specifiers int unsigned determine the type “unsigned int” ([dcl.type.simple]).
— end example]
In a declaration attribute-specifier-seq T D where D is an unadorned declarator-id, the type of the declared entity is “T.
In a declaration T D where D has the form
( D1 )
the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration T D1
Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.

9.3.4.2 Pointers [dcl.ptr]

In a declaration T D where D has the form and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list cv-qualifier-seq pointer to T.
The cv-qualifiers apply to the pointer and not to the object pointed to.
Similarly, the optional attribute-specifier-seq ([dcl.attr.grammar]) appertains to the pointer and not to the object pointed to.
[Example 1: 
The declarations const int ci = 10, *pc = &ci, *const cpc = pc, **ppc; int i, *p, *const cp = &i; declare ci, a constant integer; pc, a pointer to a constant integer; cpc, a constant pointer to a constant integer; ppc, a pointer to a pointer to a constant integer; i, an integer; p, a pointer to integer; and cp, a constant pointer to integer.
The value of ci, cpc, and cp cannot be changed after initialization.
The value of pc can be changed, and so can the object pointed to by cp.
Examples of some correct operations are i = ci; *cp = ci; pc++; pc = cpc; pc = p; ppc = &pc;
Examples of ill-formed operations are ci = 1; // error ci++; // error *pc = 2; // error cp = &ci; // error cpc++; // error p = pc; // error ppc = &p; // error
Each is unacceptable because it would either change the value of an object declared const or allow it to be changed through a cv-unqualified pointer later, for example: *ppc = &ci; // OK, but would make p point to ci because of previous error *p = 5; // clobber ci
— end example]
[Note 1: 
Forming a pointer to reference type is ill-formed; see [dcl.ref].
Forming a function pointer type is ill-formed if the function type has cv-qualifiers or a ref-qualifier; see [dcl.fct].
Since the address of a bit-field ([class.bit]) cannot be taken, a pointer can never point to a bit-field.
— end note]

9.3.4.3 References [dcl.ref]

In a declaration T D where D has either of the forms and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list reference to T.
The optional 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 typedef-name ([dcl.typedef], [temp.param]) or decltype-specifier ([dcl.type.decltype]), in which case the cv-qualifiers are ignored.
[Example 1: typedef int& A; const A aref = 3; // error: lvalue reference to non-const initialized with rvalue
The type of aref is “lvalue reference to int”, not “lvalue reference to const int.
— end example]
[Note 1: 
A reference can be thought of as a name of an object.
— end note]
Forming the type “reference to cv void” is ill-formed.
A reference type that is declared using & is called an lvalue reference, and a reference type that is declared using && is called an rvalue reference.
Lvalue references and rvalue references are distinct types.
Except where explicitly noted, they are semantically equivalent and commonly referred to as references.
[Example 2: 
void f(double& a) { a += 3.14; } // ... double d = 0; f(d); declares a to be a reference parameter of f so the call f(d) will add 3.14 to d.
int v[20]; // ... int& g(int i) { return v[i]; } // ... g(3) = 7; declares the function g() to return a reference to an integer so g(3)=7 will assign 7 to the fourth element of the array v.
For another example, struct link { link* next; }; link* first; void h(link*& p) { // p is a reference to pointer p->next = first; first = p; p = 0; } void k() { link* q = new link; h(q); } declares p to be a reference to a pointer to link so h(q) will leave q with the value zero.
— end example]
It is unspecified whether or not a reference requires storage ([basic.stc]).
There shall be no references to references, no arrays of references, and no pointers to references.
The declaration of a reference shall contain an initializer ([dcl.init.ref]) except when the declaration contains an explicit extern specifier ([dcl.stc]), is a class member ([class.mem]) declaration within a class definition, or is the declaration of a parameter or a return type ([dcl.fct]); see [basic.def].
Attempting to bind a reference to a function where the converted initializer is a glvalue whose type is not call-compatible ([expr.call]) with the type of the function's definition results in undefined behavior.
Attempting to bind a reference to an object where the converted initializer is a glvalue through which the object is not type-accessible ([basic.lval]) results in undefined behavior.
[Note 2: 
The object designated by such a glvalue can be outside its lifetime ([basic.life]).
Because a null pointer value or a pointer past the end of an object does not point to an object, a reference in a well-defined program cannot refer to such things; see [expr.unary.op].
As described in [class.bit], a reference cannot be bound directly to a bit-field.
— end note]
The behavior of an evaluation of a reference ([expr.prim.id], [expr.ref]) that does not happen after ([intro.races]) the initialization of the reference is undefined.
[Example 3: int &f(int&); int &g(); extern int &ir3; int *ip = 0; int &ir1 = *ip; // undefined behavior: null pointer int &ir2 = f(ir3); // undefined behavior: ir3 not yet initialized int &ir3 = g(); int &ir4 = f(ir4); // undefined behavior: ir4 used in its own initializer char x alignas(int); int &ir5 = *reinterpret_cast<int *>(&x); // undefined behavior: initializer refers to char object — end example]
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.
[Note 3: 
This rule is known as reference collapsing.
— end note]
[Example 4: int i; typedef int& LRI; typedef int&& RRI; LRI& r1 = i; // r1 has the type int& const LRI& r2 = i; // r2 has the type int& const LRI&& r3 = i; // r3 has the type int& RRI& r4 = i; // r4 has the type int& RRI&& r5 = 5; // r5 has the type int&& decltype(r2)& r6 = i; // r6 has the type int& decltype(r2)&& r7 = i; // r7 has the type int& — end example]
[Note 4: 
Forming a reference to function type is ill-formed if the function type has cv-qualifiers or a ref-qualifier; see [dcl.fct].
— end note]

9.3.4.4 Pointers to members [dcl.mptr]

The component names of a ptr-operator are those of its nested-name-specifier, if any.
In a declaration T D where D has the form and the nested-name-specifier denotes a class, and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list cv-qualifier-seq pointer to member of class nested-name-specifier of type T.
The optional attribute-specifier-seq ([dcl.attr.grammar]) appertains to the pointer-to-member.
[Example 1: 
struct X { void f(int); int a; }; struct Y; int X::* pmi = &X::a; void (X::* pmf)(int) = &X::f; double X::* pmd; char Y::* pmc; declares pmi, pmf, pmd and pmc to be a pointer to a member of X of type int, a pointer to a member of X of type void(int), a pointer to a member of X of type double and a pointer to a member of Y of type char respectively.
The declaration of pmd is well-formed even though X has no members of type double.
Similarly, the declaration of pmc is well-formed even though Y is an incomplete type.
pmi and pmf can be used like this: X obj; // ... obj.*pmi = 7; // assign 7 to an integer member of obj (obj.*pmf)(7); // call a function member of obj with the argument 7
— end example]
A pointer to member shall not point to a static member of a class ([class.static]), a member with reference type, or “cv void.
[Note 1: 
The type “pointer to member” is distinct from the type “pointer”, that is, a pointer to member is declared only by the pointer-to-member declarator syntax, and never by the pointer declarator syntax.
There is no “reference-to-member” type in C++.
— end note]

9.3.4.5 Arrays [dcl.array]

In a declaration T D where D has the form and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list array of N T.
The constant-expression shall be a converted constant expression of type std​::​size_t ([expr.const]).
Its value N specifies the array bound, i.e., the number of elements in the array; N shall be greater than zero.
In a declaration T D where D has the form and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”, the type of the declarator-id in D is “derived-declarator-type-list array of unknown bound of T”, except as specified below.
A type of the form “array of N U” or “array of unknown bound of U” is an array type.
The optional attribute-specifier-seq appertains to the array type.
U is called the array element type; this type shall not be a reference type, a function type, an array of unknown bound, or cv void.
[Note 1: 
An array can be constructed from one of the fundamental types (except void), from a pointer, from a pointer to member, from a class, from an enumeration type, or from an array of known bound.
— end note]
[Example 1: 
float fa[17], *afp[17]; declares an array of float numbers and an array of pointers to float numbers.
— end example]
Any type of the form “cv-qualifier-seq array of N U” is adjusted to “array of N cv-qualifier-seq U”, and similarly for “array of unknown bound of U.
[Example 2: typedef int A[5], AA[2][3]; typedef const A CA; // type is “array of 5 const int'' typedef const AA CAA; // type is “array of 2 array of 3 const int'' — end example]
[Note 2: 
An “array of N cv-qualifier-seq U” has cv-qualified type; see [basic.type.qualifier].
— end note]
An object of type “array of N U” consists of a contiguously allocated non-empty set of N subobjects of type U, known as the elements of the array, and numbered 0 to N-1.
In addition to declarations in which an incomplete object type is allowed, an array bound may be omitted in some cases in the declaration of a function parameter ([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 ([dcl.init], [class.mem], [expr.type.conv], [expr.new]).
In these cases, the array bound is calculated from the number of initial elements (say, N) supplied ([dcl.init.aggr]), and the type of the array is “array of N U.
Furthermore, if there is a reachable declaration of the entity that inhabits the same scope in which the bound was specified, an omitted array bound is taken to be the same as in that earlier declaration, and similarly for the definition of a static data member of a class.
[Example 3: extern int x[10]; struct S { static int y[10]; }; int x[]; // OK, bound is 10 int S::y[]; // OK, bound is 10 void f() { extern int x[]; int i = sizeof(x); // error: incomplete object type } — end example]
[Note 3: 
When several “array of” specifications are adjacent, a multidimensional array type is created; only the first of the constant expressions that specify the bounds of the arrays can be omitted.
[Example 4: 
int x3d[3][5][7]; declares an array of three elements, each of which is an array of five elements, each of which is an array of seven integers.
The overall array can be viewed as a three-dimensional array of integers, with rank 3 ×5 ×7.
Any of the expressions x3d, x3d[i], x3d[i][j], x3d[i][j][k] can reasonably appear in an expression.
The expression x3d[i] is equivalent to *(x3d + i); in that expression, x3d is subject to the array-to-pointer conversion ([conv.array]) and is first converted to a pointer to a 2-dimensional array with rank 5 ×7 that points to the first element of x3d.
Then i is added, which on typical implementations involves multiplying i by the length of the object to which the pointer points, which is sizeof(int)×5 ×7.
The result of the addition and indirection is an lvalue denoting the array element of x3d (an array of five arrays of seven integers).
If there is another subscript, the same argument applies again, so x3d[i][j] is an lvalue denoting the array element of the array element of x3d (an array of seven integers), and x3d[i][j][k] is an lvalue denoting the array element of the array element of the array element of x3d (an integer).
— end example]
The first subscript in the declaration helps determine the amount of storage consumed by an array but plays no other part in subscript calculations.
— end note]
[Note 4: 
Conversions affecting expressions of array type are described in [conv.array].
— end note]
[Note 5: 
The subscript operator can be overloaded for a class ([over.sub]).
For the operator's built-in meaning, see [expr.sub].
— end note]

9.3.4.6 Functions [dcl.fct]

In a declaration T D where T may be empty and D has the form a derived-declarator-type-list is determined as follows:
The declared return type U of the function type is determined as follows:
The type of the declarator-id in D is “derived-declarator-type-list noexcept function of parameter-type-list cv-qualifier-seq ref-qualifier returning U”, where
Such a type is a function type.75
The optional attribute-specifier-seq appertains to the function type.
The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called.
[Note 1: 
The parameter-declaration-clause is used to convert the arguments specified on the function call; see [expr.call].
— end note]
If the parameter-declaration-clause is empty, the function takes no arguments.
A parameter list consisting of a single unnamed non-object parameter of non-dependent type void is equivalent to an empty parameter list.
Except for this special case, a parameter shall not have type cv void.
A parameter with volatile-qualified type is deprecated; see [depr.volatile.type].
If the parameter-declaration-clause terminates with an ellipsis or a function parameter pack ([temp.variadic]), the number of arguments shall be equal to or greater than the number of parameters that do not have a default argument and are not function parameter packs.
Where syntactically correct and where “...” is not part of an abstract-declarator, “...” is synonymous with “, ....
[Example 1: 
The declaration int printf(const char*, ...); declares a function that can be called with varying numbers and types of arguments.
printf("hello world"); printf("a=%d b=%d", a, b);
However, the first argument must be of a type that can be converted to a const char*.
— end example]
[Note 2: 
The standard header <cstdarg> contains a mechanism for accessing arguments passed using the ellipsis (see [expr.call] and [support.runtime]).
— end note]
The type of a function is determined using the following rules.
The type of each parameter (including function parameter packs) is determined from its own parameter-declaration ([dcl.decl]).
After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T.
After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.
The resulting list of transformed parameter types and the presence or absence of the ellipsis or a function parameter pack is the function's parameter-type-list.
[Note 3: 
This transformation does not affect the types of the parameters.
For example, int(*)(const int p, decltype(p)*) and int(*)(int, const int*) are identical types.
— end note]
[Example 2: void f(char*); // #1 void f(char[]) {} // defines #1 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 h(int x(const int)); // #3 void h(int (*)(int)) {} // defines #3 — end example]
An explicit-object-parameter-declaration shall appear only as the first parameter-declaration of a parameter-declaration-list of one of:
A member-declarator with an explicit-object-parameter-declaration shall not include a ref-qualifier or a cv-qualifier-seq and shall not be declared static or virtual.
[Example 3: struct C { void f(this C& self); template <typename Self> void g(this Self&& self, int); void h(this C) const; // error: const not allowed here }; void test(C c) { c.f(); // OK, calls C​::​f c.g(42); // OK, calls C​::​g<C&> std::move(c).g(42); // OK, calls C​::​g<C> } — end example]
A function parameter declared with an explicit-object-parameter-declaration is an explicit object parameter.
An explicit object parameter shall not be a function parameter pack ([temp.variadic]).
An explicit object member function is a non-static member function with an explicit object parameter.
An implicit object member function is a non-static member function without an explicit object parameter.
The object parameter of a non-static member function is either the explicit object parameter or the implicit object parameter ([over.match.funcs]).
A non-object parameter is a function parameter that is not the explicit object parameter.
The non-object-parameter-type-list of a member function is the parameter-type-list of that function with the explicit object parameter, if any, omitted.
[Note 4: 
The non-object-parameter-type-list consists of the adjusted types of all the non-object parameters.
— end note]
A function type with a cv-qualifier-seq or a ref-qualifier (including a type named by typedef-name ([dcl.typedef], [temp.param])) shall appear only as:
[Example 4: typedef int FIC(int) const; FIC f; // error: does not declare a member function struct S { FIC f; // OK }; FIC S::*pm = &S::f; // OK — end example]
The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type.
In the latter case, the cv-qualifiers are ignored.
[Note 5: 
A function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types.
— end note]
[Example 5: typedef void F(); struct S { const F f; // OK, equivalent to: void f(); }; — end example]
The return type, the parameter-type-list, the ref-qualifier, the cv-qualifier-seq, and the exception specification, but not the default arguments ([dcl.fct.default]) or the trailing requires-clause ([dcl.decl]), are part of the function type.
[Note 6: 
Function types are checked during the assignments and initializations of pointers to functions, references to functions, and pointers to member functions.
— end note]
[Example 6: 
The declaration int fseek(FILE*, long, int); declares a function taking three arguments of the specified types, and returning int ([dcl.type]).
— end example]
[Note 7: 
A single name can be used for several different functions in a single scope; this is function overloading ([over]).
— end note]
The return type shall be a non-array object type, a reference type, or cv void.
[Note 8: 
An array of placeholder type is considered an array type.
— end note]
A volatile-qualified return type is deprecated; see [depr.volatile.type].
Types shall not be defined in return or parameter types.
A typedef of function type may be used to declare a function but shall not be used to define a function ([dcl.fct.def]).
[Example 7: typedef void F(); F fv; // OK, equivalent to void fv(); F fv { } // error void fv() { } // OK, definition of fv — end example]
An identifier can optionally be provided as a parameter name; if present in a function definition ([dcl.fct.def]), it names a parameter.
[Note 9: 
In particular, parameter names are also optional in function definitions and names used for a parameter in different declarations and the definition of a function need not be the same.
— end note]
[Example 8: 
The declaration int i, *pi, f(), *fpi(int), (*pif)(const char*, const char*), (*fpif(int))(int); declares an integer i, a pointer pi to an integer, a function f taking no arguments and returning an integer, a function fpi taking an integer argument and returning a pointer to an integer, a pointer pif to a function which takes two pointers to constant characters and returns an integer, a function fpif taking an integer argument and returning a pointer to a function that takes an integer argument and returns an integer.
It is especially useful to compare fpi and pif.
The binding of *fpi(int) is *(fpi(int)), so the declaration suggests, and the same construction in an expression requires, the calling of a function fpi, and then using indirection through the (pointer) result to yield an integer.
In the declarator (*pif)(const char*, const char*), the extra parentheses are necessary to indicate that indirection through a pointer to a function yields a function, which is then called.
— end example]
[Note 10: 
Typedefs and trailing-return-types are sometimes convenient when the return type of a function is complex.
For example, the function fpif above can be declared typedef int IFUNC(int); IFUNC* fpif(int); or auto fpif(int)->int(*)(int);
A trailing-return-type is most useful for a type that would be more complicated to specify before the declarator-id: template <class T, class U> auto add(T t, U u) -> decltype(t + u); rather than template <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
— end note]
A non-template function is a function that is not a function template specialization.
[Note 11: 
A function template is not a function.
— end note]
An abbreviated function template is a function declaration that has one or more generic parameter type placeholders ([dcl.spec.auto]).
An abbreviated function template is equivalent to a function template ([temp.fct]) whose template-parameter-list includes one invented type template-parameter for each generic parameter type placeholder of the function declaration, in order of appearance.
For a placeholder-type-specifier of the form auto, the invented parameter is an unconstrained type-parameter.
For a placeholder-type-specifier of the form type-constraint auto, the invented parameter is a type-parameter with that type-constraint.
The invented type template-parameter is a template parameter pack if the corresponding parameter-declaration declares a function parameter pack.
If the placeholder contains decltype(auto), the program is ill-formed.
The adjusted function parameters of an abbreviated function template are derived from the parameter-declaration-clause by replacing each occurrence of a placeholder with the name of the corresponding invented template-parameter.
[Example 9: template<typename T> concept C1 = /* ... */; template<typename T> concept C2 = /* ... */; template<typename... Ts> concept C3 = /* ... */; void g1(const C1 auto*, C2 auto&); void g2(C1 auto&...); void g3(C3 auto...); void g4(C3 auto);
The declarations above are functionally equivalent (but not equivalent) to their respective declarations below: template<C1 T, C2 U> void g1(const T*, U&); template<C1... Ts> void g2(Ts&...); template<C3... Ts> void g3(Ts...); template<C3 T> void g4(T);
Abbreviated function templates can be specialized like all function templates.
template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double> — end example]
An abbreviated function template can have a template-head.
The invented template-parameters are appended to the template-parameter-list after the explicitly declared template-parameters.
[Example 10: template<typename> concept C = /* ... */; template <typename T, C U> void g(T x, U y, C auto z);
This is functionally equivalent to each of the following two declarations.
template<typename T, C U, C W> void g(T x, U y, W z); template<typename T, typename U, typename W> requires C<U> && C<W> void g(T x, U y, W z); — end example]
A function declaration at block scope shall not declare an abbreviated function template.
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration.
When it is part of a parameter-declaration-clause, the parameter-declaration declares a function parameter pack ([temp.variadic]).
Otherwise, the parameter-declaration is part of a template-parameter-list and declares a template parameter pack; see [temp.param].
A function parameter pack is a pack expansion ([temp.variadic]).
[Example 11: template<typename... T> void f(T (* ...t)(int, int)); int add(int, int); float subtract(int, int); void g() { f(add, subtract); } — end example]
There is a syntactic ambiguity when an ellipsis occurs at the end of a parameter-declaration-clause without a preceding comma.
In this case, the ellipsis is parsed as part of the abstract-declarator if the type of the parameter either names a template parameter pack that has not been expanded or contains auto; otherwise, it is parsed as part of the parameter-declaration-clause.76
75)75)
As indicated by syntax, cv-qualifiers are a significant component in function return types.
76)76)
One can explicitly disambiguate the parse either by introducing a comma (so the ellipsis will be parsed as part of the parameter-declaration-clause) or by introducing a name for the parameter (so the ellipsis will be parsed as part of the declarator-id).

9.3.4.7 Default arguments [dcl.fct.default]

If an initializer-clause is specified in a parameter-declaration this initializer-clause is used as a default argument.
[Note 1: 
Default arguments will be used in calls where trailing arguments are missing ([expr.call]).
— end note]
[Example 1: 
The declaration void point(int = 3, int = 4); declares a function that can be called with zero, one, or two arguments of type int.
It can be called in any of these ways: point(1,2); point(1); point();
The last two calls are equivalent to point(1,4) and point(3,4), respectively.
— end example]
A default argument shall be specified only in the parameter-declaration-clause of a function declaration or lambda-declarator or in a template-parameter ([temp.param]).
A default argument shall not be specified for a template parameter pack or a function parameter pack.
If it is specified in a parameter-declaration-clause, it shall not occur within a declarator or abstract-declarator of a parameter-declaration.77
For non-template functions, default arguments can be added in later declarations of a function that inhabit the same scope.
Declarations that inhabit different scopes have completely distinct sets of default arguments.
That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa.
In a given function declaration, each parameter subsequent to a parameter with a default argument shall have a default argument supplied in this or a previous declaration, unless the parameter was expanded from a parameter pack, or shall be a function parameter pack.
[Note 2: 
A default argument cannot be redefined by a later declaration (not even to the same value) ([basic.def.odr]).
— end note]
[Example 2: void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow // a parameter with a default argument void f(int, int); void f(int, int = 7); void h() { f(3); // OK, calls f(3, 7) void f(int = 1, int); // error: does not use default from surrounding scope } void m() { void f(int, int); // has no defaults f(4); // error: wrong number of arguments void f(int, int = 5); // OK f(4); // OK, calls f(4, 5); void f(int, int = 5); // error: cannot redefine, even to same value } void n() { f(6); // OK, calls f(6, 7) } template<class ... T> struct C { void f(int n = 0, T...); }; C<int> c; // OK, instantiates declaration void C​::​f(int n = 0, int) — end example]
For a given inline function defined in different translation units, the accumulated sets of default arguments at the end of the translation units shall be the same; no diagnostic is required.
If a friend declaration D specifies a default argument expression, that declaration shall be a definition and there shall be no other declaration of the function or function template which is reachable from D or from which D is reachable.
The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics ([dcl.init]).
The names in the default argument are looked up, and the semantic constraints are checked, at the point where the default argument appears, except that an immediate invocation ([expr.const]) that is a potentially-evaluated subexpression ([intro.execution]) of the initializer-clause in a parameter-declaration is neither evaluated nor checked for whether it is a constant expression at that point.
Name lookup and checking of semantic constraints for default arguments of templated functions are performed as described in [temp.inst].
[Example 3: 
In the following code, g will be called with the value f(2): int a = 1; int f(int); int g(int x = f(a)); // default argument: f(​::​a) void h() { a = 2; { int a = 3; g(); // g(f(​::​a)) } }
— end example]
[Note 3: 
A default argument is a complete-class context ([class.mem]).
Access checking applies to names in default arguments as described in [class.access].
— end note]
Except for member functions of templated classes, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the member function declaration in the class definition; the program is ill-formed if a default constructor ([class.default.ctor]), copy or move constructor ([class.copy.ctor]), or copy or move assignment operator ([class.copy.assign]) is so declared.
Default arguments for a member function of a templated class shall be specified on the initial declaration of the member function within the templated class.
[Example 4: class C { void f(int i = 3); void g(int i, int j = 99); }; void C::f(int i = 3) {} // error: default argument already specified in class scope void C::g(int i = 88, int j) {} // in this translation unit, C​::​g can be called with no arguments — end example]
[Note 4: 
A local variable cannot be odr-used ([basic.def.odr]) in a default argument.
— end note]
[Example 5: void f() { int i; extern void g(int x = i); // error extern void h(int x = sizeof(i)); // OK // ... } — end example]
[Note 5: 
The keyword this cannot appear in a default argument of a member function; see [expr.prim.this].
[Example 6: class A { void f(A* p = this) { } // error }; — end example]
— end note]
A default argument is evaluated each time the function is called with no argument for the corresponding parameter.
A parameter shall not appear as a potentially-evaluated expression in a default argument.
[Note 6: 
Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.
— end note]
[Example 7: int a; int f(int a, int b = a); // error: parameter a used as default argument typedef int I; int g(float I, int b = I(2)); // error: parameter I found int h(int a, int b = sizeof(a)); // OK, unevaluated operand — end example]
A non-static member shall not appear in a default argument unless it appears as the id-expression of a class member access expression ([expr.ref]) or unless it is used to form a pointer to member ([expr.unary.op]).
[Example 8: 
The declaration of X​::​mem1() in the following example is ill-formed because no object is supplied for the non-static member X​::​a used as an initializer.
int b; class X { int a; int mem1(int i = a); // error: non-static member a used as default argument int mem2(int i = b); // OK; use X​::​b static int b; };
The declaration of X​::​mem2() is meaningful, however, since no object is needed to access the static member X​::​b.
Classes, objects, and members are described in [class].
— end example]
A default argument is not part of the type of a function.
[Example 9: int f(int = 0); void h() { int j = f(1); int k = f(); // OK, means f(0) } int (*p1)(int) = &f; int (*p2)() = &f; // error: type mismatch — end example]
When an overload set contains a declaration of a function that inhabits a scope S, any default argument associated with any reachable declaration that inhabits S is available to the call.
[Note 7: 
The candidate might have been found through a using-declarator from which the declaration that provides the default argument is not reachable.
— end note]
A virtual function call ([class.virtual]) uses the default arguments in the declaration of the virtual function determined by the static type of the pointer or reference denoting the object.
An overriding function in a derived class does not acquire default arguments from the function it overrides.
[Example 10: struct A { virtual void f(int a = 7); }; struct B : public A { void f(int a); }; void m() { B* pb = new B; A* pa = pb; pa->f(); // OK, calls pa->B​::​f(7) pb->f(); // error: wrong number of arguments for B​::​f() } — end example]
77)77)
This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.

9.4 Initializers [dcl.init]

9.4.1 General [dcl.init.general]

Except for objects declared with the constexpr specifier, for which see [dcl.constexpr], an initializer in the definition of a variable can consist of arbitrary expressions involving literals and previously declared variables and functions, regardless of the variable's storage duration.
[Example 1: int f(int); int a = 2; int b = f(a); int c(b); — end example]
[Note 2: 
Default arguments are more restricted; see [dcl.fct.default].
— end note]
[Note 3: 
The order of initialization of variables with static storage duration is described in [basic.start] and [stmt.dcl].
— end note]
A declaration D of a variable with linkage shall not have an initializer if D inhabits a block scope.
To zero-initialize an object or reference of type T means:
  • if T is a scalar type ([basic.types.general]), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;78
  • if T is a (possibly cv-qualified) non-union class type, its padding bits ([basic.types.general]) 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, each virtual base class subobject is zero-initialized;
  • if T is a (possibly cv-qualified) union type, its padding bits ([basic.types.general]) are initialized to zero bits and the object's first non-static named data member is zero-initialized;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.
To default-initialize an object of type T means:
  • If T is a (possibly cv-qualified) class type ([class]), constructors are considered.
    The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]).
    The constructor thus selected is called, with an empty argument list, to initialize the object.
  • If T is an array type, the semantic constraints of default-initializing a hypothetical element shall be met and each element is default-initialized.
  • Otherwise, no initialization is performed.
A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if
  • each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible,
  • if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,
  • if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and
  • each potentially constructed base class of T is const-default-constructible.
If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.
To value-initialize an object of type T means:
  • If T is a (possibly cv-qualified) class type ([class]), then let C be the constructor selected to default-initialize the object, if any.
    If C is not user-provided, the object is first zero-initialized.
    In all cases, the object is then default-initialized.
  • If T is an array type, the semantic constraints of value-initializing a hypothetical element shall be met and each element is value-initialized.
  • Otherwise, the object is zero-initialized.
A program that calls for default-initialization or value-initialization of an entity of reference type is ill-formed.
[Note 4: 
For every object of static storage duration, static initialization ([basic.start.static]) is performed at program startup before any other initialization takes place.
In some cases, additional initialization is done later.
— end note]
If no initializer is specified for an object, the object is default-initialized.
If the entity being initialized does not have class or array type, the expression-list in a parenthesized initializer shall be a single expression.
The initialization that occurs in the = form of a brace-or-equal-initializer or condition ([stmt.select]), as well as in argument passing, function return, throwing an exception ([except.throw]), handling an exception ([except.handle]), and aggregate member initialization other than by a designated-initializer-clause ([dcl.init.aggr]), is called copy-initialization.
[Note 5: 
Copy-initialization can invoke a move ([class.copy.ctor]).
— end note]
The initialization that occurs is called direct-initialization.
The semantics of initializers are as follows.
The destination type is the cv-unqualified type of the object or reference being initialized and the source type is the type of the initializer expression.
If the initializer is not a single (possibly parenthesized) expression, the source type is not defined.
  • If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized ([dcl.init.list]).
  • If the destination type is a reference type, see [dcl.init.ref].
  • If the destination type is an array of characters, an array of char8_t, an array of char16_t, an array of char32_t, or an array of wchar_t, and the initializer is a string-literal, see [dcl.init.string].
  • If the initializer is (), the object is value-initialized.
    [Note 6: 
    Since () is not permitted by the syntax for initializer, X a(); is not the declaration of an object of class X, but the declaration of a function taking no arguments and returning an X.
    The form () can appear in certain other initialization contexts ([expr.new], [expr.type.conv], [class.base.init]).
    — end note]
  • Otherwise, if the destination type is an array, the object is initialized as follows.
    The initializer shall be of the form ( expression-list ).
    Let , , be the elements of the expression-list.
    If the destination type is an array of unknown bound, it is defined as having k elements.
    Let n denote the array size after this potential adjustment.
    If k is greater than n, the program is ill-formed.
    Otherwise, the array element is copy-initialized with for each 1  ≤ i  ≤ k, and value-initialized for each .
    For each , every value computation and side effect associated with the initialization of the element of the array is sequenced before those associated with the initialization of the element.
  • Otherwise, if the destination type is a class type:
    • If the initializer expression is a prvalue and the cv-unqualified version of the source type is the same as the destination type, the initializer expression is used to initialize the destination object.
      [Example 2: 
      T x = T(T(T())); value-initializes x.
      — end example]
    • Otherwise, if the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same as or is derived from the class of the destination type, constructors are considered.
      The applicable constructors are enumerated ([over.match.ctor]), and the best one is chosen through overload resolution ([over.match]).
      Then:
      • If overload resolution is successful, the selected constructor is called to initialize the object, with the initializer expression or expression-list as its argument(s).
      • Otherwise, if no constructor is viable, the destination type is an aggregate class, and the initializer is a parenthesized expression-list, the object is initialized as follows.
        Let , , be the elements of the aggregate ([dcl.init.aggr]).
        Let , , be the elements of the expression-list.
        If k is greater than n, the program is ill-formed.
        The element is copy-initialized with for 1  ≤ i  ≤ k.
        The remaining elements are initialized with their default member initializers, if any, and otherwise are value-initialized.
        For each , every value computation and side effect associated with the initialization of is sequenced before those associated with the initialization of .
        [Note 7: 
        By contrast with direct-list-initialization, narrowing conversions ([dcl.init.list]) can appear, designators are not permitted, a temporary object bound to a reference does not have its lifetime extended ([class.temporary]), and there is no brace elision.
        [Example 3: struct A { int a; int&& r; }; int f(); int n = 10; A a1{1, f()}; // OK, lifetime is extended A a2(1, f()); // well-formed, but dangling reference A a3{1.0, 1}; // error: narrowing conversion A a4(1.0, 1); // well-formed, but dangling reference A a5(1.0, std::move(n)); // OK — end example]
        — end note]
      • Otherwise, the initialization is ill-formed.
    • Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversions that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in [over.match.copy], and the best one is chosen through overload resolution ([over.match]).
      If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
      The function selected is called with the initializer expression as its argument; if the function is a constructor, the call is a prvalue of the cv-unqualified version of the destination type whose result object is initialized by the constructor.
      The call is used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
  • Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered.
    The applicable conversion functions are enumerated ([over.match.conv]), and the best one is chosen through overload resolution ([over.match]).
    The user-defined conversion so selected is called to convert the initializer expression into the object being initialized.
    If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
  • Otherwise, if the initialization is direct-initialization, the source type is std​::​nullptr_t, and the destination type is bool, the initial value of the object being initialized is false.
  • Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression.
    A standard conversion sequence ([conv]) is used to convert the initializer expression to a prvalue of the destination type; no user-defined conversions are considered.
    If the conversion cannot be done, the initialization is ill-formed.
    When initializing a bit-field with a value that it cannot represent, the resulting value of the bit-field is implementation-defined.
    [Note 8: 
    An expression of type “cv1 T” can initialize an object of type “cv2 T” independently of the cv-qualifiers cv1 and cv2.
    int a; const int b = a; int c = b; — end note]
An immediate invocation ([expr.const]) that is not evaluated where it appears ([dcl.fct.default], [class.mem.general]) is evaluated and checked for whether it is a constant expression at the point where the enclosing initializer is used in a function call, a constructor definition, or an aggregate initialization.
An initializer-clause followed by an ellipsis is a pack expansion ([temp.variadic]).
Initialization includes the evaluation of all subexpressions of each initializer-clause of the initializer (possibly nested within braced-init-lists) and the creation of any temporary objects for function arguments or return values ([class.temporary]).
If the initializer is a parenthesized expression-list, the expressions are evaluated in the order specified for function calls ([expr.call]).
The same identifier shall not appear in multiple designators of a designated-initializer-list.
An object whose initialization has completed is deemed to be constructed, even if the object is of non-class type or no constructor of the object's class is invoked for the initialization.
[Note 9: 
Such an object might have been value-initialized or initialized by aggregate initialization ([dcl.init.aggr]) or by an inherited constructor ([class.inhctor.init]).
— end note]
Destroying an object of class type invokes the destructor of the class.
Destroying a scalar type has no effect other than ending the lifetime of the object ([basic.life]).
Destroying an array destroys each element in reverse subscript order.
A declaration that specifies the initialization of a variable, whether from an explicit initializer or by default-initialization, is called the initializing declaration of that variable.
[Note 10: 
In most cases this is the defining declaration ([basic.def]) of the variable, but the initializing declaration of a non-inline static data member ([class.static.data]) can be the declaration within the class definition and not the definition (if any) outside it.
— end note]
78)78)
As specified in [conv.ptr], converting an integer literal whose value is 0 to a pointer type results in a null pointer value.

9.4.2 Aggregates [dcl.init.aggr]

An aggregate is an array or a class ([class]) with
[Note 1: 
Aggregate initialization does not allow accessing protected and private base class' members or constructors.
— end note]
The elements of an aggregate are:
  • for an array, the array elements in increasing subscript order, or
  • for a class, the direct base classes in declaration order, followed by the direct non-static data members ([class.mem]) that are not members of an anonymous union, in declaration order.
When an aggregate is initialized by an initializer list as specified in [dcl.init.list], the elements of the initializer list are taken as initializers for the elements of the aggregate.
The explicitly initialized elements of the aggregate are determined as follows:
  • If the initializer list is a brace-enclosed designated-initializer-list, the aggregate shall be of class type, the identifier in each designator shall name a direct non-static data member of the class, and the explicitly initialized elements of the aggregate are the elements that are, or contain, those members.
  • If the initializer list is a brace-enclosed initializer-list, the explicitly initialized elements of the aggregate are those for which an element of the initializer list appertains to the aggregate element or to a subobject thereof (see below).
  • Otherwise, the initializer list must be {}, and there are no explicitly initialized elements.
For each explicitly initialized element:
  • If the element is an anonymous union member and the initializer list is a brace-enclosed designated-initializer-list, the element is initialized by the braced-init-list { D }, where D is the designated-initializer-clause naming a member of the anonymous union member.
    There shall be only one such designated-initializer-clause.
    [Example 1: 
    struct C { union { int a; const char* p; }; int x; } c = { .a = 1, .x = 3 }; initializes c.a with 1 and c.x with 3.
    — end example]
  • Otherwise, if the initializer list is a brace-enclosed designated-initializer-list, the element is initialized with the brace-or-equal-initializer of the corresponding designated-initializer-clause.
    If that initializer is of the form = assignment-expression and a narrowing conversion ([dcl.init.list]) is required to convert the expression, the program is ill-formed.
    [Note 2: 
    The form of the initializer determines whether copy-initialization or direct-initialization is performed.
    — end note]
  • Otherwise, the initializer list is a brace-enclosed initializer-list.
    If an initializer-clause appertains to the aggregate element, then the aggregate element is copy-initialized from the initializer-clause.
    Otherwise, the aggregate element is copy-initialized from a brace-enclosed initializer-list consisting of all of the initializer-clauses that appertain to subobjects of the aggregate element, in the order of appearance.
    [Note 3: 
    If an initializer is itself an initializer list, the element is list-initialized, which will result in a recursive application of the rules in this subclause if the element is an aggregate.
    — end note]
    [Example 2: 
    struct A { int x; struct B { int i; int j; } b; } a = { 1, { 2, 3 } }; initializes a.x with 1, a.b.i with 2, a.b.j with 3.
    struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1{{1, 2}, {}, 4}; derived d2{{}, {}, 4}; initializes d1.b1 with 1, d1.b2 with 2, d1.b3 with 42, d1.d with 4, and d2.b1 with 0, d2.b2 with 42, d2.b3 with 42, d2.d with 4.
    — end example]
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
  • If the element has a default member initializer ([class.mem]), the element is initialized from that initializer.
  • Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
  • Otherwise, the program is ill-formed.
If the aggregate is a union and the initializer list is empty, then
  • if any variant member has a default member initializer, that member is initialized from its default member initializer;
  • otherwise, the first member of the union (if any) is copy-initialized from an empty initializer list.
[Example 3: 
struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" }; initializes ss.a with 1, ss.b with "asdf", ss.c with the value of an expression of the form int{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, 's').
struct A { string a; int b = 42; int c = -1; };
A{.c=21} has the following steps:
  • Initialize a with {}
  • Initialize b with = 42
  • Initialize c with = 21
— end example]
The initializations of the elements of the aggregate are evaluated in the element order.
That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.
An aggregate that is a class can also be initialized with a single expression not enclosed in braces, as described in [dcl.init].
The destructor for each element of class type other than an anonymous union member is potentially invoked ([class.dtor]) from the context where the aggregate initialization occurs.
[Note 4: 
This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([except.ctor]).
— end note]
The number of elements ([dcl.array]) in an array of unknown bound initialized with a brace-enclosed initializer-list is the number of explicitly initialized elements of the array.
[Example 4: 
int x[] = { 1, 3, 5 }; declares and initializes x as a one-dimensional array that has three elements since no size was specified and there are three initializers.
— end example]
[Example 5: 
In struct X { int i, j, k; }; X a[] = { 1, 2, 3, 4, 5, 6 }; X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } }; a and b have the same value.
— end example]
An array of unknown bound shall not be initialized with an empty braced-init-list {}.79
[Note 5: 
A default member initializer does not determine the bound for a member array of unknown bound.
Since the default member initializer is ignored if a suitable mem-initializer is present ([class.base.init]), the default member initializer is not considered to initialize the array of unknown bound.
[Example 6: struct S { int y[] = { 0 }; // error: non-static data member of incomplete type }; — end example]
— end note]
[Note 6: 
Static data members, non-static data members of anonymous union members, and unnamed bit-fields are not considered elements of the aggregate.
[Example 7: struct A { int i; static int s; int j; int :17; int k; } a = { 1, 2, 3 };
Here, the second initializer 2 initializes a.j and not the static data member A​::​s, and the third initializer 3 initializes a.k and not the unnamed bit-field before it.
— end example]
— end note]
If a member has a default member initializer and a potentially-evaluated subexpression thereof is an aggregate initialization that would use that default member initializer, the program is ill-formed.
[Example 8: struct A; extern A a; struct A { const A& a1 { A{a,a} }; // OK const A& a2 { A{} }; // error }; A a{a,a}; // OK struct B { int n = B{}.n; // error }; — end example]
When initializing a multidimensional array, the initializer-clauses initialize the elements with the last (rightmost) index of the array varying the fastest ([dcl.array]).
[Example 9: 
int x[2][2] = { 3, 1, 4, 2 }; initializes x[0][0] to 3, x[0][1] to 1, x[1][0] to 4, and x[1][1] to 2.
On the other hand, float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; initializes the first column of y (regarded as a two-dimensional array) and leaves the rest zero.
— end example]
Each initializer-clause in a brace-enclosed initializer-list is said to appertain to an element of the aggregate being initialized or to an element of one of its subaggregates.
Considering the sequence of initializer-clauses, and the sequence of aggregate elements initially formed as the sequence of elements of the aggregate being initialized and potentially modified as described below, each initializer-clause appertains to the corresponding aggregate element if
  • the aggregate element is not an aggregate, or
  • the initializer-clause begins with a left brace, or
  • the initializer-clause is an expression and an implicit conversion sequence can be formed that converts the expression to the type of the aggregate element, or
  • the aggregate element is an aggregate that itself has no aggregate elements.
Otherwise, the aggregate element is an aggregate and that subaggregate is replaced in the list of aggregate elements by the sequence of its own aggregate elements, and the appertainment analysis resumes with the first such element and the same initializer-clause.
[Note 7: 
These rules apply recursively to the aggregate's subaggregates.
[Example 10: 
In struct S1 { int a, b; }; struct S2 { S1 s, t; }; S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 }; S2 y[2] = { { { 1, 2 }, { 3, 4 } }, { { 5, 6 }, { 7, 8 } } }; x and y have the same value.
— end example]
— end note]
This process continues until all initializer-clauses have been exhausted.
If any initializer-clause remains that does not appertain to an element of the aggregate or one of its subaggregates, the program is ill-formed.
[Example 11: char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers — end example]
[Example 12: 
float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, }; is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2].
Likewise the next two lines initialize y[1] and y[2].
The initializer ends early and therefore y[3]'s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0.
In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example, float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 };
The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used.
Likewise the next three are taken successively for y[1] and y[2].
— end example]
[Note 8: 
The initializer for an empty subaggregate is needed if any initializers are provided for subsequent elements.
[Example 13: struct S { } s; struct A { S s1; int i1; S s2; int i2; S s3; int i3; } a = { { }, // Required initialization 0, s, // Required initialization 0 }; // Initialization not required for A​::​s3 because A​::​i3 is also not initialized — end example]
— end note]
[Example 14: struct A { int i; operator int(); }; struct B { A a1, a2; int z; }; A a; B b = { 4, a, a };
Braces are elided around the initializer-clause for b.a1.i.
b.a1.i is initialized with 4, b.a2 is initialized with a, b.z is initialized with whatever a.operator int() returns.
— end example]
[Note 9: 
An aggregate array or an aggregate class can contain elements of a class type with a user-declared constructor ([class.ctor]).
Initialization of these aggregate objects is described in [class.expl.init].
— end note]
[Note 10: 
Whether the initialization of aggregates with static storage duration is static or dynamic is specified in [basic.start.static], [basic.start.dynamic], and [stmt.dcl].
— end note]
When a union is initialized with an initializer list, there shall not be more than one explicitly initialized element.
[Example 15: union u { int a; const char* b; }; u a = { 1 }; u b = a; u c = 1; // error u d = { 0, "asdf" }; // error u e = { "asdf" }; // error u f = { .b = "asdf" }; u g = { .a = 1, .b = "asdf" }; // error — end example]
[Note 11: 
As described above, the braces around the initializer-clause for a union member can be omitted if the union is a member of another aggregate.
— end note]
79)79)
The syntax provides for empty braced-init-lists, but nonetheless C++ does not have zero length arrays.

9.4.3 Character arrays [dcl.init.string]

An array of ordinary character type ([basic.fundamental]), char8_t array, char16_t array, char32_t array, or wchar_t array may be initialized by an ordinary string literal, UTF-8 string literal, UTF-16 string literal, UTF-32 string literal, or wide string literal, respectively, or by an appropriately-typed string-literal enclosed in braces ([lex.string]).
Additionally, an array of char or unsigned char may be initialized by a UTF-8 string literal, or by such a string literal enclosed in braces.
Successive characters of the value of the string-literal initialize the elements of the array, with an integral conversion ([conv.integral]) if necessary for the source and destination value.
[Example 1: 
char msg[] = "Syntax error on line %s\n"; shows a character array whose members are initialized with a string-literal.
Note that because '\n' is a single character and because a trailing '\0' is appended, sizeof(msg) is 25.
— end example]
There shall not be more initializers than there are array elements.
[Example 2: 
char cv[4] = "asdf"; // error is ill-formed since there is no space for the implied trailing '\0'.
— end example]
If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized ([dcl.init]).

9.4.4 References [dcl.init.ref]

A variable whose declared type is “reference to T” ([dcl.ref]) shall be initialized.
[Example 1: int g(int) noexcept; void f() { int i; int& r = i; // r refers to i r = 1; // the value of i becomes 1 int* p = &r; // p points to i int& rr = r; // rr refers to what r refers to, that is, to i int (&rg)(int) = g; // rg refers to the function g rg(i); // calls function g int a[3]; int (&ra)[3] = a; // ra refers to the array a ra[1] = i; // modifies a[1] } — end example]
A reference cannot be changed to refer to another object after initialization.
[Note 1: 
Assignment to a reference assigns to the object referred to by the reference ([expr.ass]).
— end note]
Argument passing ([expr.call]) and function value return ([stmt.return]) are initializations.
The initializer can be omitted for a reference only in a parameter declaration ([dcl.fct]), in the declaration of a function return type, in the declaration of a class member within its class definition ([class.mem]), and where the extern specifier is explicitly used.
[Example 2: int& r1; // error: initializer missing extern int& r2; // OK — end example]
Given types “cv1 T1” and “cv2 T2”, “cv1 T1” is reference-related to “cv2 T2” if T1 is similar ([conv.qual]) to T2, or T1 is a base class of T2.
cv1 T1” is reference-compatible with “cv2 T2” if a prvalue of type “pointer to cv2 T2” can be converted to the type “pointer to cv1 T1” via a standard conversion sequence ([conv]).
In all cases where the reference-compatible relationship of two types is used to establish the validity of a reference binding and the standard conversion sequence would be ill-formed, a program that necessitates such a binding is ill-formed.
A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
  • If the reference is an lvalue reference and the initializer expression
    • is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2”, or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T380 (this conversion is selected by enumerating the applicable conversion functions ([over.match.ref]) and choosing the best one through overload resolution),
    then the reference binds to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).
    [Note 2: 
    The usual lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done.
    — end note]
    [Example 3: double d = 2.0; double& rd = d; // rd refers to d const double& rcd = d; // rcd refers to d struct A { }; struct B : A { operator int&(); } b; A& ra = b; // ra refers to A subobject in b const A& rca = b; // rca refers to A subobject in b int& ir = B(); // ir refers to the result of B​::​operator int& — end example]
  • Otherwise, if the reference is an lvalue reference to a type that is not const-qualified or is volatile-qualified, the program is ill-formed.
    [Example 4: double& rd2 = 2.0; // error: not an lvalue and reference not const int i = 2; double& rd3 = i; // error: type mismatch and reference not const — end example]
  • Otherwise, if the initializer expression
    • is an rvalue (but not a bit-field) or an lvalue of function type and “cv1 T1” is reference-compatible with “cv2 T2”, or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an rvalue of type “cv3 T3” or an lvalue of function type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3” (see [over.match.ref]),
    then the initializer expression in the first case and the converted expression in the second case is called the converted initializer.
    If the converted initializer is a prvalue, let its type be denoted by T4; the temporary materialization conversion ([conv.rval]) is applied, considering the type of the prvalue to be “cv1 T4” ([conv.qual]).
    In any case, the reference binds to the resulting glvalue (or to an appropriate base class subobject).
    [Example 5: struct A { }; struct B : A { } b; extern B f(); const A& rca2 = f(); // binds to the A subobject of the B rvalue. A&& rra = f(); // same as above struct X { operator B(); operator int&(); } x; const A& r = x; // binds to the A subobject of the result of the conversion int i2 = 42; int&& rri = static_cast<int&&>(i2); // binds directly to i2 B&& rrb = x; // binds directly to the result of operator B constexpr int f() { const int &x = 42; const_cast<int &>(x) = 1; // undefined behavior return x; } constexpr int z = f(); // error: not a constant expression typedef int *A[3]; // array of 3 pointer to int typedef const int *const CA[3]; // array of 3 const pointer to const int ACPC &&r = AP{}; // binds directly — end example]
  • Otherwise, T1 shall not be reference-related to T2.
    • If T1 or T2 is a class type, user-defined conversions are considered using the rules for copy-initialization of an object of type “cv1 T1” by user-defined conversion ([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 copy-initialization, is then used to direct-initialize the reference.
      For this direct-initialization, user-defined conversions are not considered.
    • Otherwise, the initializer expression is implicitly converted to a prvalue of type “T1.
      The temporary materialization conversion is applied, considering the type of the prvalue to be “cv1 T1”, and the reference is bound to the result.
    [Example 6: struct Banana { }; struct Enigma { operator const Banana(); }; struct Alaska { operator Banana&(); }; void enigmatic() { typedef const Banana ConstBanana; Banana &&banana1 = ConstBanana(); // error Banana &&banana2 = Enigma(); // error Banana &&banana3 = Alaska(); // error } const double& rcd2 = 2; // rcd2 refers to temporary with type const double and value 2.0 double&& rrd = 2; // rrd refers to temporary with value 2.0 const volatile int cvi = 1; const int& r2 = cvi; // error: cv-qualifier dropped struct A { operator volatile int&(); } a; const int& r3 = a; // error: cv-qualifier dropped // from result of conversion function double d2 = 1.0; double&& rrd2 = d2; // error: initializer is lvalue of reference-related type struct X { operator int&(); }; int&& rri2 = X(); // error: result of conversion function is // lvalue of reference-related type int i3 = 2; double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0 — end example]
In all cases except the last (i.e., implicitly converting the initializer expression to the referenced type), the reference is said to bind directly to the initializer expression.
[Note 3: 
[class.temporary] describes the lifetime of temporaries bound to references.
— end note]
80)80)
This requires a conversion function ([class.conv.fct]) returning a reference type.

9.4.5 List-initialization [dcl.init.list]

List-initialization is initialization of an object or reference from a braced-init-list.
Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the initializer-list or designated-initializer-clauses of the designated-initializer-list are called the elements of the initializer list.
An initializer list may be empty.
List-initialization can occur in direct-initialization or copy-initialization contexts; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization.
Direct-initialization that is not list-initialization is called direct-non-list-initialization.
[Note 1: 
List-initialization can be used
[Example 1: int a = {1}; std::complex<double> z{1,2}; new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements f( {"Nicholas","Annemarie"} ); // pass list of two elements return { "Norah" }; // return list of one element int* e {}; // initialization to zero / null pointer x = double{1}; // explicitly construct a double std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; — end example]
— end note]
A constructor is an initializer-list constructor if its first parameter is of type std​::​initializer_list<E> or reference to cv std​::​initializer_list<E> for some type E, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).
[Note 2: 
Initializer-list constructors are favored over other constructors in list-initialization ([over.match.list]).
Passing an initializer list as the argument to the constructor template template<class T> C(T) of a class C does not create an initializer-list constructor, because an initializer list argument causes the corresponding parameter to be a non-deduced context ([temp.deduct.call]).
— end note]
The template std​::​initializer_list is not predefined; if a standard library declaration ([initializer.list.syn], [std.modules]) of std​::​initializer_list is not reachable from ([module.reach]) a use of std​::​initializer_list — even an implicit use in which the type is not named ([dcl.spec.auto]) — the program is ill-formed.
List-initialization of an object or reference of type cv T is defined as follows:
  • If the braced-init-list contains a designated-initializer-list and T is not a reference type, T shall be an aggregate class.
    The ordered identifiers in the designators of the designated-initializer-list shall form a subsequence of the ordered identifiers in the direct non-static data members of T.
    Aggregate initialization is performed ([dcl.init.aggr]).
    [Example 2: struct A { int x; int y; int z; }; A a{.y = 2, .x = 1}; // error: designator order does not match declaration order A b{.x = 1, .z = 2}; // OK, b.y initialized to 0 — end example]
  • If T is an aggregate class and the initializer list has a single element of type cv1 U, where U is T or a class derived from T, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
  • Otherwise, if T is a character array and the initializer list has a single element that is an appropriately-typed string-literal ([dcl.init.string]), initialization is performed as described in that subclause.
  • Otherwise, if T is an aggregate, aggregate initialization is performed ([dcl.init.aggr]).
    [Example 3: double ad[] = { 1, 2.0 }; // OK int ai[] = { 1, 2.0 }; // error: narrowing struct S2 { int m1; double m2, m3; }; S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing S2 s23 { }; // OK, default to 0,0,0 — end example]
  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
  • Otherwise, if T is a specialization of std​::​initializer_list, the object is constructed as described below.
  • Otherwise, if T is a class type, constructors are considered.
    The applicable constructors are enumerated and the best one is chosen through overload resolution ([over.match], [over.match.list]).
    If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
    [Example 4: struct S { S(std::initializer_list<double>); // #1 S(std::initializer_list<int>); // #2 S(std::initializer_list<S>); // #3 S(); // #4 // ... }; S s1 = { 1.0, 2.0, 3.0 }; // invoke #1 S s2 = { 1, 2, 3 }; // invoke #2 S s3{s2}; // invoke #3 (not the copy constructor) S s4 = { }; // invoke #4 — end example]
    [Example 5: struct Map { Map(std::initializer_list<std::pair<std::string,int>>); }; Map ship = {{"Sophie",14}, {"Surprise",28}}; — end example]
    [Example 6: struct S { // no initializer-list constructors S(int, double, double); // #1 S(); // #2 // ... }; S s1 = { 1, 2, 3.0 }; // OK, invoke #1 S s2 { 1.0, 2, 3 }; // error: narrowing S s3 { }; // OK, invoke #2 — end example]
  • Otherwise, if T is an enumeration with a fixed underlying type ([dcl.enum]) U, the initializer-list has a single element v of scalar type, v can be implicitly converted to U, and the initialization is direct-list-initialization, the object is initialized with the value T(v) ([expr.type.conv]); if a narrowing conversion is required to convert v to U, the program is ill-formed.
    [Example 7: enum byte : unsigned char { }; byte b { 42 }; // OK byte c = { 42 }; // error byte d = byte{ 42 }; // OK; same value as b byte e { -1 }; // error struct A { byte b; }; A a1 = { { 42 } }; // error A a2 = { byte{ 42 } }; // OK void f(byte); f({ 42 }); // error enum class Handle : uint32_t { Invalid = 0 }; Handle h { 42 }; // OK — end example]
  • Otherwise, if the initializer list is not a designated-initializer-list and has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization); if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.
    [Example 8: int x1 {2}; // OK int x2 {2.0}; // error: narrowing — end example]
  • Otherwise, if T is a reference type, a prvalue is generated.
    The prvalue initializes its result object by copy-list-initialization from the initializer list.
    The prvalue is then used to direct-initialize the reference.
    The type of the prvalue is the type referenced by T, unless T is “reference to array of unknown bound of U”, in which case the type of the prvalue is the type of x in the declaration U x[] H, where H is the initializer list.
    [Note 3: 
    As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type.
    — end note]
    [Example 9: struct S { S(std::initializer_list<double>); // #1 S(const std::string&); // #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, iar is bound to temporary array struct A { } a; struct B { explicit B(const A&); }; const B& b2{a}; // error: cannot copy-list-initialize B temporary from A struct C { int x; }; C&& c = { .x = 1 }; // OK — end example]
  • Otherwise, if the initializer list has no elements, the object is value-initialized.
    [Example 10: int** pp {}; // initialized to null pointer — end example]
  • Otherwise, the program is ill-formed.
    [Example 11: struct A { int i; int j; }; A a1 { 1, 2 }; // aggregate initialization A a2 { 1.2 }; // error: narrowing struct B { B(std::initializer_list<int>); }; B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor B b2 { 1, 2.0 }; // error: narrowing struct C { C(int i, double j); }; C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) C c2 = { 1.1, 2 }; // error: narrowing int j { 1 }; // initialize to 1 int k { }; // initialize to 0 — end example]
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions ([temp.variadic]), are evaluated in the order in which they appear.
That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.
[Note 4: 
This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call.
— end note]
An object of type std​::​initializer_list<E> is constructed from an initializer list as if the implementation generated and materialized ([conv.rval]) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list; this is called the initializer list's backing array.
Each element of the backing array is copy-initialized with the corresponding element of the initializer list, and the std​::​initializer_list<E> object is constructed to refer to that array.
[Note 5: 
A constructor or conversion function selected for the copy needs to be accessible ([class.access]) in the context of the initializer list.
— end note]
If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.
[Note 6: 
Backing arrays are potentially non-unique objects ([intro.object]).
— end note]
The backing array has the same lifetime as any other temporary object ([class.temporary]), except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary.
[Example 12: void f(std::initializer_list<double> il); void g(float x) { f({1, x, 3}); } void h() { f({1, 2, 3}); } struct A { mutable int i; }; void q(std::initializer_list<A>); void r() { q({A{1}, A{2}, A{3}}); }
The initialization will be implemented in a way roughly equivalent to this: void g(float x) { const double __a[3] = {double{1}, double{x}, double{3}}; // backing array f(std::initializer_list<double>(__a, __a+3)); } void h() { static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array f(std::initializer_list<double>(__b, __b+3)); } void r() { const A __c[3] = {A{1}, A{2}, A{3}}; // backing array q(std::initializer_list<A>(__c, __c+3)); } assuming that the implementation can construct an initializer_list object with a pair of pointers, and with the understanding that __b does not outlive the call to f.
— end example]
[Example 13: typedef std::complex<double> cmplx; std::vector<cmplx> v1 = { 1, 2, 3 }; void f() { std::vector<cmplx> v2{ 1, 2, 3 }; std::initializer_list<int> i3 = { 1, 2, 3 }; } struct A { std::initializer_list<int> i4; A() : i4{ 1, 2, 3 } {} // ill-formed, would create a dangling reference };
For v1 and v2, the initializer_list object is a parameter in a function call, so the array created for { 1, 2, 3 } has full-expression lifetime.
For i3, the initializer_list object is a variable, so the array persists for the lifetime of the variable.
For i4, the initializer_list object is initialized in the constructor's ctor-initializer as if by binding a temporary array to a reference member, so the program is ill-formed ([class.base.init]).
— end example]
A narrowing conversion is an implicit conversion
  • from a floating-point type to an integer type, or
  • from a floating-point type T to another floating-point type whose floating-point conversion rank is neither greater than nor equal to that of T, except where the result of the conversion is a constant expression and either its value is finite and the conversion did not overflow, or the values before and after the conversion are not finite, or
  • from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
  • from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where
    • the source is a bit-field whose width w is less than that of its type (or, for an enumeration type, its underlying type) and the target type can represent all the values of a hypothetical extended integer type with width w and with the same signedness as the original type or
    • the source is a constant expression whose value after integral promotions will fit into the target type, or
  • from a pointer type or a pointer-to-member type to bool.
[Note 7: 
As indicated above, such conversions are not allowed at the top level in list-initializations.
— end note]
[Example 14: int x = 999; // x is not a constant expression const int y = 999; const int z = 99; 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 char is 8 bits) 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 float bool b = {"meow"}; // error: narrows int f(int); int a[] = { 2, f(2), f(2.0) }; // OK, the double-to-int conversion is not at the top level — end example]

9.5 Function definitions [dcl.fct.def]

9.5.1 General [dcl.fct.def.general]

deleted-function-body:
= delete ;
= delete ( unevaluated-string ) ;
Any informal reference to the body of a function should be interpreted as a reference to the non-terminal function-body, including, for a constructor, default member initializers or default initialization used to initialize a base or member subobject in the absence of a mem-initializer-id ([class.base.init]).
The optional attribute-specifier-seq in a function-definition appertains to the function.
A function-definition with a requires-clause shall define a templated function.
In a function-definition, either void declarator ; or declarator ; shall be a well-formed function declaration as described in [dcl.fct].
A function shall be defined only in namespace or class scope.
The type of a parameter or the return type for a function definition shall not be a (possibly cv-qualified) class type that is incomplete or abstract within the function body unless the function is deleted ([dcl.fct.def.delete]).
[Example 1: 
A simple example of a complete function definition is int max(int a, int b, int c) { int m = (a > b) ? a : b; return (m > c) ? m : c; }
Here int is the decl-specifier-seq; max(int a, int b, int c) is the declarator; { /* ... */ } is the function-body.
— end example]
A ctor-initializer is used only in a constructor; see [class.ctor] and [class.init].
[Note 1: 
A cv-qualifier-seq affects the type of this in the body of a member function; see [expr.prim.this].
— end note]
[Note 2: 
Unused parameters need not be named.
For example,
void print(int a, int) { std::printf("a = %d\n",a); } — end note]
A function-local predefined variable is a variable with static storage duration that is implicitly defined in a function parameter scope.
The function-local predefined variable __func__ is defined as if a definition of the form static const char __func__[] = "function-name"; had been provided, where function-name is an implementation-defined string.
It is unspecified whether such a variable has an address distinct from that of any other object in the program.81
[Example 2: struct S { S() : s(__func__) { } // OK const char* s; }; void f(const char* s = __func__); // error: __func__ is undeclared — end example]
81)81)
Implementations are permitted to provide additional predefined variables with names that are reserved to the implementation ([lex.name]).
If a predefined variable is not odr-used ([basic.def.odr]), its string value need not be present in the program image.

9.5.2 Explicitly-defaulted functions [dcl.fct.def.default]

A function definition whose function-body is of the form = default ; is called an explicitly-defaulted definition.
A function that is explicitly defaulted shall
An explicitly defaulted special member function is allowed to differ from the corresponding special member function that would have been implicitly declared, as follows:
  • and may have differing ref-qualifiers;
  • if has an implicit object parameter of type “reference to C”, may be an explicit object member function whose explicit object parameter is of (possibly different) type “reference to C”, in which case the type of would differ from the type of in that the type of has an additional parameter;
  • and may have differing exception specifications; and
  • if has a non-object parameter of type const C&, the corresponding non-object parameter of may be of type C&.
If the type of differs from the type of in a way other than as allowed by the preceding rules, then:
  • if is an assignment operator, and the return type of differs from the return type of or 's non-object parameter type is not a reference, the program is ill-formed;
  • otherwise, if is explicitly defaulted on its first declaration, it is defined as deleted;
  • otherwise, the program is ill-formed.
A function explicitly defaulted on its first declaration is implicitly inline ([dcl.inline]), and is implicitly constexpr ([dcl.constexpr]) if it is constexpr-suitable.
[Note 1: 
Other defaulted functions are not implicitly constexpr.
— end note]
[Example 1: struct S { S(int a = 0) = default; // error: default argument void operator=(const S&) = default; // error: non-matching return type ~S() noexcept(false) = default; // OK, despite mismatched exception specification private: int i; S(S&); // OK, private copy constructor }; S::S(S&) = default; // OK, defines copy constructor struct T { T(); T(T &&) noexcept(false); }; struct U { T t; U(); U(U &&) noexcept = default; }; U u1; U u2 = static_cast<U&&>(u1); // OK, calls std​::​terminate if T​::​T(T&&) throws — end example]
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor], [class.dtor], [class.copy.ctor], [class.copy.assign]) as described below, including possibly defining them as deleted.
A defaulted prospective destructor ([class.dtor]) that is not a destructor is defined as deleted.
A defaulted special member function that is neither a prospective destructor nor an eligible special member function ([special]) is defined as deleted.
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed.
[Note 2: 
Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base.
— end note]
A non-user-provided defaulted function (i.e., implicitly declared or explicitly defaulted in the class) that is not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) or needed for constant evaluation ([expr.const]).
[Note 3: 
The implicit definition of a non-user-provided defaulted function does not bind any names.
— end note]
[Example 2: struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration — end example]

9.5.3 Deleted definitions [dcl.fct.def.delete]

A deleted definition of a function is a function definition whose function-body is a deleted-function-body or an explicitly-defaulted definition of the function where the function is defined as deleted.
A deleted function is a function with a deleted definition or a function that is implicitly defined as deleted.
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
Recommended practice: The resulting diagnostic message should include the text of the unevaluated-string, if one is supplied.
[Note 1: 
This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function.
It applies even for references in expressions that are not potentially-evaluated.
For an overload set, only the function selected by overload resolution is referenced.
The implicit odr-use ([basic.def.odr]) of a virtual function does not, by itself, constitute a reference.
The unevaluated-string, if present, can be used to explain the rationale for deletion and/or to suggest an alternative.
— end note]
[Example 1: 
One can prevent default initialization and initialization by non-doubles with struct onlydouble { onlydouble() = delete; // OK, but redundant template<class T> onlydouble(T) = delete; onlydouble(double); };
— end example]
[Example 2: 
One can prevent use of a class in certain new-expressions by using deleted definitions of a user-declared operator new for that class.
struct sometype { void* operator new(std::size_t) = delete; void* operator new[](std::size_t) = delete; }; sometype* p = new sometype; // error: deleted class operator new sometype* q = new sometype[3]; // error: deleted class operator new[] — end example]
[Example 3: 
One can make a class uncopyable, i.e., move-only, by using deleted definitions of the copy constructor and copy assignment operator, and then providing defaulted definitions of the move constructor and move assignment operator.
struct moveonly { moveonly() = default; moveonly(const moveonly&) = delete; moveonly(moveonly&&) = default; moveonly& operator=(const moveonly&) = delete; moveonly& operator=(moveonly&&) = default; ~moveonly() = default; }; moveonly* p; moveonly q(*p); // error: deleted copy constructor — end example]
A deleted function is implicitly an inline function ([dcl.inline]).
[Note 2: 
The one-definition rule ([basic.def.odr]) applies to deleted definitions.
— end note]
A deleted definition of a function shall be the first declaration of the function or, for an explicit specialization of a function template, the first declaration of that specialization.
An implicitly declared allocation or deallocation function ([basic.stc.dynamic]) shall not be defined as deleted.
[Example 4: struct sometype { sometype(); }; sometype::sometype() = delete; // error: not first declaration — end example]

9.5.4 Coroutine definitions [dcl.fct.def.coroutine]

The parameter-declaration-clause of the coroutine shall not terminate with an ellipsis that is not part of a parameter-declaration.
[Example 1: task<int> f(); task<void> g1() { int i = co_await f(); std::cout << "f() => " << i << std::endl; } template <typename... Args> task<void> g2(Args&&...) { // OK, ellipsis is a pack expansion int i = co_await f(); std::cout << "f() => " << i << std::endl; } task<void> g3(int a, ...) { // error: variable parameter list not allowed int i = co_await f(); std::cout << "f() => " << i << std::endl; } — end example]
The promise type of a coroutine is std​::​coroutine_traits<R, P, , P>​::​promise_type, where R is the return type of the function, and is the sequence of types of the non-object function parameters, preceded by the type of the object parameter ([dcl.fct]) if the coroutine is a non-static member function.
The promise type shall be a class type.
In the following, is an lvalue of type , where denotes the object parameter and denotes the non-object function parameter for an implicit object member function, and denotes the function parameter otherwise.
For an implicit object member function, is an lvalue that denotes *this; any other is an lvalue that denotes the parameter copy corresponding to , as described below.
A coroutine behaves as if its function-body were replaced by:
{
   promise-type promise promise-constructor-arguments ;
   try {
      co_await promise.initial_suspend() ;
      function-body
   } catch ( ... ) {
      if (!initial-await-resume-called)
         throw ;
      promise.unhandled_exception() ;
   }
final-suspend :
   co_await promise.final_suspend() ;
}
where
  • the await-expression containing the call to initial_suspend is the initial await expression, and
  • the await-expression containing the call to final_suspend is the final await expression, and
  • initial-await-resume-called is initially false and is set to true immediately before the evaluation of the await-resume expression ([expr.await]) of the initial await expression, and
  • promise-type denotes the promise type, and
  • the object denoted by the exposition-only name promise is the promise object of the coroutine, and
  • the label denoted by the name final-suspend is defined for exposition only ([stmt.return.coroutine]), and
  • promise-constructor-arguments is determined as follows: overload resolution is performed on a promise constructor call created by assembling an argument list .
    If a viable constructor is found ([over.match.viable]), then promise-constructor-arguments is (, , ), otherwise promise-constructor-arguments is empty, and
  • a coroutine is suspended at the initial suspend point if it is suspended at the initial await expression, and
  • a coroutine is suspended at a final suspend point if it is suspended
    • at a final await expression or
    • due to an exception exiting from unhandled_exception().
If searches for the names return_void and return_value in the scope of the promise type each find any declarations, the program is ill-formed.
[Note 1: 
If return_void is found, flowing off the end of a coroutine is equivalent to a co_return with no operand.
Otherwise, flowing off the end of a coroutine results in undefined behavior ([stmt.return.coroutine]).
— end note]
The expression promise.get_return_object() is used to initialize the returned reference or prvalue result object of a call to a coroutine.
The call to get_return_object is sequenced before the call to initial_suspend and is invoked at most once.
A suspended coroutine can be resumed to continue execution by invoking a resumption member function ([coroutine.handle.resumption]) of a coroutine handle ([coroutine.handle]) that refers to the coroutine.
The evaluation that invoked a resumption member function is called the resumer.
Invoking a resumption member function for a coroutine that is not suspended results in undefined behavior.
An implementation may need to allocate additional storage for a coroutine.
This storage is known as the coroutine state and is obtained by calling a non-array allocation function ([basic.stc.dynamic.allocation]).
The allocation function's name is looked up by searching for it in the scope of the promise type.
  • If the search finds any declarations, overload resolution is performed on a function call created by assembling an argument list.
    The first argument is the amount of space requested, and is a prvalue of type std​::​size_t.
    The lvalues are the successive arguments.
    If no viable function is found ([over.match.viable]), overload resolution is performed again on a function call created by passing just the amount of space required as a prvalue of type std​::​size_t.
  • If the search finds no declarations, a search is performed in the global scope.
    Overload resolution is performed on a function call created by passing the amount of space required as a prvalue of type std​::​size_t.
If a search for the name get_return_object_on_allocation_failure in the scope of the promise type ([class.member.lookup]) finds any declarations, then the result of a call to an allocation function used to obtain storage for the coroutine state is assumed to return nullptr if it fails to obtain storage, and if a global allocation function is selected, the ​::​operator new(size_t, nothrow_t) form is used.
The allocation function used in this case shall have a non-throwing noexcept-specifier.
If the allocation function returns nullptr, the coroutine transfers control to the caller of the coroutine and the return value is obtained by a call to T​::​get_return_object_on_allocation_failure(), where T is the promise type.
[Example 2: #include <iostream> #include <coroutine> // ​::​operator new(size_t, nothrow_t) will be used if allocation is needed struct generator { struct promise_type; using handle = std::coroutine_handle<promise_type>; struct promise_type { int current_value; static auto get_return_object_on_allocation_failure() { return generator{nullptr}; } auto get_return_object() { return generator{handle::from_promise(*this)}; } auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() noexcept { return std::suspend_always{}; } void unhandled_exception() { std::terminate(); } void return_void() {} auto yield_value(int value) { current_value = value; return std::suspend_always{}; } }; bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; } int current_value() { return coro.promise().current_value; } generator(generator const&) = delete; generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; } ~generator() { if (coro) coro.destroy(); } private: generator(handle h) : coro(h) {} handle coro; }; generator f() { co_yield 1; co_yield 2; } int main() { auto g = f(); while (g.move_next()) std::cout << g.current_value() << std::endl; } — end example]
The coroutine state is destroyed when control flows off the end of the coroutine or the destroy member function ([coroutine.handle.resumption]) of a coroutine handle ([coroutine.handle]) that refers to the coroutine is invoked.
In the latter case, control in the coroutine is considered to be transferred out of the function ([stmt.dcl]).
The storage for the coroutine state is released by calling a non-array deallocation function ([basic.stc.dynamic.deallocation]).
If destroy is called for a coroutine that is not suspended, the program has undefined behavior.
The deallocation function's name is looked up by searching for it in the scope of the promise type.
If nothing is found, a search is performed in the global scope.
If both a usual deallocation function with only a pointer parameter and a usual deallocation function with both a pointer parameter and a size parameter are found, then the selected deallocation function shall be the one with two parameters.
Otherwise, the selected deallocation function shall be the function with one parameter.
If no usual deallocation function is found, the program is ill-formed.
The selected deallocation function shall be called with the address of the block of storage to be reclaimed as its first argument.
If a deallocation function with a parameter of type std​::​size_t is used, the size of the block is passed as the corresponding argument.
When a coroutine is invoked, after initializing its parameters ([expr.call]), a copy is created for each coroutine parameter.
For a parameter of type cv T, the copy is a variable of type cv T with automatic storage duration that is direct-initialized from an xvalue of type T referring to the parameter.
[Note 2: 
An original parameter object is never a const or volatile object ([basic.type.qualifier]).
— end note]
The initialization and destruction of each parameter copy occurs in the context of the called coroutine.
Initializations of parameter copies are sequenced before the call to the coroutine promise constructor and indeterminately sequenced with respect to each other.
The lifetime of parameter copies ends immediately after the lifetime of the coroutine promise object ends.
[Note 3: 
If a coroutine has a parameter passed by reference, resuming the coroutine after the lifetime of the entity referred to by that parameter has ended is likely to result in undefined behavior.
— end note]
If the evaluation of the expression promise.unhandled_exception() exits via an exception, the coroutine is considered suspended at the final suspend point and the exception propagates to the caller or resumer.
The expression co_await promise.final_suspend() shall not be potentially-throwing ([except.spec]).

9.6 Structured binding declarations [dcl.struct.bind]

A structured binding declaration introduces the identifiers , , of the sb-identifier-list as names.
An sb-identifier that contains an ellipsis introduces a structured binding pack ([temp.variadic]).
A structured binding is either an sb-identifier that does not contain an ellipsis or an element of a structured binding pack.
The optional attribute-specifier-seq of an sb-identifier appertains to the associated structured bindings.
Let cv denote the cv-qualifiers in the decl-specifier-seq and S consist of each decl-specifier of the decl-specifier-seq that is constexpr, constinit, or a storage-class-specifier.
A cv that includes volatile is deprecated; see [depr.volatile.type].
First, a variable with a unique name e is introduced.
If the assignment-expression in the initializer has array type cv1 A and no ref-qualifier is present, e is defined by
attribute-specifier-seq S cv A e ;
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
Otherwise, e is defined as-if by where the declaration is never interpreted as a function declaration and the parts of the declaration other than the declarator-id are taken from the corresponding structured binding declaration.
The type of the id-expression e is called E.
[Note 1: 
E is never a reference type ([expr.prop]).
— end note]
The structured binding size of E, as defined below, is the number of structured bindings that need to be introduced by the structured binding declaration.
If there is no structured binding pack, then the number of elements in the sb-identifier-list shall be equal to the structured binding size of E.
Otherwise, the number of non-pack elements shall be no more than the structured binding size of E; the number of elements of the structured binding pack is the structured binding size of E less the number of non-pack elements in thesb-identifier-list.
Let denote the structured binding in the structured binding declaration after expanding the structured binding pack, if any.
[Note 2: 
If there is no structured binding pack, then denotes .
— end note]
[Example 1: struct C { int x, y, z; }; template<class T> void now_i_know_my() { auto [a, b, c] = C(); // OK, is a, is b, and is c auto [d, ...e] = C(); // OK, is d, the pack e contains two structured bindings: and auto [...f, g] = C(); // OK, the pack f contains two structured bindings: and , and is g auto [h, i, j, ...k] = C(); // OK, the pack k is empty auto [l, m, n, o, ...p] = C(); // error: structured binding size is too small } — end example]
If a structured binding declaration appears as a condition, the decision variable ([stmt.pre]) of the condition is e.
If the initializer refers to one of the names introduced by the structured binding declaration, the program is ill-formed.
If E is an array type with element type T, the structured binding size of E is equal to the number of elements of E.
Each is the name of an lvalue that refers to the element i of the array and whose type is T; the referenced type is T.
[Note 3: 
The top-level cv-qualifiers of T are cv.
— end note]
[Example 2: auto f() -> int(&)[2]; auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return value auto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return value auto g() -> int(&)[4]; template<size_t N> void h(int (&arr)[N]) { auto [a, ...b, c] = arr; // a names the first element of the array, b is a pack referring to the second and // third elements, and c names the fourth element auto& [...e] = arr; // e is a pack referring to the four elements of the array } void call_h() { h(g()); } — end example]
Otherwise, if the qualified-id std​::​tuple_size<E> names a complete class type with a member named value, the expression std​::​tuple_size<E>​::​value shall be a well-formed integral constant expression and the structured binding size of E is equal to the value of that expression.
Let i be an index prvalue of type std​::​size_t corresponding to .
If a search for the name get in the scope of E ([class.member.lookup]) finds at least one declaration that is a function template whose first template parameter is a non-type parameter, the initializer is e.get<i>().
Otherwise, the initializer is get<i>(e), where get undergoes argument-dependent lookup ([basic.lookup.argdep]).
In either case, get<i> is interpreted as a template-id.
[Note 4: 
Ordinary unqualified lookup is not performed.
— end note]
In either case, e is an lvalue if the type of the entity e is an lvalue reference and an xvalue otherwise.
Given the type designated by std​::​tuple_element<i, E>​::​type and the type designated by either & or &&, where is an lvalue reference if the initializer is an lvalue and an rvalue reference otherwise, variables are introduced with unique names as follows:
S U r = initializer ;
Each is the name of an lvalue of type that refers to the object bound to ; the referenced type is .
The initialization of e and any conversion of e considered as a decision variable ([stmt.pre]) is sequenced before the initialization of any .
The initialization of each is sequenced before the initialization of any where .
Otherwise, all of E's non-static data members shall be direct members of E or of the same base class of E, well-formed when named as e.name in the context of the structured binding, E shall not have an anonymous union member, and the structured binding size of E is equal to the number of non-static data members of E.
Designating the non-static data members of E as , , (in declaration order), each is the name of an lvalue that refers to the member m of e and whose type is that of e. ([expr.ref]); the referenced type is the declared type of if that type is a reference type, or the type of e. otherwise.
The lvalue is a bit-field if that member is a bit-field.
[Example 3: struct S { mutable int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f();
The type of the id-expression x is “int”, the type of the id-expression y is “const volatile double.
— end example]

9.7 Enumerations [enum]

9.7.1 Enumeration declarations [dcl.enum]

An enumeration is a distinct type ([basic.compound]) with named constants.
Its name becomes an enum-name within its scope.
enum-key:
enum
enum class
enum struct
The optional attribute-specifier-seq in the enum-head and the opaque-enum-declaration appertains to the enumeration; the attributes in that attribute-specifier-seq are thereafter considered attributes of the enumeration whenever it is named.
A : following “enum nested-name-specifier identifier” within the decl-specifier-seq of a member-declaration is parsed as part of an enum-base.
[Note 1: 
This resolves a potential ambiguity between the declaration of an enumeration with an enum-base and the declaration of an unnamed bit-field of enumeration type.
[Example 1: struct S { enum E : int {}; enum E : int {}; // error: redeclaration of enumeration }; — end example]
— end note]
The identifier in an enum-head-name is not looked up and is introduced by the enum-specifier or opaque-enum-declaration.
If the enum-head-name of an opaque-enum-declaration contains a nested-name-specifier, the declaration shall be an explicit specialization.
The enumeration type declared with an enum-key of only enum is an unscoped enumeration, and its enumerators are unscoped enumerators.
The enum-keys enum class and enum struct are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators.
The optional enum-head-name shall not be omitted in the declaration of a scoped enumeration.
The type-specifier-seq of an enum-base shall name an integral type; any cv-qualification is ignored.
An opaque-enum-declaration declaring an unscoped enumeration shall not omit the enum-base.
The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required.
The same identifier shall not appear as the name of multiple enumerators in an enumerator-list.
An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression.
An enumerator-definition without = gives the associated enumerator the value zero if it is the first enumerator-definition, and the value of the previous enumerator increased by one otherwise.
[Example 2: 
enum { a, b, c=0 }; enum { d, e, f=e+2 }; defines a, c, and d to be zero, b and e to be 1, and f to be 3.
— end example]
The optional attribute-specifier-seq in an enumerator appertains to that enumerator.
An opaque-enum-declaration is either a redeclaration of an enumeration in the current scope or a declaration of a new enumeration.
[Note 2: 
An enumeration declared by an opaque-enum-declaration has a fixed underlying type and is a complete type.
The list of enumerators can be provided in a later redeclaration with an enum-specifier.
— end note]
A scoped enumeration shall not be later redeclared as unscoped or with a different underlying type.
An unscoped enumeration shall not be later redeclared as scoped and each redeclaration shall include an enum-base specifying the same underlying type as in the original declaration.
If an enum-head-name contains a nested-name-specifier, the enclosing enum-specifier or opaque-enum-declaration D shall not inhabit a class scope and shall correspond to one or more declarations nominable in the class, class template, or namespace to which the nested-name-specifier refers ([basic.scope.scope]).
All those declarations shall have the same target scope; the target scope of D is that scope.
Each enumeration defines a type that is different from all other types.
Each enumeration also has an underlying type.
The underlying type can be explicitly specified using an enum-base.
For a scoped enumeration type, the underlying type is int if it is not explicitly specified.
In both of these cases, the underlying type is said to be fixed.
Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration.
If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definition shall be a converted constant expression of the underlying type.
If the underlying type is not fixed, the type of each enumerator prior to the closing brace is determined as follows:
  • If an initializer is specified for an enumerator, the constant-expression shall be an integral constant expression.
    If the expression has unscoped enumeration type, the enumerator has the underlying type of that enumeration type, otherwise it has the same type as the expression.
  • If no initializer is specified for the first enumerator, its type is an unspecified signed integral type.
  • Otherwise the type of the enumerator is the same as that of the preceding enumerator unless the incremented value is not representable in that type, in which case the type is an unspecified integral type sufficient to contain the incremented value.
    If no such type exists, the program is ill-formed.
An enumeration whose underlying type is fixed is an incomplete type until immediately after its enum-base (if any), at which point it becomes a complete type.
An enumeration whose underlying type is not fixed is an incomplete type until the closing } of its enum-specifier, at which point it becomes a complete type.
For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration.
If no integral type can represent all the enumerator values, the enumeration is ill-formed.
It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.
If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.
For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type.
Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width M such that all enumerators can be represented.
The width of the smallest bit-field large enough to hold all the values of the enumeration type is M.
It is possible to define an enumeration that has values not defined by any of its enumerators.
If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.82
An enumeration has the same size, value representation, and alignment requirements ([basic.align]) as its underlying type.
Furthermore, each value of an enumeration has the same representation as the corresponding value of the underlying type.
Two enumeration types are layout-compatible enumerations if they have the same underlying type.
The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion.
[Example 3: 
enum color { red, yellow, green=20, blue }; color col = red; color* cp = &col; if (*cp == blue) // ... makes color a type describing various colors, and then declares col as an object of that type, and cp as a pointer to an object of that type.
The possible values of an object of type color are red, yellow, green, blue; these values can be converted to the integral values 0, 1, 20, and 21.
Since enumerations are distinct types, objects of type color can be assigned only values of type color.
color c = 1; // error: type mismatch, no conversion from int to color int i = yellow; // OK, yellow converted to integral value 1, integral promotion
Note that this implicit enum to int conversion is not provided for a scoped enumeration: enum class Col { red, yellow, green }; int x = Col::red; // error: no Col to int conversion Col y = Col::red; if (y) { } // error: no Col to bool conversion
— end example]
The name of each unscoped enumerator is also bound in the scope that immediately contains the enum-specifier.
An unnamed enumeration that does not have a typedef name for linkage purposes ([dcl.typedef]) and that has a first enumerator is denoted, for linkage purposes ([basic.link]), by its underlying type and its first enumerator; such an enumeration is said to have an enumerator as a name for linkage purposes.
[Note 3: 
Each unnamed enumeration with no enumerators is a distinct type.
— end note]
[Example 4: enum direction { left='l', right='r' }; void g() { direction d; // OK d = left; // OK d = direction::right; // OK } enum class altitude { high='h', low='l' }; void h() { altitude a; // OK a = high; // error: high not in scope a = altitude::low; // OK } — end example]
82)82)
This set of values is used to define promotion and conversion semantics for the enumeration type.
It does not preclude an expression of enumeration type from having a value that falls outside this range.

9.7.2 The using enum declaration [enum.udecl]

A using-enum-declarator names the set of declarations found by type-only lookup ([basic.lookup.general]) for the using-enum-declarator ([basic.lookup.unqual], [basic.lookup.qual]).
The using-enum-declarator shall designate a non-dependent type with a reachable enum-specifier.
[Example 1: enum E { x }; void f() { int E; using enum E; // OK } using F = E; using enum F; // OK template<class T> using EE = T; void g() { using enum EE<E>; // OK } — end example]
A using-enum-declaration is equivalent to a using-declaration for each enumerator.
[Note 1: 
A using-enum-declaration in class scope makes the enumerators of the named enumeration available via member lookup.
[Example 2: enum class fruit { orange, apple }; struct S { using enum fruit; // OK, introduces orange and apple into S }; void f() { S s; s.orange; // OK, names fruit​::​orange S::orange; // OK, names fruit​::​orange } — end example]
— end note]
[Note 2: 
Two using-enum-declarations that introduce two enumerators of the same name conflict.
[Example 3: enum class fruit { orange, apple }; enum class color { red, orange }; void f() { using enum fruit; // OK using enum color; // error: color​::​orange and fruit​::​orange conflict } — end example]
— end note]

9.8 Namespaces [basic.namespace]

9.8.1 General [basic.namespace.general]

A namespace is an optionally-named entity whose scope can contain declarations of any kind of entity.
The name of a namespace can be used to access entities that belong to that namespace; that is, the members of the namespace.
Unlike other entities, the definition of a namespace can be split over several parts of one or more translation units and modules.
[Note 1: 
A namespace-definition is exported if it contains any export-declarations ([module.interface]).
A namespace is never attached to a named module and never has a name with module linkage.
— end note]
[Example 1: export module M; namespace N1 {} // N1 is not exported export namespace N2 {} // N2 is exported namespace N3 { export int n; } // N3 is exported — end example]
There is a global namespace with no declaration; see [basic.scope.namespace].
The global namespace belongs to the global scope; it is not an unnamed namespace ([namespace.unnamed]).
[Note 2: 
Lacking a declaration, it cannot be found by name lookup.
— end note]

9.8.2 Namespace definition [namespace.def]

9.8.2.1 General [namespace.def.general]

Every namespace-definition shall inhabit a namespace scope ([basic.scope.namespace]).
In a named-namespace-definition D, the identifier is the name of the namespace.
The identifier is looked up by searching for it in the scopes of the namespace A in which D appears and of every element of the inline namespace set of A.
If the lookup finds a namespace-definition for a namespace N, D extends N, and the target scope of D is the scope to which N belongs.
If the lookup finds nothing, the identifier is introduced as a namespace-name into A.
Because a namespace-definition contains declarations in its namespace-body and a namespace-definition is itself a declaration, it follows that namespace-definitions can be nested.
[Example 1: namespace Outer { int i; namespace Inner { void f() { i++; } // Outer​::​i int i; void g() { i++; } // Inner​::​i } } — end example]
If the optional initial inline keyword appears in a namespace-definition for a particular namespace, that namespace is declared to be an inline namespace.
The inline keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definition that initially declared the namespace-name for that namespace.
The optional attribute-specifier-seq in a named-namespace-definition appertains to the namespace being defined or extended.
Members of an inline namespace can be used in most respects as though they were members of the innermost enclosing namespace.
Specifically, the inline namespace and its enclosing namespace are both added to the set of associated namespaces used in argument-dependent lookup whenever one of them is, and a using-directive ([namespace.udir]) that names the inline namespace is implicitly inserted into the enclosing namespace as for an unnamed namespace ([namespace.unnamed]).
Furthermore, each member of the inline namespace can subsequently be partially specialized ([temp.spec.partial]), explicitly instantiated ([temp.explicit]), or explicitly specialized ([temp.expl.spec]) as though it were a member of the enclosing namespace.
Finally, looking up a name in the enclosing namespace via explicit qualification ([namespace.qual]) will include members of the inline namespace even if there are declarations of that name in the enclosing namespace.
These properties are transitive: if a namespace N contains an inline namespace M, which in turn contains an inline namespace O, then the members of O can be used as though they were members of M or N.
The inline namespace set of N is the transitive closure of all inline namespaces in N.
A nested-namespace-definition with an enclosing-namespace-specifier E, identifier I and namespace-body B is equivalent to namespace E { inline namespace I { B } } where the optional inline is present if and only if the identifier I is preceded by inline.
[Example 2: namespace A::inline B::C { int i; }
The above has the same effect as: namespace A { inline namespace B { namespace C { int i; } } }
— end example]

9.8.2.2 Unnamed namespaces [namespace.unnamed]

An unnamed-namespace-definition behaves as if it were replaced by
inline namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
where inline appears if and only if it appears in the unnamed-namespace-definition and all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit.
The optional attribute-specifier-seq in the unnamed-namespace-definition appertains to unique.
[Example 1: namespace { int i; } // unique​::​i void f() { i++; } // unique​::​i++ namespace A { namespace { int i; // A​::​unique​::​i int j; // A​::​unique​::​j } void g() { i++; } // A​::​unique​::​i++ } using namespace A; void h() { i++; // error: unique​::​i or A​::​unique​::​i A::i++; // A​::​unique​::​i j++; // A​::​unique​::​j } — end example]

9.8.3 Namespace alias [namespace.alias]

The identifier in a namespace-alias-definition becomes a namespace-alias and denotes the namespace denoted by the qualified-namespace-specifier.
[Note 1: 
When looking up a namespace-name in a namespace-alias-definition, only namespace names are considered, see [basic.lookup.udir].
— end note]

9.8.4 Using namespace directive [namespace.udir]

A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope.
[Note 1: 
When looking up a namespace-name in a using-directive, only namespace names are considered, see [basic.lookup.udir].
— end note]
The optional attribute-specifier-seq appertains to the using-directive.
[Note 2: 
A using-directive makes the names in the nominated namespace usable in the scope in which the using-directive appears after the using-directive ([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 using-directive and the nominated namespace.
— end note]
[Note 3: 
A using-directive does not introduce any names.
— end note]
[Example 1: namespace A { int i; namespace B { namespace C { int i; } using namespace A::B::C; void f1() { i = 5; // OK, C​::​i visible in B and hides A​::​i } } namespace D { using namespace B; using namespace C; void f2() { i = 5; // ambiguous, B​::​C​::​i or A​::​i? } } void f3() { i = 5; // uses A​::​i } } void f4() { i = 5; // error: neither i is visible } — end example]
[Note 4: 
A using-directive is transitive: if a scope contains a using-directive that nominates a namespace that itself contains using-directives, the namespaces nominated by those using-directives are also eligible to be considered.
— end note]
[Example 2: namespace M { int i; } namespace N { int i; using namespace M; } void f() { using namespace N; i = 7; // error: both M​::​i and N​::​i are visible }
For another example, namespace A { int i; } namespace B { int i; int j; namespace C { namespace D { using namespace A; int j; int k; int a = i; // B​::​i hides A​::​i } using namespace D; int k = 89; // no problem yet int l = k; // ambiguous: C​::​k or D​::​k int m = i; // B​::​i hides A​::​i int n = j; // D​::​j hides B​::​j } }
— end example]
[Note 5: 
Declarations in a namespace that appear after a using-directive for that namespace can be found through that using-directive after they appear.
— end note]
[Note 6: 
If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions or function templates, the use of the name is ill-formed ([basic.lookup]).
In particular, the name of a variable, function or enumerator does not hide the name of a class or enumeration declared in a different namespace.
For example, namespace A { class X { }; extern "C" int g(); extern "C++" int h(); } namespace B { void X(int); extern "C" int g(); extern "C++" int h(int); } using namespace A; using namespace B; void f() { X(1); // error: name X found in two namespaces g(); // OK, name g refers to the same entity h(); // OK, overload resolution selects A​::​h }
— end note]
[Note 7: 
The order in which namespaces are considered and the relationships among the namespaces implied by the using-directives do not affect overload resolution.
Neither is any function excluded because another has the same signature, even if one is in a namespace reachable through using-directives in the namespace of the other.83
— end note]
[Example 3: namespace D { int d1; void f(char); } using namespace D; int d1; // OK, no conflict with D​::​d1 namespace E { int e; void f(int); } namespace D { // namespace extension int d2; using namespace E; void f(int); } void f() { d1++; // error: ambiguous ​::​d1 or D​::​d1? ::d1++; // OK D::d1++; // OK d2++; // OK, D​::​d2 e++; // OK, E​::​e f(1); // error: ambiguous: D​::​f(int) or E​::​f(int)? f('a'); // OK, D​::​f(char) } — end example]
83)83)
During name lookup in a class hierarchy, some ambiguities can be resolved by considering whether one member hides the other along some paths ([class.member.lookup]).
There is no such disambiguation when considering the set of names found as a result of following using-directives.

9.9 The using declaration [namespace.udecl]

The component names of a using-declarator are those of its nested-name-specifier and unqualified-id.
Each using-declarator in a using-declaration84 names the set of declarations found by lookup ([basic.lookup.qual]) for the using-declarator, except that class and enumeration declarations that would be discarded are merely ignored when checking for ambiguity ([basic.lookup]), conversion function templates with a dependent return type are ignored, and certain functions are hidden as described below.
If the terminal name of the using-declarator is dependent ([temp.dep.type]), the using-declarator is considered to name a constructor if and only if the nested-name-specifier has a terminal name that is the same as the unqualified-id.
If the lookup in any instantiation finds that a using-declarator that is not considered to name a constructor does do so, or that a using-declarator that is considered to name a constructor does not, the program is ill-formed.
If the using-declarator names a constructor, it declares that the class inherits the named set of constructor declarations from the nominated base class.
[Note 1: 
Otherwise, the unqualified-id in the using-declarator is bound to the using-declarator, which is replaced during name lookup with the declarations it names ([basic.lookup]).
If such a declaration is of an enumeration, the names of its enumerators are not bound.
For the keyword typename, see [temp.res].
— end note]
In a using-declaration used as a member-declaration, each using-declarator shall either name an enumerator or have a nested-name-specifier naming a base class of the current class ([expr.prim.this]).
[Example 1: enum class button { up, down }; struct S { using button::up; button b = up; // OK }; — end example]
If a using-declarator names a constructor, its nested-name-specifier shall name a direct base class of the current class.
If the immediate (class) scope is associated with a class template, it shall derive from the specified base class or have at least one dependent base class.
[Example 2: struct B { void f(char); enum E { e }; union { int x; }; }; struct C { int f(); }; struct D : B { using B::f; // OK, B is a base of D using B::e; // OK, e is an enumerator of base B using B::x; // OK, x is a union member of base B using C::f; // error: C isn't a base of D void f(int) { f('c'); } // calls B​::​f(char) void g(int) { g('c'); } // recursively calls D​::​g(int) }; template <typename... bases> struct X : bases... { using bases::f...; }; X<B, C> x; // OK, B​::​f and C​::​f named — end example]
[Note 2: 
Since destructors do not have names, a using-declaration cannot refer to a destructor for a base class.
— end note]
If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator for the derived class ([class.copy.ctor], [class.copy.assign]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declared copy/move constructor or assignment operator of the derived class, as described below.
A using-declaration shall not name a template-id.
[Example 3: struct A { template <class T> void f(T); template <class T> struct X { }; }; struct B : A { using A::f<double>; // error using A::X<int>; // error }; — end example]
A using-declaration shall not name a namespace.
A using-declaration that names a class member other than an enumerator shall be a member-declaration.
[Example 4: struct X { int i; static int s; }; void f() { using X::i; // error: X​::​i is a class member and this is not a member declaration. using X::s; // error: X​::​s is a class member and this is not a member declaration. } — end example]
If a declaration is named by two using-declarators that inhabit the same class scope, the program is ill-formed.
[Example 5: struct C { int i; }; struct D1 : C { }; struct D2 : C { }; struct D3 : D1, D2 { using D1::i; // OK, equivalent to using C​::​i using D1::i; // error: duplicate using D2::i; // error: duplicate, also names C​::​i }; — end example]
[Note 3: 
A using-declarator whose nested-name-specifier names a namespace does not name declarations added to the namespace after it.
Thus, additional overloads added after the using-declaration are ignored, but default function arguments ([dcl.fct.default]), default template arguments ([temp.param]), and template specializations ([temp.spec.partial], [temp.expl.spec]) are considered.
— end note]
[Example 6: namespace A { void f(int); } using A::f; // f is a synonym for A​::​f; that is, for A​::​f(int). namespace A { void f(char); } void foo() { f('a'); // calls f(int), even though f(char) exists. } void bar() { using A::f; // f is a synonym for A​::​f; that is, for A​::​f(int) and A​::​f(char). f('a'); // calls f(char) } — end example]
If a declaration named by a using-declaration that inhabits the target scope of another declaration B potentially conflicts with it ([basic.scope.scope]), and either is reachable from the other, the program is ill-formed unless B is name-independent and the using-declaration precedes B.
[Example 7: int _; void f() { int _; // B _ = 0; using ::_; // error: using-declaration does not precede B } — end example]
If two declarations named by using-declarations that inhabit the same scope potentially conflict, either is reachable from the other, and they do not both declare functions or function templates, the program is ill-formed.
[Note 4: 
Overload resolution possibly cannot distinguish between conflicting function declarations.
— end note]
[Example 8: namespace A { int x; int f(int); int g; void h(); } namespace B { int i; struct g { }; struct x { }; void f(int); void f(double); void g(char); // OK, hides struct g } void func() { int i; using B::i; // error: conflicts void f(char); using B::f; // OK, each f is a function using A::f; // OK, but interferes with B​::​f(int) f(1); // error: ambiguous static_cast<int(*)(int)>(f)(1); // OK, calls A​::​f f(3.5); // calls B​::​f(double) using B::g; g('a'); // calls B​::​g(char) struct g g1; // g1 has class type B​::​g using A::g; // error: conflicts with B​::​g void h(); using A::h; // error: conflicts using B::x; using A::x; // OK, hides struct B​::​x using A::x; // OK, does not conflict with previous using A​::​x x = 99; // assigns to A​::​x struct x x1; // x1 has class type B​::​x } — end example]
The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that correspond to (and thus would conflict with) a declaration of a function or function template in C.
[Example 9: struct B { virtual void f(int); virtual void f(char); void g(int); void h(int); }; struct D : B { using B::f; void f(int); // OK, D​::​f(int) overrides B​::​f(int); using B::g; void g(char); // OK using B::h; void h(int); // OK, D​::​h(int) hides B​::​h(int) }; void k(D* p) { p->f(1); // calls D​::​f(int) p->f('a'); // calls B​::​f(char) p->g(1); // calls B​::​g(int) p->g('a'); // calls D​::​g(char) } struct B1 { B1(int); }; struct B2 { B2(int); }; struct D1 : B1, B2 { using B1::B1; using B2::B2; }; D1 d1(0); // error: ambiguous struct D2 : B1, B2 { using B1::B1; using B2::B2; D2(int); // OK, D2​::​D2(int) hides B1​::​B1(int) and B2​::​B2(int) }; D2 d2(0); // calls D2​::​D2(int) — end example]
[Note 5: 
For the purpose of forming a set of candidates during overload resolution, the functions named by a using-declaration in a derived class are treated as though they were direct members of the derived class.
In particular, the implicit object parameter is treated as if it were a reference to the derived class rather than to the base class ([over.match.funcs]).
This has no effect on the type of the function, and in all other respects the function remains part of the base class.
— end note]
Constructors that are named by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class ([class.qual]) or forming a set of overload candidates ([over.match.ctor], [over.match.copy], [over.match.list]).
[Note 6: 
If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class from which the constructor originated are implicitly initialized ([class.inhctor.init]).
A constructor of a derived class is sometimes preferred to a constructor of a base class if they would otherwise be ambiguous ([over.match.best]).
— end note]
In a using-declarator that does not name a constructor, every declaration named shall be accessible.
In a using-declarator that names a constructor, no access check is performed.
[Note 7: 
Because a using-declarator designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declarator cannot be used to resolve inherited member ambiguities.
[Example 10: struct A { int x(); }; struct B : A { }; struct C : A { using A::x; int x(int); }; struct D : B, C { using C::x; int x(double); }; int f(D* d) { return d->x(); // error: overload resolution selects A​::​x, but A is an ambiguous base class } — end example]
— end note]
A using-declaration has the usual accessibility for a member-declaration.
Base-class constructors considered because of a using-declarator are accessible if they would be accessible when used to construct an object of the base class; the accessibility of the using-declaration is ignored.
[Example 11: class A { private: void f(char); public: void f(int); protected: void g(); }; class B : public A { using A::f; // error: A​::​f(char) is inaccessible public: using A::g; // B​::​g is a public synonym for A​::​g }; — end example]
84)84)
A using-declaration with more than one using-declarator is equivalent to a corresponding sequence of using-declarations with one using-declarator each.

9.10 The asm declaration [dcl.asm]

An asm declaration has the form
The asm declaration is conditionally-supported; any restrictions on the balanced-token-seq and its meaning are implementation-defined.
The optional attribute-specifier-seq in an asm-declaration appertains to the asm declaration.
[Note 1: 
Typically it is used to pass information through the implementation to an assembler.
— end note]

9.12 Attributes [dcl.attr]

9.12.1 Attribute syntax and semantics [dcl.attr.grammar]

If an attribute-specifier contains an attribute-using-prefix, the attribute-list following that attribute-using-prefix shall not contain an attribute-scoped-token and every attribute-token in that attribute-list is treated as if its identifier were prefixed with N​::​, where N is the attribute-namespace specified in the attribute-using-prefix.
[Note 1: 
This rule imposes no constraints on how an attribute-using-prefix affects the tokens in an attribute-argument-clause.
— end note]
[Example 1: [[using CC: opt(1), debug]] // same as [[CC​::​opt(1), CC​::​debug]] void f() {} [[using CC: opt(1)]] [[CC::debug]] // same as [[CC​::​opt(1)]] [[CC​::​debug]] void g() {} [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute token void h() {} — end example]
[Note 2: 
For each individual attribute, the form of the balanced-token-seq will be specified.
— end note]
In an attribute-list, an ellipsis may appear only if that attribute's specification permits it.
An attribute followed by an ellipsis is a pack expansion.
An attribute-specifier that contains no attributes has no effect.
The order in which the attribute-tokens appear in an attribute-list is not significant.
If a keyword or an alternative token that satisfies the syntactic requirements of an identifier ([lex.name]) is contained in an attribute-token, it is considered an identifier.
No name lookup is performed on any of the identifiers contained in an attribute-token.
The attribute-token determines additional requirements on the attribute-argument-clause (if any).
Each attribute-specifier-seq is said to appertain to some entity or statement, identified by the syntactic context where it appears ([stmt.stmt], [dcl.dcl], [dcl.decl]).
If an attribute-specifier-seq that appertains to some entity or statement contains an attribute or alignment-specifier that is not allowed to apply to that entity or statement, the program is ill-formed.
If an attribute-specifier-seq appertains to a friend declaration ([class.friend]), that declaration shall be a definition.
[Note 3: 
An attribute-specifier-seq cannot appertain to an explicit instantiation ([temp.explicit]).
— end note]
For an attribute-token (including an attribute-scoped-token) not specified in this document, the behavior is implementation-defined; any such attribute-token that is not recognized by the implementation is ignored.
[Note 4: 
A program is ill-formed if it contains an attribute specified in [dcl.attr] that violates the rules specifying to which entity or statement the attribute can apply or the syntax rules for the attribute's attribute-argument-clause, if any.
— end note]
[Note 5: 
The attributes specified in [dcl.attr] have optional semantics: given a well-formed program, removing all instances of any one of those attributes results in a program whose set of possible executions ([intro.abstract]) for a given input is a subset of those of the original program for the same input, absent implementation-defined guarantees with respect to that attribute.
— end note]
An attribute-token is reserved for future standardization if
Each implementation should choose a distinctive name for the attribute-namespace in an attribute-scoped-token.
Two consecutive left square bracket tokens shall appear only when introducing an attribute-specifier or within the balanced-token-seq of an attribute-argument-clause.
[Note 6: 
If two consecutive left square brackets appear where an attribute-specifier is not allowed, the program is ill-formed even if the brackets match an alternative grammar production.
— end note]
[Example 2: int p[10]; void f() { int x = 42, y[5]; int(p[[x] { return x; }()]); // error: invalid attribute on a nested declarator-id and // not a function-style cast of an element of p. y[[] { return 2; }()] = 2; // error even though attributes are not allowed in this context. int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute. } — end example]

9.12.2 Alignment specifier [dcl.align]

An alignment-specifier may be applied to a variable or to a class data member, but it shall not be applied to a bit-field, a function parameter, or an exception-declaration ([except.handle]).
An alignment-specifier may also be applied to the declaration of a class (in an elaborated-type-specifier ([dcl.type.elab]) or class-head ([class]), respectively).
An alignment-specifier with an ellipsis is a pack expansion ([temp.variadic]).
When the alignment-specifier is of the form alignas( constant-expression ):
  • the constant-expression shall be an integral constant expression
  • if the constant expression does not evaluate to an alignment value ([basic.align]), or evaluates to an extended alignment and the implementation does not support that alignment in the context of the declaration, the program is ill-formed.
An alignment-specifier of the form alignas( type-id ) has the same effect as alignas(alignof( type-id )).
The alignment requirement of an entity is the strictest nonzero alignment specified by its alignment-specifiers, if any; otherwise, the alignment-specifiers have no effect.
The combined effect of all alignment-specifiers in a declaration shall not specify an alignment that is less strict than the alignment that would be required for the entity being declared if all alignment-specifiers appertaining to that entity were omitted.
[Example 1: struct alignas(8) S {}; struct alignas(1) U { S s; }; // error: U specifies an alignment that is less strict than if the alignas(1) were omitted. — end example]
If the defining declaration of an entity has an alignment-specifier, any non-defining declaration of that entity shall either specify equivalent alignment or have no alignment-specifier.
Conversely, if any declaration of an entity has an alignment-specifier, every defining declaration of that entity shall specify an equivalent alignment.
No diagnostic is required if declarations of an entity have different alignment-specifiers in different translation units.
[Example 2: // Translation unit #1: struct S { int x; } s, *p = &s; // Translation unit #2: struct alignas(16) S; // ill-formed, no diagnostic required: definition of S lacks alignment extern S* p; — end example]
[Example 3: 
An aligned buffer with an alignment requirement of A and holding N elements of type T can be declared as: alignas(T) alignas(A) T buffer[N];
Specifying alignas(T) ensures that the final requested alignment will not be weaker than alignof(T), and therefore the program will not be ill-formed.
— end example]
[Example 4: alignas(double) void f(); // error: alignment applied to function alignas(double) unsigned char c[sizeof(double)]; // array of characters, suitably aligned for a double extern unsigned char c[sizeof(double)]; // no alignas necessary alignas(float) extern unsigned char c[sizeof(double)]; // error: different alignment in declaration — end example]

9.12.3 Assumption attribute [dcl.attr.assume]

The attribute-token assume may be applied to a null statement; such a statement is an assumption.
An attribute-argument-clause shall be present and shall have the form: The expression is contextually converted to bool ([conv.general]).
The expression is not evaluated.
If the converted expression would evaluate to true at the point where the assumption appears, the assumption has no effect.
Otherwise, evaluation of the assumption has runtime-undefined behavior.
[Note 1: 
The expression is potentially evaluated ([basic.def.odr]).
The use of assumptions is intended to allow implementations to analyze the form of the expression and deduce information used to optimize the program.
Implementations are not required to deduce any information from any particular assumption.
It is expected that the value of a has-attribute-expression for the assume attribute is 0 if an implementation does not attempt to deduce any such information from assumptions.
— end note]
[Example 1: int divide_by_32(int x) { [[assume(x >= 0)]]; return x/32; // The instructions produced for the division // may omit handling of negative values. } int f(int y) { [[assume(++y == 43)]]; // y is not incremented return y; // statement may be replaced with return 42; } — end example]

9.12.4 Carries dependency attribute [dcl.attr.depend]

The attribute-token carries_dependency specifies dependency propagation into and out of functions.
No attribute-argument-clause shall be present.
The attribute may be applied to a parameter of a function or lambda, in which case it specifies that the initialization of the parameter carries a dependency to ([intro.multithread]) each lvalue-to-rvalue conversion ([conv.lval]) of that object.
The attribute may also be applied to a function or a lambda call operator, in which case it specifies that the return value, if any, carries a dependency to the evaluation of the function call expression.
The first declaration of a function shall specify the carries_dependency attribute for its declarator-id if any declaration of the function specifies the carries_dependency attribute.
Furthermore, the first declaration of a function shall specify the carries_dependency attribute for a parameter if any declaration of that function specifies the carries_dependency attribute for that parameter.
If a function or one of its parameters is declared with the carries_dependency attribute in its first declaration in one translation unit and the same function or one of its parameters is declared without the carries_dependency attribute in its first declaration in another translation unit, the program is ill-formed, no diagnostic required.
[Note 1: 
The carries_dependency attribute does not change the meaning of the program, but might result in generation of more efficient code.
— end note]
[Example 1: /* Translation unit A. */ struct foo { int* a; int* b; }; std::atomic<struct foo *> foo_head[10]; int foo_array[10][10]; [[carries_dependency]] struct foo* f(int i) { return foo_head[i].load(memory_order::consume); } int g(int* x, int* y [[carries_dependency]]) { return kill_dependency(foo_array[*x][*y]); } /* Translation unit B. */ [[carries_dependency]] struct foo* f(int i); int g(int* x, int* y [[carries_dependency]]); int c = 3; void h(int i) { struct foo* p; p = f(i); do_something_with(g(&c, p->a)); do_something_with(g(p->a, &c)); }
The carries_dependency attribute on function f means that the return value carries a dependency out of f, so that the implementation need not constrain ordering upon return from f.
Implementations of f and its caller may choose to preserve dependencies instead of emitting hardware memory ordering instructions (a.k.a. fences).
Function g's second parameter has a carries_dependency attribute, but its first parameter does not.
Therefore, function h's first call to g carries a dependency into g, but its second call does not.
The implementation might need to insert a fence prior to the second call to g.
— end example]

9.12.5 Deprecated attribute [dcl.attr.deprecated]

The attribute-token deprecated can be used to mark names and entities whose use is still allowed, but is discouraged for some reason.
[Note 1: 
In particular, deprecated is appropriate for names and entities that are deemed obsolescent or unsafe.
— end note]
An attribute-argument-clause may be present and, if present, it shall have the form:
[Note 2: 
The unevaluated-string in the attribute-argument-clause can be used to explain the rationale for deprecation and/or to suggest a replacing entity.
— end note]
The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, a namespace, an enumeration, an enumerator, a concept, or a template specialization.
An entity declared without the deprecated attribute can later be redeclared with the attribute and vice-versa.
[Note 3: 
Thus, an entity initially declared without the attribute can be marked as deprecated by a subsequent redeclaration.
However, after an entity is marked as deprecated, later redeclarations do not un-deprecate the entity.
— end note]
Redeclarations using different forms of the attribute (with or without the attribute-argument-clause or with different attribute-argument-clauses) are allowed.
Recommended practice: Implementations should use the deprecated attribute to produce a diagnostic message in case the program refers to a name or entity other than to declare it, after a declaration that specifies the attribute.
The diagnostic message should include the text provided within the attribute-argument-clause of any deprecated attribute applied to the name or entity.
The value of a has-attribute-expression for the deprecated attribute should be 0 unless the implementation can issue such diagnostic messages.

9.12.6 Fallthrough attribute [dcl.attr.fallthrough]

The attribute-token fallthrough may be applied to a null statement; such a statement is a fallthrough statement.
No attribute-argument-clause shall be present.
A fallthrough statement may only appear within an enclosing switch statement ([stmt.switch]).
The next statement that would be executed after a fallthrough statement shall be a labeled statement whose label is a case label or default label for the same switch statement and, if the fallthrough statement is contained in an iteration statement, the next statement shall be part of the same execution of the substatement of the innermost enclosing iteration statement.
The program is ill-formed if there is no such statement.
Recommended practice: The use of a fallthrough statement should suppress a warning that an implementation might otherwise issue for a case or default label that is reachable from another case or default label along some path of execution.
The value of a has-attribute-expression for the fallthrough attribute should be 0 if the attribute does not cause suppression of such warnings.
Implementations should issue a warning if a fallthrough statement is not dynamically reachable.
[Example 1: void f(int n) { void g(), h(), i(); switch (n) { case 1: case 2: g(); [[fallthrough]]; case 3: // warning on fallthrough discouraged do { [[fallthrough]]; // error: next statement is not part of the same substatement execution } while (false); case 6: do { [[fallthrough]]; // error: next statement is not part of the same substatement execution } while (n--); case 7: while (false) { [[fallthrough]]; // error: next statement is not part of the same substatement execution } case 5: h(); case 4: // implementation may warn on fallthrough i(); [[fallthrough]]; // error } } — end example]

9.12.7 Indeterminate storage [dcl.attr.indet]

The attribute-token indeterminate may be applied to the definition of a block variable with automatic storage duration or to a parameter-declaration of a function declaration.
No attribute-argument-clause shall be present.
The attribute specifies that the storage of an object with automatic storage duration is initially indeterminate rather than erroneous ([basic.indet]).
If a function parameter is declared with the indeterminate attribute, it shall be so declared in the first declaration of its function.
If a function parameter is declared with the indeterminate attribute in the first declaration of its function in one translation unit and the same function is declared without the indeterminate attribute on the same parameter in its first declaration in another translation unit, the program is ill-formed, no diagnostic required.
[Note 1: 
Reading from an uninitialized variable that is marked [[indeterminate]] can cause undefined behavior.
void f(int); void g() { int x [[indeterminate]], y; f(y); // erroneous behavior ([basic.indet]) f(x); // undefined behavior } struct T { T() {} int x; }; int h(T t [[indeterminate]]) { f(t.x); // undefined behavior when called below return 0; } int _ = h(T()); — end note]

9.12.8 Likelihood attributes [dcl.attr.likelihood]

The attribute-tokens likely and unlikely may be applied to labels or statements.
No attribute-argument-clause shall be present.
The attribute-token likely shall not appear in an attribute-specifier-seq that contains the attribute-token unlikely.
[Note 1: 
The use of the likely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more likely than any alternative path of execution that does not include such an attribute on a statement or label.
The use of the unlikely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more unlikely than any alternative path of execution that does not include such an attribute on a statement or label.
It is expected that the value of a has-attribute-expression for the likely and unlikely attributes is 0 if the implementation does not attempt to use these attributes for such optimizations.
A path of execution includes a label if and only if it contains a jump to that label.
— end note]
[Note 2: 
Excessive usage of either of these attributes is liable to result in performance degradation.
— end note]
[Example 1: void g(int); int f(int n) { if (n > 5) [[unlikely]] { // n > 5 is considered to be arbitrarily unlikely g(0); return n * 2 + 1; } switch (n) { case 1: g(1); [[fallthrough]]; [[likely]] case 2: // n == 2 is considered to be arbitrarily more g(2); // likely than any other value of n break; } return 3; } — end example]

9.12.9 Maybe unused attribute [dcl.attr.unused]

The attribute-token maybe_unused indicates that a name, label, or entity is possibly intentionally unused.
No attribute-argument-clause shall be present.
The attribute may be applied to the declaration of a class, typedef-name, variable (including a structured binding declaration), structured binding, non-static data member, function, enumeration, or enumerator, or to an identifier label ([stmt.label]).
A name or entity declared without the maybe_unused attribute can later be redeclared with the attribute and vice versa.
An entity is considered marked after the first declaration that marks it.
Recommended practice: For an entity marked maybe_unused, implementations should not emit a warning that the entity or its structured bindings (if any) are used or unused.
For a structured binding declaration not marked maybe_unused, implementations should not emit such a warning unless all of its structured bindings are unused.
For a label to which maybe_unused is applied, implementations should not emit a warning that the label is used or unused.
The value of a has-attribute-expression for the maybe_unused attribute should be 0 if the attribute does not cause suppression of such warnings.
[Example 1: [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); #ifdef NDEBUG goto x; #endif [[maybe_unused]] x: }
Implementations should not warn that b or x is unused, whether or not NDEBUG is defined.
— end example]

9.12.10 Nodiscard attribute [dcl.attr.nodiscard]

The attribute-token nodiscard may be applied to a function or a lambda call operator or to the declaration of a class or enumeration.
An attribute-argument-clause may be present and, if present, shall have the form:
A name or entity declared without the nodiscard attribute can later be redeclared with the attribute and vice-versa.
[Note 1: 
Thus, an entity initially declared without the attribute can be marked as nodiscard by a subsequent redeclaration.
However, after an entity is marked as nodiscard, later redeclarations do not remove the nodiscard from the entity.
— end note]
Redeclarations using different forms of the attribute (with or without the attribute-argument-clause or with different attribute-argument-clauses) are allowed.
A nodiscard type is a (possibly cv-qualified) class or enumeration type marked nodiscard in a reachable declaration.
A nodiscard call is either
  • a function call expression ([expr.call]) that calls a function declared nodiscard in a reachable declaration or whose return type is a nodiscard type, or
  • an explicit type conversion ([expr.type.conv], [expr.static.cast], [expr.cast]) that constructs an object through a constructor declared nodiscard in a reachable declaration, or that initializes an object of a nodiscard type.
Recommended practice: Appearance of a nodiscard call as a potentially-evaluated discarded-value expression ([expr.prop]) is discouraged unless explicitly cast to void.
Implementations should issue a warning in such cases.
The value of a has-attribute-expression for the nodiscard attribute should be 0 unless the implementation can issue such warnings.
[Note 2: 
This is typically because discarding the return value of a nodiscard call has surprising consequences.
— end note]
The unevaluated-string in a nodiscard attribute-argument-clause should be used in the message of the warning as the rationale for why the result should not be discarded.
[Example 1: struct [[nodiscard]] my_scopeguard { /* ... */ }; struct my_unique { my_unique() = default; // does not acquire resource [[nodiscard]] my_unique(int fd) { /* ... */ } // acquires resource ~my_unique() noexcept { /* ... */ } // releases resource, if any /* ... */ }; struct [[nodiscard]] error_info { /* ... */ }; error_info enable_missile_safety_mode(); void launch_missiles(); void test_missiles() { my_scopeguard(); // warning encouraged (void)my_scopeguard(), // warning not encouraged, cast to void launch_missiles(); // comma operator, statement continues my_unique(42); // warning encouraged my_unique(); // warning not encouraged enable_missile_safety_mode(); // warning encouraged launch_missiles(); } error_info &foo(); void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither // the (reference) return type nor the function is declared nodiscard — end example]

9.12.11 Noreturn attribute [dcl.attr.noreturn]

The attribute-token noreturn specifies that a function does not return.
No 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 noreturn attribute if any declaration of that function specifies the noreturn attribute.
If a function is declared with the noreturn attribute in one translation unit and the same function is declared without the noreturn attribute in another translation unit, the program is ill-formed, no diagnostic required.
If a function f is invoked where f was previously declared with the noreturn attribute and that invocation eventually returns, the behavior is runtime-undefined.
[Note 1: 
The function can terminate by throwing an exception.
— end note]
Recommended practice: Implementations should issue a warning if a function marked [[noreturn]] might return.
The value of a has-attribute-expression for the noreturn attribute should be 0 unless the implementation can issue such warnings.
[Example 1: [[ noreturn ]] void f() { throw "error"; // OK } [[ noreturn ]] void q(int i) { // behavior is undefined if called with an argument <= 0 if (i > 0) throw "positive"; } — end example]

9.12.12 No unique address attribute [dcl.attr.nouniqueaddr]

The attribute-token no_unique_address specifies that a non-static data member is a potentially-overlapping subobject ([intro.object]).
No attribute-argument-clause shall be present.
The attribute may appertain to a non-static data member other than a bit-field.
[Note 1: 
The non-static data member can share the address of another non-static data member or that of a base class, and any padding that would normally be inserted at the end of the object can be reused as storage for other members.
— end note]
Recommended practice: The value of a has-attribute-expression for the no_unique_address attribute should be 0 for a given implementation unless this attribute can cause a potentially-overlapping subobject to have zero size.
[Example 1: template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator> class hash_map { [[no_unique_address]] Hash hasher; [[no_unique_address]] Pred pred; [[no_unique_address]] Allocator alloc; Bucket *buckets; // ... public: // ... };
Here, hasher, pred, and alloc could have the same address as buckets if their respective types are all empty.
— end example]

10 Modules [module]

10.1 Module units and purviews [module.unit]

A module unit is a translation unit that contains a module-declaration.
A named module is the collection of module units with the same module-name.
The identifiers module and import shall not appear as identifiers in a module-name or module-partition.
All module-names either beginning with an identifier consisting of std followed by zero or more digits or containing a reserved identifier ([lex.name]) are reserved and shall not be specified in a module-declaration; no diagnostic is required.
If any identifier in a reserved module-name is a reserved identifier, the module name is reserved for use by C++ implementations; otherwise it is reserved for future standardization.
The optional attribute-specifier-seq appertains to the module-declaration.
A module interface unit is a module unit whose module-declaration starts with export-keyword; any other module unit is a module implementation unit.
A named module shall contain exactly one module interface unit with no module-partition, known as the primary module interface unit of the module; no diagnostic is required.
A module partition is a module unit whose module-declaration contains a module-partition.
A named module shall not contain multiple module partitions with the same module-partition.
All module partitions of a module that are module interface units shall be directly or indirectly exported by the primary module interface unit ([module.import]).
No diagnostic is required for a violation of these rules.
[Note 1: 
Module partitions can be imported only by other module units in the same module.
The division of a module into module units is not visible outside the module.
— end note]
[Example 1: 

Translation unit #1:export module A; export import :Foo; export int baz();

Translation unit #2:export module A:Foo; import :Internals; export int foo() { return 2 * (bar() + 1); }

Translation unit #3:module A:Internals; int bar();

Translation unit #4:module A; import :Internals; int bar() { return baz() - 10; } int baz() { return 30; }

Module A contains four translation units:
  • a primary module interface unit,
  • a module partition A:Foo, which is a module interface unit forming part of the interface of module A,
  • a module partition A:Internals, which does not contribute to the external interface of module A, and
  • a module implementation unit providing a definition of bar and baz, which cannot be imported because it does not have a partition name.
— end example]
A module unit purview is the sequence of tokens starting at the module-declaration and extending to the end of the translation unit.
The purview of a named module M is the set of module unit purviews of M's module units.
The global module is the collection of all global-module-fragments and all translation units that are not module units.
Declarations appearing in such a context are said to be in the purview of the global module.
[Note 2: 
The global module has no name, no module interface unit, and is not introduced by any module-declaration.
— end note]
A module is either a named module or the global module.
A declaration is attached to a module as follows:
A module-declaration that contains neither an export-keyword nor a module-partition implicitly imports the primary module interface unit of the module as if by a module-import-declaration.
[Example 2: 

Translation unit #1:module B:Y; // does not implicitly import B int y();

Translation unit #2:export module B; import :Y; // OK, does not create interface dependency cycle int n = y();

Translation unit #3:module B:X1; // does not implicitly import B int &a = n; // error: n not visible here

Translation unit #4:module B:X2; // does not implicitly import B import B; int &b = n; // OK

Translation unit #5:module B; // implicitly imports B int &c = n; // OK — end example]

10.2 Export declaration [module.interface]

An export-declaration shall inhabit a namespace scope and appear in the purview of a module interface unit.
An export-declaration shall not appear directly or indirectly within an unnamed namespace or a private-module-fragment.
An export-declaration has the declarative effects of its name-declaration, declaration-seq (if any), or module-import-declaration.
The name-declaration of an export-declaration shall not declare a partial specialization ([temp.decls.general]).
[Note 1: 
An export-declaration does not establish a scope.
— end note]
A declaration is exported if it is declared within an export-declaration and inhabits a namespace scope or it is
If an exported declaration is not within a header unit, it shall not declare a name with internal linkage.
[Example 1: 

Source file "a.h":export int x;

Translation unit #1:module; #include "a.h" // error: declaration of x is not in the // purview of a module interface unit export module M; export namespace {} // error: namespace has internal linkage namespace { export int a2; // error: export of name with internal linkage } export static int b; // error: b explicitly declared static export int f(); // OK export namespace N { } // OK export using namespace N; // OK — end example]

If an exported declaration is a using-declaration ([namespace.udecl]) and is not within a header unit, all entities to which all of the using-declarators ultimately refer (if any) shall have been introduced with a name having external linkage.
[Example 2: 

Source file "b.h":int f();

Importable header "c.h":int g();

Translation unit #1:export module X; export int h();

Translation unit #2:module; #include "b.h" export module M; import "c.h"; import X; export using ::f, ::g, ::h; // OK struct S; export using ::S; // error: S has module linkage namespace N { export int h(); static int h(int); // #1 } export using N::h; // error: #1 has internal linkage — end example]

[Note 2: 
These constraints do not apply to type names introduced by typedef declarations and alias-declarations.
[Example 3: export module M; struct S; export using T = S; // OK, exports name T denoting type S — end example]
— end note]
A redeclaration of an entity X is implicitly exported if X was introduced by an exported declaration; otherwise it shall not be exported if it is attached to a named module.
[Example 4: export module M; struct S { int n; }; typedef S S; export typedef S S; // OK, does not redeclare an entity export struct S; // error: exported declaration follows non-exported declaration — end example]
[Note 3: 
Names introduced by exported declarations have either external linkage or no linkage; see [basic.link].
Namespace-scope declarations exported by a module can be found by name lookup in any translation unit importing that module ([basic.lookup]).
Class and enumeration member names can be found by name lookup in any context in which a definition of the type is reachable.
— end note]
[Example 5: 

Interface unit of M:export module M; export struct X { static void f(); struct Y { }; }; namespace { struct S { }; } export void f(S); // OK struct T { }; export T id(T); // OK export struct A; // A exported as incomplete export auto rootFinder(double a) { return [=](double x) { return (x + a/x)/2; }; } export const int n = 5; // OK, n has external linkage

Implementation unit of M:module M; struct A { int value; };

Main program:import M; int main() { X::f(); // OK, X is exported and definition of X is reachable X::Y y; // OK, X​::​Y is exported as a complete type auto f = rootFinder(2); // OK return A{45}.value; // error: A is incomplete } — end example]

[Note 4: 
Declarations in an exported namespace-definition or in an exported linkage-specification ([dcl.link]) are exported and subject to the rules of exported declarations.
[Example 6: export module M; int g; export namespace N { int x; // OK using ::g; // error: ​::​g has module linkage } — end example]
— end note]

10.3 Import declaration [module.import]

A module-import-declaration shall inhabit the global namespace scope.
In a module unit, all module-import-declarations and export-declarations exporting module-import-declarations shall appear before all other declarations in the declaration-seq of the translation-unit and of the private-module-fragment (if any).
A module-import-declaration imports a set of translation units determined as described below.
[Note 1: 
Namespace-scope declarations exported by the imported translation units can be found by name lookup ([basic.lookup]) in the importing translation unit and declarations within the imported translation units become reachable ([module.reach]) in the importing translation unit after the import declaration.
— end note]
A module-import-declaration that specifies a module-name M imports all module interface units of M.
A module-import-declaration that specifies a module-partition shall only appear after the module-declaration in a module unit of some module M.
Such a declaration imports the so-named module partition of M.
A module-import-declaration that specifies a header-name H imports a synthesized header unit, which is a translation unit formed by applying phases 1 to 7 of translation ([lex.phases]) to the source file or header nominated by H, which shall not contain a module-declaration.
[Note 2: 
A header unit is a separate translation unit with an independent set of defined macros.
All declarations within a header unit are implicitly exported ([module.interface]), and are attached to the global module ([module.unit]).
— end note]
An importable header is a member of an implementation-defined set of headers that includes all importable C++ library headers ([headers]).
H shall identify an importable header.
Given two such module-import-declarations:
  • if their header-names identify different headers or source files ([cpp.include]), they import distinct header units;
  • otherwise, if they appear in the same translation unit, they import the same header unit;
  • otherwise, it is unspecified whether they import the same header unit.
    [Note 3: 
    It is therefore possible that multiple copies exist of entities declared with internal linkage in an importable header.
    — end note]
[Note 4: 
A module-import-declaration nominating a header-name is also recognized by the preprocessor, and results in macros defined at the end of phase 4 of translation of the header unit being made visible as described in [cpp.import].
Any other module-import-declaration does not make macros visible.
— end note]
A declaration of a name with internal linkage is permitted within a header unit despite all declarations being implicitly exported ([module.interface]).
[Note 5: 
A definition that appears in multiple translation units cannot in general refer to such names ([basic.def.odr]).
— end note]
A header unit shall not contain a definition of a non-inline function or variable whose name has external linkage.
When a module-import-declaration imports a translation unit T, it also imports all translation units imported by exported module-import-declarations in T; such translation units are said to be exported by T.
Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M, it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.85
These rules can in turn lead to the importation of yet more translation units.
[Note 6: 
Such indirect importation does not make macros available, because a translation unit is a sequence of tokens in translation phase 7 ([lex.phases]).
Macros can be made available by directly importing header units as described in [cpp.import].
— end note]
A module implementation unit shall not be exported.
[Example 1: 

Translation unit #1:module M:Part;

Translation unit #2:export module M; export import :Part; // error: exported partition :Part is an implementation unit — end example]

A module implementation unit of a module M that is not a module partition shall not contain a module-import-declaration nominating M.
[Example 2: module M; import M; // error: cannot import M in its own unit — end example]
A translation unit has an interface dependency on a translation unit U if it contains a declaration (possibly a module-declaration) that imports U or if it has an interface dependency on a translation unit that has an interface dependency on U.
A translation unit shall not have an interface dependency on itself.
[Example 3: 

Interface unit of M1:export module M1; import M2;

Interface unit of M2:export module M2; import M3;

Interface unit of M3:export module M3; import M1; // error: cyclic interface dependency M3M1M2M3 — end example]

85)85)
This is consistent with the lookup rules for imported names ([basic.lookup]).

10.4 Global module fragment [module.global.frag]

[Note 1: 
Prior to phase 4 of translation, only preprocessing directives can appear in the declaration-seq ([cpp.pre]).
— end note]
A global-module-fragment specifies the contents of the global module fragment for a module unit.
The global module fragment can be used to provide declarations that are attached to the global module and usable within the module unit.
A declaration D is decl-reachable from a declaration S in the same translation unit if
  • D does not declare a function or function template and S contains an id-expression, namespace-name, type-name, template-name, or concept-name naming D, or
  • D declares a function or function template that is named by an expression ([basic.def.odr]) appearing in S, or
  • S contains a dependent call E ([temp.dep]) and D is found by any name lookup performed for an expression synthesized from E by replacing each type-dependent argument or operand with a value of a placeholder type with no associated namespaces or entities, or
    [Note 2: 
    This includes the lookup for operator== performed when considering rewriting an != expression, the lookup for operator<=> performed when considering rewriting a relational comparison, and the lookup for operator!= when considering whether an operator== is a rewrite target.
    — end note]
  • S contains an expression that takes the address of an overload set ([over.over]) that contains D and for which the target type is dependent, or
  • there exists a declaration M that is not a namespace-definition for which M is decl-reachable from S and either
    • D is decl-reachable from M, or
    • D and M declare the same entity, and D neither is a friend declaration nor inhabits a block scope, or
    • D declares a namespace N and M is a member of N, or
    • one of D and M declares a class or class template C and the other declares a member or friend of C, or
    • one of D and M declares an enumeration E and the other declares an enumerator of E, or
    • D declares a function or variable and M is declared in D,86 or
    • one of D and M declares a template and the other declares a partial or explicit specialization or an implicit or explicit instantiation of that template, or
    • M declares a class template and D is a deduction guide for that template, or
    • one of D and M declares a class or enumeration type and the other introduces a typedef name for linkage purposes for that type.
In this determination, it is unspecified
A declaration D in a global module fragment of a module unit is discarded if D is not decl-reachable from any declaration in the declaration-seq of the translation-unit.
[Note 3: 
A discarded declaration is neither reachable nor visible to name lookup outside the module unit, nor in template instantiations whose points of instantiation ([temp.point]) are outside the module unit, even when the instantiation context ([module.context]) includes the module unit.
— end note]
[Example 1: const int size = 2; int ary1[size]; // unspecified whether size is decl-reachable from ary1 constexpr int identity(int x) { return x; } int ary2[identity(2)]; // unspecified whether identity is decl-reachable from ary2 template<typename> struct S; template<typename, int> struct S2; constexpr int g(int); template<typename T, int N> S<S2<T, g(N)>> f(); // S, S2, g, and ​::​ are decl-reachable from f template<int N> void h() noexcept(g(N) == N); // g and ​::​ are decl-reachable from h — end example]
[Example 2: 

Source file "foo.h":namespace N { struct X {}; int d(); int e(); inline int f(X, int = d()) { return e(); } int g(X); int h(X); }

Module M interface:module; #include "foo.h" export module M; template<typename T> int use_f() { N::X x; // N​::​X, N, and ​::​ are decl-reachable from use_f return f(x, 123); // N​::​f is decl-reachable from use_f, // N​::​e is indirectly decl-reachable from use_f // because it is decl-reachable from N​::​f, and // N​::​d is decl-reachable from use_f // because it is decl-reachable from N​::​f // even though it is not used in this call } template<typename T> int use_g() { N::X x; // N​::​X, N, and ​::​ are decl-reachable from use_g return g((T(), x)); // N​::​g is not decl-reachable from use_g } template<typename T> int use_h() { N::X x; // N​::​X, N, and ​::​ are decl-reachable from use_h return h((T(), x)); // N​::​h is not decl-reachable from use_h, but // N​::​h is decl-reachable from use_h<int> } int k = use_h<int>(); // use_h<int> is decl-reachable from k, so // N​::​h is decl-reachable from k

Module M implementation:module M; int a = use_f<int>(); // OK int b = use_g<int>(); // error: no viable function for call to g; // g is not decl-reachable from purview of // module M's interface, so is discarded int c = use_h<int>(); // OK — end example]

86)86)
A declaration can appear within a lambda-expression in the initializer of a variable.

10.5 Private module fragment [module.private.frag]

private-module-fragment:
module-keyword : private ; declaration-seq
A private-module-fragment shall appear only in a primary module interface unit ([module.unit]).
A module unit with a private-module-fragment shall be the only module unit of its module; no diagnostic is required.
[Note 1: 
A private-module-fragment ends the portion of the module interface unit that can affect the behavior of other translation units.
A private-module-fragment allows a module to be represented as a single translation unit without making all of the contents of the module reachable to importers.
The presence of a private-module-fragment affects:
— end note]
[Example 1: export module A; export inline void fn_e(); // error: exported inline function fn_e not defined // before private module fragment inline void fn_m(); // error: non-exported inline function fn_m not defined static void fn_s(); export struct X; export void g(X *x) { fn_s(); // OK, call to static function in same translation unit } export X *factory(); // OK module :private; struct X {}; // definition not reachable from importers of A X *factory() { return new X (); } void fn_e() {} void fn_m() {} void fn_s() {} — end example]

10.6 Instantiation context [module.context]

The instantiation context is a set of points within the program that determines which declarations are found by argument-dependent name lookup ([basic.lookup.argdep]) and which are reachable ([module.reach]) in the context of a particular declaration or template instantiation.
During the implicit definition of a defaulted function ([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 resulted in the implicit definition of the defaulted function.
During the implicit instantiation of a template whose point of instantiation is specified as that of an enclosing specialization ([temp.point]), the instantiation context is the union of the instantiation context of the enclosing specialization and, if the template is defined in a module interface unit of a module M and the point of instantiation is not in a module interface unit of M, the point at the end of the declaration-seq of the primary module interface unit of M (prior to the private-module-fragment, if any).
During the implicit instantiation of a template that is implicitly instantiated because it is referenced from within the implicit definition of a defaulted function, the instantiation context is the instantiation context of the defaulted function.
During the instantiation of any other template specialization, the instantiation context comprises the point of instantiation of the template.
In any other case, the instantiation context at a point within the program comprises that point.
[Example 1: 

Translation unit #1:export module stuff; export template<typename T, typename U> void foo(T, U u) { auto v = u; } export template<typename T, typename U> void bar(T, U u) { auto v = *u; }

Translation unit #2:export module M1; import "defn.h"; // provides struct X {}; import stuff; export template<typename T> void f(T t) { X x; foo(t, x); }

Translation unit #3:export module M2; import "decl.h"; // provides struct X; (not a definition) import stuff; export template<typename T> void g(T t) { X *x; bar(t, x); }

Translation unit #4:import M1; import M2; void test() { f(0); g(0); }

The call to f(0) is valid; the instantiation context of foo<int, X> comprises
  • the point at the end of translation unit #1,
  • the point at the end of translation unit #2, and
  • the point of the call to f(0),
so the definition of X is reachable ([module.reach]).
It is unspecified whether the call to g(0) is valid: the instantiation context of bar<int, X> comprises
  • the point at the end of translation unit #1,
  • the point at the end of translation unit #3, and
  • the point of the call to g(0),
so the definition of X need not be reachable, as described in [module.reach].
— end example]

10.7 Reachability [module.reach]

A translation unit U is necessarily reachable from a point P if U is a module interface unit on which the translation unit containing P has an interface dependency, or the translation unit containing P imports U, in either case prior to P ([module.import]).
[Note 1: 
While module interface units are reachable even when they are only transitively imported via a non-exported import declaration, namespace-scope names from such module interface units are not found by name lookup ([basic.lookup]).
— end note]
All translation units that are necessarily reachable are reachable.
Additional translation units on which the point within the program has an interface dependency may be considered reachable, but it is unspecified which are and under what circumstances.87
[Note 2: 
It is advisable to avoid depending on the reachability of any additional translation units in programs intending to be portable.
— end note]
A declaration D is reachable from a point P if
A declaration is reachable if it is reachable from any point in the instantiation context ([module.context]).
[Note 3: 
Whether a declaration is exported has no bearing on whether it is reachable.
— end note]
The accumulated properties of all reachable declarations of an entity within a context determine the behavior of the entity within that context.
[Note 4: 
These reachable semantic properties include type completeness, type definitions, initializers, default arguments of functions or template declarations, attributes, names bound, etc.
Since default arguments are evaluated in the context of the call expression, the reachable semantic properties of the corresponding parameter types apply in that context.
[Example 1: 

Translation unit #1:export module M:A; export struct B;

Translation unit #2:module M:B; struct B { operator int(); };

Translation unit #3:module M:C; import :A; B b1; // error: no reachable definition of struct B

Translation unit #4:export module M; export import :A; import :B; B b2; export void f(B b = B());

Translation unit #5:import M; B b3; // error: no reachable definition of struct B void g() { f(); } // error: no reachable definition of struct B — end example]

— end note]
[Note 5: 
Declarations of an entity can be reachable even where they cannot be found by name lookup.
— end note]
[Example 2: 

Translation unit #1:export module A; struct X {}; export using Y = X;

Translation unit #2:import A; Y y; // OK, definition of X is reachable X x; // error: X not visible to unqualified lookup — end example]

87)87)
Implementations are therefore not required to prevent the semantic effects of additional translation units involved in the compilation from being observed.

11 Classes [class]

11.1 Preamble [class.pre]

A class is a type.
Its name becomes a class-name ([class.name]) within its scope.
An object of a class consists of a (possibly empty) sequence of members and base class objects.
class-key:
class
struct
union
A class declaration where the class-name in the class-head-name is a simple-template-id shall be an explicit specialization ([temp.expl.spec]) or a partial specialization ([temp.spec.partial]).
[Note 1: 
An unnamed class thus can't be final.
— end note]
Otherwise, the class-name is an identifier; it is not looked up, and the class-specifier introduces it.
The component name of the class-name is also bound in the scope of the class (template) itself; this is known as the injected-class-name.
For purposes of access checking, the injected-class-name is treated as if it were a public member name.
A class-specifier is commonly referred to as a class definition.
A class is considered defined after the closing brace of its class-specifier has been seen even though its member functions are in general not yet defined.
The optional attribute-specifier-seq appertains to the class; the attributes in the attribute-specifier-seq are thereafter considered attributes of the class whenever it is named.
If a class-head-name contains a nested-name-specifier, the class-specifier shall not inhabit a class scope.
If its class-name is an identifier, the class-specifier shall correspond to one or more declarations nominable in the class, class template, or namespace to which the nested-name-specifier refers; they shall all have the same target scope, and the target scope of the class-specifier is that scope.
[Example 1: namespace N { template<class> struct A { struct B; }; } using N::A; template<class T> struct A<T>::B {}; // OK template<> struct A<void> {}; // OK — end example]
[Note 2: 
The class-key determines whether the class is a union ([class.union]) and whether access is public or private by default ([class.access]).
A union holds the value of at most one data member at a time.
— end note]
If a class is marked with the class-virt-specifier final and it appears as a class-or-decltype in a base-clause ([class.derived]), the program is ill-formed.
Whenever a class-key is followed by a class-head-name, the identifier final, and a colon or left brace, final is interpreted as a class-virt-specifier.
[Example 2: struct A; struct A final {}; // OK, definition of struct A, // not value-initialization of variable final struct X { struct C { constexpr operator int() { return 5; } }; struct B final : C{}; // OK, definition of nested class B, // not declaration of a bit-field member final }; — end example]
[Note 3: 
Complete objects of class type have nonzero size.
Base class subobjects and members declared with the no_unique_address attribute ([dcl.attr.nouniqueaddr]) are not so constrained.
— end note]
[Note 4: 
Class objects can be assigned ([over.ass], [class.copy.assign]), passed as arguments to functions ([dcl.init], [class.copy.ctor]), and returned by functions (except objects of classes for which copying or moving has been restricted; see [dcl.fct.def.delete] and [class.access]).
Other plausible operators, such as equality comparison, can be defined by the user; see [over.oper].
— end note]

11.2 Properties of classes [class.prop]

A trivially copyable class is a class:
  • that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),
  • where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
  • that has a trivial, non-deleted destructor ([class.dtor]).
A class S is a standard-layout class if it:
  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions and no virtual base classes,
  • has the same access control for all non-static data members,
  • has no non-standard-layout base classes,
  • has at most one base class subobject of any given type,
  • has all non-static data members and bit-fields in the class and its base classes first declared in the same class, and
  • has no element of the set M(S) of types as a base class, where for any type X, M(X) is defined as follows.88
    [Note 1: 
    M(X) is the set of the types of all non-base-class subobjects that can be at a zero offset in X.
    — end note]
    • If X is a non-union class type with no non-static data members, the set M(X) is empty.
    • If X is a non-union class type with a non-static data member of type that is either of zero size or is the first non-static data member of X (where said member may be an anonymous union), the set M(X) consists of and the elements of .
    • If X is a union type, the set M(X) is the union of all and the set containing all , where each is the type of the non-static data member of X.
    • If X is an array type with element type , the set M(X) consists of and the elements of .
    • If X is a non-class, non-array type, the set M(X) is empty.
[Example 1: struct B { int i; }; // standard-layout class struct C : B { }; // standard-layout class struct D : C { }; // standard-layout class struct E : D { char : 4; }; // not a standard-layout class struct Q {}; struct S : Q { }; struct T : Q { }; struct U : S, T { }; // not a standard-layout class — end example]
A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class.
A standard-layout union is a standard-layout class defined with the class-key union.
[Note 2: 
Standard-layout classes are useful for communicating with code written in other programming languages.
Their layout is specified in [class.mem].
— end note]
[Example 2: struct N { // neither trivially copyable nor standard-layout int i; int j; virtual ~N(); }; struct T { // trivially copyable but not standard-layout int i; private: int j; }; struct SL { // standard-layout but not trivially copyable int i; int j; ~SL(); }; struct POD { // both trivially copyable and standard-layout int i; int j; }; — end example]
[Note 3: 
Aggregates of class type are described in [dcl.init.aggr].
— end note]
A class S is an implicit-lifetime class if
  • it is an aggregate whose destructor is not user-provided or
  • it has at least one trivial eligible constructor and a trivial, non-deleted destructor.
88)88)
This ensures that two subobjects that have the same class type and that belong to the same most derived object are not allocated at the same address ([expr.eq]).

11.3 Class names [class.name]

A class definition introduces a new type.
[Example 1: 
struct X { int a; }; struct Y { int a; }; X a1; Y a2; int a3; declares three variables of three different types.
This implies that a1 = a2; // error: Y assigned to X a1 = a3; // error: int assigned to X are type mismatches, and that int f(X); int f(Y); declare overloads ([over]) named f and not simply a single function f twice.
For the same reason, struct S { int a; }; struct S { int a; }; // error: double definition is ill-formed because it defines S twice.
— end example]
[Note 1: 
It can be necessary to use an elaborated-type-specifier to refer to a class that belongs to a scope in which its name is also bound to a variable, function, or enumerator ([basic.lookup.elab]).
[Example 2: struct stat { // ... }; stat gstat; // use plain stat to define variable int stat(struct stat*); // stat now also names a function void f() { struct stat* ps; // struct prefix needed to name struct stat stat(ps); // call stat function } — end example]
An elaborated-type-specifier can also be used to declare an identifier as a class-name.
[Example 3: struct s { int a; }; void g() { struct s; // hide global struct s with a block-scope declaration s* p; // refer to local struct s struct s { char* p; }; // define local struct s struct s; // redeclaration, has no effect } — end example]
Such declarations allow definition of classes that refer to each other.
[Example 4: class Vector; class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); };
Declaration of friends is described in [class.friend], operator functions in [over.oper].
— end example]
— end note]
[Note 2: 
An elaborated-type-specifier ([dcl.type.elab]) can also be used as a type-specifier as part of a declaration.
It differs from a class declaration in that it can refer to an existing class of the given name.
— end note]
[Example 5: struct s { int a; }; void g(int s) { struct s* p = new struct s; // global s p->a = s; // parameter s } — end example]
[Note 3: 
The declaration of a class name takes effect immediately after the identifier is seen in the class definition or elaborated-type-specifier.
[Example 6: 
class A * A; first specifies A to be the name of a class and then redefines it as the name of a pointer to an object of that class.
This means that the elaborated form class A must be used to refer to the class.
Such artistry with names can be confusing and is best avoided.
— end example]
— end note]
A simple-template-id is only a class-name if its template-name names a class template.

11.4 Class members [class.mem]

11.4.1 General [class.mem.general]

virt-specifier:
override
final
In the absence of a virt-specifier-seq, the token sequence = 0 is treated as a pure-specifier if the type of the declarator-id ([dcl.meaning.general]) is a function type, and is otherwise treated as a brace-or-equal-initializer.
[Note 1: 
If the member declaration acquires a function type through template instantiation, the program is ill-formed; see [temp.spec.general].
— end note]
The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.
A direct member of a class X is a member of X that was first declared within the member-specification of X, including anonymous union members ([class.union.anon]) and direct members thereof.
Members of a class are data members, member functions ([class.mfct]), nested types, enumerators, and member templates ([temp.mem]) and specializations thereof.
[Note 2: 
A specialization of a static data member template is a static data member.
A specialization of a member function template is a member function.
A specialization of a member class template is a nested class.
— end note]
For any other member-declaration, each declared entity that is not an unnamed bit-field is a member of the class, and each such member-declaration shall either declare at least one member name of the class or declare at least one unnamed bit-field.
A data member is a non-function member introduced by a member-declarator.
A member function is a member that is a function.
Nested types are classes ([class.name], [class.nest]) and enumerations ([dcl.enum]) declared in the class and arbitrary types declared as members by use of a typedef declaration ([dcl.typedef]) or alias-declaration.
The enumerators of an unscoped enumeration defined in the class are members of the class.
A data member or member function may be declared static in its member-declaration, in which case it is a static member (see [class.static]) (a static data member ([class.static.data]) or static member function ([class.static.mfct]), respectively) of the class.
Any other data member or member function is a non-static member (a non-static data member or non-static member function ([class.mfct.non.static]), respectively).
[Note 3: 
A non-static data member of non-reference type is a member subobject of a class object.
— end note]
A member shall not be declared twice in the member-specification, except that
[Note 4: 
A single name can denote several member functions provided their types are sufficiently different ([basic.scope.scope]).
— end note]
A redeclaration of a class member outside its class definition shall be a definition, an explicit specialization, or an explicit instantiation ([temp.expl.spec], [temp.explicit]).
The member shall not be a non-static data member.
A complete-class context of a class (template) is a within the member-specification of the class or class template.
[Note 5: 
A complete-class context of a nested class is also a complete-class context of any enclosing class, if the nested class is defined within the member-specification of the enclosing class.
— end note]
A class C is complete at a program point P if the definition of C is reachable from P ([module.reach]) or if P is in a complete-class context of C.
Otherwise, C is incomplete at P.
If a member-declaration matches the syntactic requirements of friend-type-declaration, it is a friend-type-declaration.
In a member-declarator, an = immediately following the declarator is interpreted as introducing a pure-specifier if the declarator-id has function type, otherwise it is interpreted as introducing a brace-or-equal-initializer.
[Example 1: struct S { using T = void(); T * p = 0; // OK, brace-or-equal-initializer virtual T f = 0; // OK, pure-specifier }; — end example]
In a member-declarator for a bit-field, the constant-expression is parsed as the longest sequence of tokens that could syntactically form a constant-expression.
[Example 2: int a; const int b = 0; struct S { int x1 : 8 = 42; // OK, "= 42" is brace-or-equal-initializer int x2 : 8 { 42 }; // OK, "{ 42 }" is brace-or-equal-initializer int y1 : true ? 8 : a = 42; // OK, brace-or-equal-initializer is absent int y2 : true ? 8 : b = 42; // error: cannot assign to const int int y3 : (true ? 8 : b) = 42; // OK, "= 42" is brace-or-equal-initializer int z : 1 || new int { 0 }; // OK, brace-or-equal-initializer is absent }; — end example]
A brace-or-equal-initializer shall appear only in the declaration of a data member.
(For static data members, see [class.static.data]; for non-static data members, see [class.base.init] and [dcl.init.aggr]).
A brace-or-equal-initializer for a non-static data member specifies a default member initializer for the member, and shall not directly or indirectly cause the implicit definition of a defaulted default constructor for the enclosing class or the exception specification of that constructor.
An immediate invocation ([expr.const]) that is a potentially-evaluated subexpression ([intro.execution]) of a default member initializer is neither evaluated nor checked for whether it is a constant expression at the point where the subexpression appears.
A member shall not be declared with the extern storage-class-specifier.
Within a class definition, a member shall not be declared with the thread_local storage-class-specifier unless also declared static.
The decl-specifier-seq may be omitted in constructor, destructor, and conversion function declarations only; when declaring another kind of member the decl-specifier-seq shall contain a type-specifier that is not a cv-qualifier.
The member-declarator-list can be omitted only after a class-specifier or an enum-specifier or in a friend declaration.
A pure-specifier shall be used only in the declaration of a virtual function that is not a friend declaration.
The optional attribute-specifier-seq in a member-declaration appertains to each of the entities declared by the member-declarators; it shall not appear if the optional member-declarator-list is omitted.
A virt-specifier-seq shall contain at most one of each virt-specifier.
A virt-specifier-seq shall appear only in the first declaration of a virtual member function ([class.virtual]).
The type of a non-static data member shall not be an incomplete type ([basic.types.general]), an abstract class type ([class.abstract]), or a (possibly multidimensional) array thereof.
[Note 6: 
In particular, a class C cannot contain a non-static member of class C, but it can contain a pointer or reference to an object of class C.
— end note]
[Note 7: 
See [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions.
— end note]
[Note 8: 
The type of a non-static member function is an ordinary function type, and the type of a non-static data member is an ordinary object type.
There are no special member function types or data member types.
— end note]
[Example 3: 
A simple example of a class definition is struct tnode { char tword[20]; int count; tnode* left; tnode* right; }; which contains an array of twenty characters, an integer, and two pointers to objects of the same type.
Once this definition has been given, the declaration tnode s, *sp; declares s to be a tnode and sp to be a pointer to a tnode.
With these declarations, sp->count refers to the count member of the object to which sp points; s.left refers to the left subtree pointer of the object s; and s.right->tword[0] refers to the initial character of the tword member of the right subtree of s.
— end example]
[Note 9: 
Non-variant non-static data members of non-zero size ([intro.object]) are allocated so that later members have higher addresses within a class object ([expr.rel]).
Implementation alignment requirements can cause two adjacent members not to be allocated immediately after each other; so can requirements for space for managing virtual functions ([class.virtual]) and virtual base classes ([class.mi]).
— end note]
If T is the name of a class, then each of the following shall have a name different from T:
  • every static data member of class T;
  • every member function of class T;
    [Note 10: 
    This restriction does not apply to constructors, which do not have names ([class.ctor]).
    — end note]
  • every member of class T that is itself a type;
  • every member template of class T;
  • every enumerator of every member of class T that is an unscoped enumeration type; and
  • every member of every anonymous union that is a member of class T.
In addition, if class T has a user-declared constructor, every non-static data member of class T shall have a name different from T.
The common initial sequence of two standard-layout struct ([class.prop]) types is the longest sequence of non-static data members and bit-fields in declaration order, starting with the first such entity in each of the structs, such that
[Example 4: struct A { int a; char b; }; struct B { const int b1; volatile char b2; }; struct C { int c; unsigned : 0; char b; }; struct D { int d; char b : 4; }; struct E { unsigned int e; char b; };
The common initial sequence of A and B comprises all members of either class.
The common initial sequence of A and C and of A and D comprises the first member in each case.
The common initial sequence of A and E is empty.
— end example]
Two standard-layout struct ([class.prop]) types are layout-compatible classes if their common initial sequence comprises all members and bit-fields of both classes ([basic.types]).
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 ([basic.types.general]).
In a standard-layout union with an active member of struct type T1, it is permitted to read a non-static data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2; the behavior is as if the corresponding member of T1 were nominated.
[Example 5: struct T1 { int a, b; }; struct T2 { int c; double d; }; union U { T1 t1; T2 t2; }; int f() { U u = { { 1, 2 } }; // active member is t1 return u.t2.c; // OK, as if u.t1.a were nominated } — end example]
[Note 11: 
Reading a volatile object through a glvalue of non-volatile type has undefined behavior ([dcl.type.cv]).
— end note]
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member if that member is not a bit-field.
Its address is also the same as the address of each of its base class subobjects.
[Note 12: 
There can therefore be unnamed padding within a standard-layout struct object inserted by an implementation, but not at its beginning, as necessary to achieve appropriate alignment.
— end note]
[Note 13: 
The object and its first subobject are pointer-interconvertible ([basic.compound], [expr.static.cast]).
— end note]

11.4.2 Member functions [class.mfct]

If a member function is attached to the global module and is defined ([dcl.fct.def]) in its class definition, it is inline ([dcl.inline]).
[Note 1: 
A member function is also inline if it is declared inline, constexpr, or consteval.
— end note]
[Example 1: struct X { typedef int T; static T count; void f(T); }; void X::f(T t = count) { }
The definition of the member function f of class X inhabits the global scope; the notation X​::​f indicates that the function f is a member of class X and in the scope of class X.
In the function definition, the parameter type T refers to the typedef member T declared in class X and the default argument count refers to the static data member count declared in class X.
— end example]
Member functions of a local class shall be defined inline in their class definition, if they are defined at all.
[Note 2: 
A member function can be declared (but not defined) using a typedef for a function type.
The resulting member function has exactly the same type as it would have if the function declarator were provided explicitly, see [dcl.fct] and [temp.arg].
[Example 2: typedef void fv(); typedef void fvc() const; struct S { fv memfunc1; // equivalent to: void memfunc1(); void memfunc2(); fvc memfunc3; // equivalent to: void memfunc3() const; }; fv S::* pmfv1 = &S::memfunc1; fv S::* pmfv2 = &S::memfunc2; fvc S::* pmfv3 = &S::memfunc3; — end example]
— end note]

11.4.3 Non-static member functions [class.mfct.non.static]

A non-static member function may be called for an object of its class type, or for an object of a class derived ([class.derived]) from its class type, using the class member access syntax ([expr.ref], [over.match.call]).
A non-static member function may also be called directly using the function call syntax ([expr.call], [over.match.call]) from within its class or a class derived from its class, or a member thereof, as described below.
[Note 1: 
An implicit object member function can be declared with cv-qualifiers, which affect the type of the this pointer ([expr.prim.this]), and/or a ref-qualifier ([dcl.fct]); both affect overload resolution ([over.match.funcs]).
— end note]
An implicit object member function may be declared virtual ([class.virtual]) or pure virtual ([class.abstract]).

11.4.4 Special member functions [special]

Default constructors ([class.default.ctor]), copy constructors, move constructors ([class.copy.ctor]), copy assignment operators, move assignment operators ([class.copy.assign]), and prospective destructors ([class.dtor]) are special member functions.
[Note 1: 
The implementation will implicitly declare these member functions for some class types when the program does not explicitly declare them.
The implementation will implicitly define them as needed ([dcl.fct.def.default]).
— end note]
An implicitly-declared special member function is declared at the closing } of the class-specifier.
Programs shall not define implicitly-declared special member functions.
Programs may explicitly refer to implicitly-declared special member functions.
[Example 1: 
A program may explicitly call or form a pointer to member to an implicitly-declared special member function.
struct A { }; // implicitly declared A​::​operator= struct B : A { B& operator=(const B &); }; B& B::operator=(const B& s) { this->A::operator=(s); // well-formed return *this; } — end example]
[Note 2: 
The special member functions affect the way objects of class type are created, copied, moved, and destroyed, and how values can be converted to values of other types.
Often such special member functions are called implicitly.
— end note]
Special member functions obey the usual access rules ([class.access]).
[Example 2: 
Declaring a constructor protected ensures that only derived classes and friends can create objects using it.
— end example]
Two special member functions are of the same kind if
  • they are both default constructors,
  • they are both copy or move constructors with the same first parameter type, or
  • they are both copy or move assignment operators with the same first parameter type and the same cv-qualifiers and ref-qualifier, if any.
An eligible special member function is a special member function for which:
  • the function is not deleted,
  • the associated constraints ([temp.constr]), if any, are satisfied, and
  • no special member function of the same kind whose associated constraints, if any, are satisfied is more constrained ([temp.constr.order]).
For a class, its non-static data members, its non-virtual direct base classes, and, if the class is not abstract ([class.abstract]), its virtual base classes are called its potentially constructed subobjects.

11.4.5 Constructors [class.ctor]

11.4.5.1 General [class.ctor.general]

A declarator declares a constructor if it is a function declarator ([dcl.fct]) of the form where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
Constructors do not have names.
In a constructor declaration, each decl-specifier in the optional decl-specifier-seq shall be friend, inline, constexpr, consteval, or an explicit-specifier.
[Example 1: struct S { S(); // declares the constructor }; S::S() { } // defines the constructor — end example]
A constructor is used to initialize objects of its class type.
[Note 1: 
Because constructors do not have names, they are never found during unqualified name lookup; however an explicit type conversion using the functional notation ([expr.type.conv]) will cause a constructor to be called to initialize an object.
The syntax looks like an explicit call of the constructor.
— end note]
[Example 2: complex zz = complex(1,2.3); cprint( complex(7.8,1.2) ); — end example]
[Note 2: 
For initialization of objects of class type see [class.init].
— end note]
An object created in this way is unnamed.
[Note 3: 
[class.temporary] describes the lifetime of temporary objects.
— end note]
[Note 4: 
Explicit constructor calls do not yield lvalues, see [basic.lval].
— end note]
[Note 5: 
Some language constructs have special semantics when used during construction; see [class.base.init] and [class.cdtor].
— end note]
A constructor can be invoked for a const, volatile or const volatile object.
const and volatile semantics ([dcl.type.cv]) are not applied on an object under construction.
They come into effect when the constructor for the most derived object ([intro.object]) ends.
The address of a constructor shall not be taken.
[Note 6: 
A return statement in the body of a constructor cannot specify a return value ([stmt.return]).
— end note]
A constructor shall not be a coroutine.
A constructor shall not have an explicit object parameter ([dcl.fct]).

11.4.5.2 Default constructors [class.default.ctor]

A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters).
If there is no user-declared constructor or constructor template for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted ([dcl.fct.def]).
An implicitly-declared default constructor is an inline public member of its class.
A defaulted default constructor for class X is defined as deleted if
  • any non-static data member with no default member initializer ([class.mem]) is of reference type,
  • any non-variant non-static data member of const-qualified type (or possibly multidimensional array thereof) with no brace-or-equal-initializer is not const-default-constructible ([dcl.init]),
  • X is a union and all of its variant members are of const-qualified type (or possibly multidimensional array thereof),
  • X is a non-union class and all members of any anonymous union member are of const-qualified type (or possibly multidimensional array thereof),
  • any potentially constructed subobject, except for a non-static data member with a brace-or-equal-initializer or a variant member of a union where another non-static data member has a brace-or-equal-initializer, has class type M (or possibly multidimensional array thereof) and overload resolution ([over.match]) as applied to find M's corresponding constructor either does not result in a usable candidate ([over.match.general]) or, in the case of a variant member, selects a non-trivial function, or
  • any potentially constructed subobject has class type M (or possibly multidimensional array thereof) and M has a destructor that is deleted or inaccessible from the defaulted default constructor.
A default constructor is trivial if it is not user-provided and if
  • its class has no virtual functions ([class.virtual]) and no virtual base classes ([class.mi]), and
  • no non-static data member of its class has a default member initializer ([class.mem]), and
  • all the direct base classes of its class have trivial default constructors, and
  • for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.
Otherwise, the default constructor is non-trivial.
An implicitly-defined ([dcl.fct.def.default]) default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer ([class.base.init]) and an empty compound-statement.
If that user-written default constructor would be ill-formed, the program is ill-formed.
If that user-written default constructor would be constexpr-suitable ([dcl.constexpr]), the implicitly-defined default constructor is constexpr.
Before the defaulted default constructor for a class is implicitly defined, all the non-user-provided default constructors for its base classes and its non-static data members are implicitly defined.
[Note 1: 
An implicitly-declared default constructor has an exception specification ([except.spec]).
An explicitly-defaulted definition might have an implicit exception specification, see [dcl.fct.def].
— end note]
[Note 2: 
A default constructor is implicitly invoked to initialize a class object when no initializer is specified ([dcl.init.general]).
Such a default constructor needs to be accessible ([class.access]).
— end note]
[Note 3: 
[class.base.init] describes the order in which constructors for base classes and non-static data members are called and describes how arguments can be specified for the calls to these constructors.
— end note]

11.4.5.3 Copy/move constructors [class.copy.ctor]

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).
[Example 1: 
X​::​X(const X&) and X​::​X(X&,int=1) are copy constructors.
struct X { X(int); X(const X&, int = 1); }; X a(1); // calls X(int); X b(a, 0); // calls X(const X&, int); X c = b; // calls X(const X&, int); — end example]
A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).
[Example 2: 
Y​::​Y(Y&&) is a move constructor.
struct Y { Y(const Y&); Y(Y&&); }; extern Y f(int); Y d(f(1)); // calls Y(Y&&) Y e = d; // calls Y(const Y&) — end example]
[Note 1: 
All forms of copy/move constructor can be declared for a class.
[Example 3: struct X { X(const X&); X(X&); // OK X(X&&); X(const X&&); // OK, but possibly not sensible }; — end example]
— end note]
[Note 2: 
If a class X only has a copy constructor with a parameter of type X&, an initializer of type const X or volatile X cannot initialize an object of type cv X.
[Example 4: struct X { X(); // default constructor X(X&); // copy constructor with a non-const parameter }; const X cx; X x = cx; // error: X​::​X(X&) cannot copy cx into x — end example]
— end note]
A declaration of a constructor for a class X is ill-formed if its first parameter is of type cv X and either there are no other parameters or else all other parameters have default arguments.
A member function template is never instantiated to produce such a constructor signature.
[Example 5: struct S { template<typename T> S(T); S(); }; S g; void h() { S a(g); // does not instantiate the member template to produce S​::​S<S>(S); // uses the implicitly declared copy constructor } — end example]
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly.
If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defaulted ([dcl.fct.def]).
The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor ([depr.impldec]).
The implicitly-declared copy constructor for a class X will have the form X::X(const X&) if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M&.89
Otherwise, the implicitly-declared copy constructor will have the form X::X(X&)
If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if
  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator, and
  • X does not have a user-declared destructor.
[Note 3: 
When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor might instead invoke a copy constructor.
— end note]
The implicitly-declared move constructor for class X will have the form X::X(X&&)
An implicitly-declared copy/move constructor is an inline public member of its class.
A defaulted copy/​move constructor for a class X is defined as deleted ([dcl.fct.def.delete]) if X has:
  • a potentially constructed subobject of type M (or possibly multidimensional array thereof) for which overload resolution ([over.match]), as applied to find M's corresponding constructor, either does not result in a usable candidate ([over.match.general]) or, in the case of a variant member, selects a non-trivial function,
  • any potentially constructed subobject of class type M (or possibly multidimensional array thereof) where M has a destructor that is deleted or inaccessible from the defaulted constructor, or,
  • for the copy constructor, a non-static data member of rvalue reference type.
[Note 4: 
A defaulted move constructor that is defined as deleted is ignored by overload resolution ([over.match], [over.over]).
Such a constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead.
— end note]
A copy/move constructor for class X is trivial if it is not user-provided and if
  • class X has no virtual functions ([class.virtual]) and no virtual base classes ([class.mi]), and
  • the constructor selected to copy/move each direct base class subobject is trivial, and
  • for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;
otherwise the copy/move constructor is non-trivial.
[Note 5: 
The copy/move constructor is implicitly defined even if the implementation elided its odr-use ([basic.def.odr], [class.temporary]).
— end note]
If an implicitly-defined ([dcl.fct.def.default]) constructor would be constexpr-suitable ([dcl.constexpr]), the implicitly-defined constructor is constexpr.
Before the defaulted copy/move constructor for a class is implicitly defined, all non-user-provided copy/move constructors for its potentially constructed subobjects are implicitly defined.
[Note 6: 
An implicitly-declared copy/move constructor has an implied exception specification ([except.spec]).
— end note]
The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members.
[Note 7: 
Default member initializers of non-static data members are ignored.
— end note]
The order of initialization is the same as the order of initialization of bases and members in a user-defined constructor (see [class.base.init]).
Let x be either the parameter of the constructor or, for the move constructor, an xvalue referring to the parameter.
Each base or non-static data member is copied/moved in the manner appropriate to its type:
  • if the member is an array, each element is direct-initialized with the corresponding subobject of x;
  • if a member m has rvalue reference type T&&, it is direct-initialized with static_cast<T&&>(x.m);
  • otherwise, the base or member is direct-initialized with the corresponding base or member of x.
Virtual base class subobjects shall be initialized only once by the implicitly-defined copy/move constructor (see [class.base.init]).
The implicitly-defined copy/move constructor for a union X copies the object representation ([basic.types.general]) of X.
For each object nested within ([intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is identified (if the object is a subobject) or created (otherwise), and the lifetime of o begins before the copy is performed.
89)89)
This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see [diff.class].

11.4.6 Copy/move assignment operator [class.copy.assign]

A user-declared copy assignment operator X​::​operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X, X&, const X&, volatile X&, or const volatile X&.90
[Note 1: 
More than one form of copy assignment operator can be declared for a class.
— end note]
[Note 2: 
If a class X only has a copy assignment operator with a non-object parameter of type X&, an expression of type const X cannot be assigned to an object of type X.
[Example 1: struct X { X(); X& operator=(X&); }; const X cx; X x; void f() { x = cx; // error: X​::​operator=(X&) cannot assign cx into x } — end example]
— end note]
If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly.
If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defaulted ([dcl.fct.def]).
The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor ([depr.impldec]).
The implicitly-declared copy assignment operator for a class X will have the form X& X::operator=(const X&) if
  • each direct base class B of X has a copy assignment operator whose non-object parameter is of type const B&, const volatile B&, or B, and
  • for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose non-object parameter is of type const M&, const volatile M&, or M.91
Otherwise, the implicitly-declared copy assignment operator will have the form X& X::operator=(X&)
A user-declared move assignment operator X​::​operator= is a non-static non-template member function of class X with exactly one non-object parameter of type X&&, const X&&, volatile X&&, or const volatile X&&.
[Note 3: 
More than one form of move assignment operator can be declared for a class.
— end note]
If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly declared as defaulted if and only if
  • X does not have a user-declared copy constructor,
  • X does not have a user-declared move constructor,
  • X does not have a user-declared copy assignment operator, and
  • X does not have a user-declared destructor.
[Example 2: 
The class definition struct S { int a; S& operator=(const S&) = default; }; will not have a default move assignment operator implicitly declared because the copy assignment operator has been user-declared.
The move assignment operator may be explicitly defaulted.
struct S { int a; S& operator=(const S&) = default; S& operator=(S&&) = default; }; — end example]
The implicitly-declared move assignment operator for a class X will have the form X& X::operator=(X&&)
The implicitly-declared copy/move assignment operator for class X has the return type X&.
An implicitly-declared copy/move assignment operator is an inline public member of its class.
A defaulted copy/move assignment operator for class X is defined as deleted if X has:
  • a non-static data member of const non-class type (or possibly multidimensional array thereof), or
  • a non-static data member of reference type, or
  • a direct non-static data member of class type M (or possibly multidimensional array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, either does not result in a usable candidate ([over.match.general]) or, in the case of a variant member, selects a non-trivial function.
[Note 4: 
A defaulted move assignment operator that is defined as deleted is ignored by overload resolution ([over.match], [over.over]).
— end note]
Because a copy/move assignment operator is implicitly declared for a class if not declared by the user, a base class copy/move assignment operator is always hidden by the corresponding assignment operator of a derived class ([over.ass]).
[Note 5: 
A using-declaration in a derived class C that names an assignment operator from a base class never suppresses the implicit declaration of an assignment operator of C, even if the base class assignment operator would be a copy or move assignment operator if declared as a member of C.
— end note]
A copy/move assignment operator for class X is trivial if it is not user-provided and if
  • class X has no virtual functions ([class.virtual]) and no virtual base classes ([class.mi]), and
  • the assignment operator selected to copy/move each direct base class subobject is trivial, and
  • for each non-static data member of X that is of class type (or array thereof), the assignment operator selected to copy/move that member is trivial;
otherwise the copy/move assignment operator is non-trivial.
An implicitly-defined ([dcl.fct.def.default]) copy/move assignment operator is constexpr.
Before the defaulted copy/move assignment operator for a class is implicitly defined, all non-user-provided copy/move assignment operators for its direct base classes and its non-static data members are implicitly defined.
[Note 6: 
An implicitly-declared copy/move assignment operator has an implied exception specification ([except.spec]).
— end note]
The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy/move assignment of its subobjects.
The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition.
Let x be either the parameter of the function or, for the move operator, an xvalue referring to the parameter.
Each subobject is assigned in the manner appropriate to its type:
  • if the subobject is of class type, as if by a call to operator= with the subobject as the object expression and the corresponding subobject of x as a single function argument (as if by explicit qualification; that is, ignoring any possible virtual overriding functions in more derived classes);
  • if the subobject is an array, each element is assigned, in the manner appropriate to the element type;
  • if the subobject is of scalar type, the built-in assignment operator is used.
It is unspecified whether subobjects representing virtual base classes are assigned more than once by the implicitly-defined copy/move assignment operator.
[Example 3: struct V { }; struct A : virtual V { }; struct B : virtual V { }; struct C : B, A { };
It is unspecified whether the virtual base class subobject V is assigned twice by the implicitly-defined copy/move assignment operator for C.
— end example]
The implicitly-defined copy/move assignment operator for a union X copies the object representation ([basic.types.general]) of X.
If the source and destination of the assignment are not the same object, then for each object nested within ([intro.object]) the object that is the source of the copy, a corresponding object o nested within the destination is created, and the lifetime of o begins before the copy is performed.
The implicitly-defined copy/move assignment operator for a class returns the object for which the assignment operator is invoked, that is, the object assigned to.
90)90)
Because a template assignment operator or an assignment operator taking an rvalue reference parameter is never a copy assignment operator, the presence of such an assignment operator does not suppress the implicit declaration of a copy assignment operator.
Such assignment operators participate in overload resolution with other assignment operators, including copy assignment operators, and, if selected, will be used to assign an object.
91)91)
This implies that the reference parameter of the implicitly-declared copy assignment operator cannot bind to a volatile lvalue; see [diff.class].

11.4.7 Destructors [class.dtor]

A declaration whose declarator-id has an unqualified-id that begins with a ~ declares a prospective destructor; its declarator shall be a function declarator ([dcl.fct]) of the form where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
A prospective destructor shall take no arguments ([dcl.fct]).
Each decl-specifier of the decl-specifier-seq of a prospective destructor declaration (if any) shall be friend, inline, virtual, or constexpr.
If a class has no user-declared prospective destructor, a prospective destructor is implicitly declared as defaulted ([dcl.fct.def]).
An implicitly-declared prospective destructor is an inline public member of its class.
An implicitly-declared prospective destructor for a class X will have the form ~X()
At the end of the definition of a class, overload resolution is performed among the prospective destructors declared in that class with an empty argument list to select the destructor for the class, also known as the selected destructor.
The program is ill-formed if overload resolution fails.
Destructor selection does not constitute a reference to, or odr-use ([basic.def.odr]) of, the selected destructor, and in particular, the selected destructor may be deleted ([dcl.fct.def.delete]).
The address of a destructor shall not be taken.
[Note 1: 
A return statement in the body of a destructor cannot specify a return value ([stmt.return]).
— end note]
A destructor can be invoked for a const, volatile or const volatile object.
const and volatile semantics ([dcl.type.cv]) are not applied on an object under destruction.
They stop being in effect when the destructor for the most derived object ([intro.object]) starts.
[Note 2: 
A declaration of a destructor that does not have a noexcept-specifier has the same exception specification as if it had been implicitly declared ([except.spec]).
— end note]
A defaulted destructor for a class X is defined as deleted if
  • any potentially constructed subobject has class type M (or possibly multidimensional array thereof) and M has a destructor that is deleted or is inaccessible from the defaulted destructor or, in the case of a variant member, is non-trivial,
  • or, for a virtual destructor, lookup of the non-array deallocation function results in an ambiguity or in a function that is deleted or inaccessible from the defaulted destructor.
A destructor is trivial if it is not user-provided and if
  • the destructor is not virtual,
  • all of the direct base classes of its class have trivial destructors, and
  • for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.
Otherwise, the destructor is non-trivial.
A defaulted destructor is a constexpr destructor if it is constexpr-suitable ([dcl.constexpr]).
Before a defaulted destructor for a class is implicitly defined, all the non-user-provided destructors for its base classes and its non-static data members are implicitly defined.
A prospective destructor can be declared virtual ([class.virtual]) and with a pure-specifier ([class.abstract]).
If the destructor of a class is virtual and any objects of that class or any derived class are created in the program, the destructor shall be defined.
[Note 3: 
Some language constructs have special semantics when used during destruction; see [class.cdtor].
— end note]
After executing the body of the destructor and destroying any objects with automatic storage duration allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members other than anonymous unions, the destructors for X's non-virtual direct base classes and, if X is the most derived class ([class.base.init]), its destructor calls the destructors for X's virtual base classes.
All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes.
Bases and members are destroyed in the reverse order of the completion of their constructor (see [class.base.init]).
[Note 4: 
A return statement ([stmt.return]) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called.
— end note]
Destructors for elements of an array are called in reverse order of their construction (see [class.init]).
A destructor is invoked implicitly
In each case, the context of the invocation is the context of the construction of the object.
A destructor may also be invoked implicitly through use of a delete-expression ([expr.delete]) for a constructed object allocated by a new-expression ([expr.new]); the context of the invocation is the delete-expression.
[Note 5: 
An array of class type contains several subobjects for each of which the destructor is invoked.
— end note]
A destructor can also be invoked explicitly.
A destructor is potentially invoked if it is invoked or as specified in [expr.new], [stmt.return], [dcl.init.aggr], [class.base.init], and [except.throw].
A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.
At the point of definition of a virtual destructor (including an implicit definition), the non-array deallocation function is determined as if for the expression delete this appearing in a non-virtual destructor of the destructor's class (see [expr.delete]).
If the lookup fails or if the deallocation function has a deleted definition ([dcl.fct.def]), the program is ill-formed.
[Note 6: 
This assures that a deallocation function corresponding to the dynamic type of an object is available for the delete-expression ([class.free]).
— end note]
In an explicit destructor call, the destructor is specified by a ~ followed by a type-name or computed-type-specifier that denotes the destructor's class type.
The invocation of a destructor is subject to the usual rules for member functions ([class.mfct]); that is, if the object is not of the destructor's class type and not of a class derived from the destructor's class type (including when the destructor is invoked via a null pointer value), the program has undefined behavior.
[Note 7: 
Invoking delete on a null pointer does not call the destructor; see [expr.delete].
— end note]
[Example 1: struct B { virtual ~B() { } }; struct D : B { ~D() { } }; D D_object; typedef B B_alias; B* B_ptr = &D_object; void f() { D_object.B::~B(); // calls B's destructor B_ptr->~B(); // calls D's destructor B_ptr->~B_alias(); // calls D's destructor B_ptr->B_alias::~B(); // calls B's destructor B_ptr->B_alias::~B_alias(); // calls B's destructor } — end example]
[Note 8: 
An explicit destructor call must always be written using a member access operator ([expr.ref]) or a qualified-id ([expr.prim.id.qual]); in particular, the unary-expression ~X() in a member function is not an explicit destructor call ([expr.unary.op]).
— end note]
[Note 9: 
Explicit calls of destructors are rarely needed.
One use of such calls is for objects placed at specific addresses using a placement new-expression.
Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities.
[Example 2: void* operator new(std::size_t, void* p) { return p; } struct X { X(int); ~X(); }; void f(X* p); void g() { // rare, specialized use: char* buf = new char[sizeof(X)]; X* p = new(buf) X(222); // use buf[] and initialize f(p); p->X::~X(); // cleanup } — end example]
— end note]
Once a destructor is invoked for an object, the object's lifetime ends; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended ([basic.life]).
[Example 3: 
If the destructor for an object with automatic storage duration is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined.
— end example]
[Note 10: 
The notation for explicit call of a destructor can be used for any scalar type name ([expr.prim.id.dtor]).
Allowing this makes it possible to write code without having to know if a destructor exists for a given type.
For example: typedef int I; I* p; p->I::~I();
— end note]
A destructor shall not be a coroutine.

11.4.8 Conversions [class.conv]

11.4.8.1 General [class.conv.general]

Type conversions of class objects can be specified by constructors and by conversion functions.
These conversions are called user-defined conversions and are used for implicit type conversions ([conv]), for initialization ([dcl.init]), and for explicit type conversions ([expr.type.conv], [expr.cast], [expr.static.cast]).
User-defined conversions are applied only where they are unambiguous ([class.member.lookup], [class.conv.fct]).
Conversions obey the access control rules ([class.access]).
Access control is applied after ambiguity resolution ([basic.lookup]).
[Note 1: 
See [over.match] for a discussion of the use of conversions in function calls.
— end note]
At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
[Example 1: struct X { operator int(); }; struct Y { operator X(); }; Y a; int b = a; // error: no viable conversion (a.operator X().operator int() not considered) int c = X(a); // OK, a.operator X().operator int() — end example]

11.4.8.2 Conversion by constructor [class.conv.ctor]

A constructor that is not explicit ([dcl.fct.spec]) specifies a conversion from the types of its parameters (if any) to the type of its class.
Such a constructor is called a converting constructor.
[Example 1: struct X { X(int); X(const char*, int = 0); X(int, int); }; void f(X arg) { X a = 1; // a = X(1) X b = "Jessie"; // b = X("Jessie",0) a = 2; // a = X(2) f(3); // f(X(3)) f({1, 2}); // f(X(1,2)) } — end example]
[Note 1: 
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax ([dcl.init]) or where casts ([expr.static.cast], [expr.cast]) are explicitly used; see also [over.match.copy].
A default constructor can be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization ([dcl.init]).
[Example 2: struct Z { explicit Z(); explicit Z(int); explicit Z(int, int); }; 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<Z>(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion — end example]
— end note]
[Note 2: 
A non-explicit copy/move constructor ([class.copy.ctor]), including one implicitly declared, is a converting constructor.
— end note]

11.4.8.3 Conversion functions [class.conv.fct]

A declaration whose declarator-id has an unqualified-id that is a conversion-function-id declares a conversion function; its declarator shall be a function declarator ([dcl.fct]) of the form where the noptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
A conversion function shall have no non-object parameters and shall be a non-static member function of a class or class template X; its declared return type is the conversion-type-id and it specifies a conversion from X to the type specified by the conversion-type-id, interpreted as a type-id ([dcl.name]).
A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall not be a defining-type-specifier.
[Note 1: 
A conversion function is never invoked for implicit or explicit conversions of an object to the same object type (or a reference to it), to a base class of that type (or a reference to it), or to cv void.
Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class.
— end note]
[Example 1: struct X { operator int(); operator auto() -> short; // error: trailing return type }; void f(X a) { int i = int(a); i = (int)a; i = a; }
In all three cases the value assigned will be converted by X​::​operator int().
— end example]
A conversion function may be explicit ([dcl.fct.spec]), in which case it is only considered as a user-defined conversion for direct-initialization ([dcl.init]).
Otherwise, user-defined conversions are not restricted to use in assignments and initializations.
[Example 2: class Y { }; struct Z { explicit operator Y() const; }; void h(Z z) { Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization Y y3 = (Y)z; // OK, cast notation } void g(X a, X b) { int i = (a) ? 1+a : 0; int j = (a&&b) ? a+b : i; if (a) { } } — end example]
The conversion-type-id shall not represent a function type nor an array type.
The conversion-type-id in a conversion-function-id is the longest sequence of tokens that could possibly form a conversion-type-id.
[Note 2: 
This prevents ambiguities between the declarator operator * and its expression counterparts.
[Example 3: &ac.operator int*i; // syntax error: // parsed as: &(ac.operator int *)i // not as: &(ac.operator int)*i
The * is the pointer declarator and not the multiplication operator.
— end example]
This rule also prevents ambiguities for attributes.
[Example 4: operator int [[noreturn]] (); // error: noreturn attribute applied to a type — end example]
— end note]
[Note 3: 
A conversion function in a derived class hides only conversion functions in base classes that convert to the same type.
A conversion function template with a dependent return type hides only templates in base classes that correspond to it ([class.member.lookup]); otherwise, it hides and is hidden as a non-template function.
Function overload resolution ([over.match.best]) selects the best conversion function to perform the conversion.
[Example 5: struct X { operator int(); }; struct Y : X { operator char(); }; void f(Y& a) { if (a) { // error: ambiguous between X​::​operator int() and Y​::​operator char() } } — end example]
— end note]
Conversion functions can be virtual.
A conversion function template shall not have a deduced return type ([dcl.spec.auto]).
[Example 6: struct S { operator auto() const { return 10; } // OK template<class T> operator auto() const { return 1.2; } // error: conversion function template }; — end example]

11.4.9 Static members [class.static]

11.4.9.1 General [class.static.general]

A static member s of class X may be referred to using the qualified-id expression X​::​s; it is not necessary to use the class member access syntax ([expr.ref]) to refer to a static member.
A static member may be referred to using the class member access syntax, in which case the object expression is evaluated.
[Example 1: struct process { static void reschedule(); }; process& g(); void f() { process::reschedule(); // OK, no object necessary g().reschedule(); // g() is called } — end example]
Static members obey the usual class member access rules ([class.access]).
When used in the declaration of a class member, the static specifier shall only be used in the member declarations that appear within the member-specification of the class definition.
[Note 1: 
It cannot be specified in member declarations that appear in namespace scope.
— end note]

11.4.9.2 Static member functions [class.static.mfct]

[Note 1: 
The rules described in [class.mfct] apply to static member functions.
— end note]
[Note 2: 
A static member function does not have a this pointer ([expr.prim.this]).
A static member function cannot be qualified with const, volatile, or virtual ([dcl.fct]).
— end note]

11.4.9.3 Static data members [class.static.data]

A static data member is not part of the subobjects of a class.
If a static data member is declared thread_local there is one copy of the member per thread.
If a static data member is not declared thread_local there is one copy of the data member that is shared by all the objects of the class.
A static data member shall not be mutable ([dcl.stc]).
A static data member shall not be a direct member ([class.mem]) of an unnamed ([class.pre]) or local ([class.local]) class or of a (possibly indirectly) nested class ([class.nest]) thereof.
The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void.
[Note 1: 
The initializer in the definition of a static data member is in the scope of its class ([basic.scope.class]).
— end note]
[Example 1: class process { static process* run_chain; static process* running; }; process* process::running = get_main(); process* process::run_chain = running;
The definition of the static data member run_chain of class process inhabits the global scope; the notation process​::​run_chain indicates that the member run_chain is a member of class process and in the scope of class process.
In the static data member definition, the initializer expression refers to the static data member running of class process.
— end example]
[Note 2: 
Once the static data member has been defined, it exists even if no objects of its class have been created.
[Example 2: 
In the example above, run_chain and running exist even if no objects of class process are created by the program.
— end example]
The initialization and destruction of static data members is described in [basic.start.static], [basic.start.dynamic], and [basic.start.term].
— end note]
If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]).
The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.
The declaration of an inline static data member (which is a definition) may specify a brace-or-equal-initializer.
If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static.constexpr]).
Declarations of other static data members shall not specify a brace-or-equal-initializer.
[Note 3: 
There is exactly one definition of a static data member that is odr-used ([basic.def.odr]) in a valid program.
— end note]
[Note 4: 
Static data members of a class in namespace scope have the linkage of the name of the class ([basic.link]).
— end note]

11.4.10 Bit-fields [class.bit]

The optional attribute-specifier-seq appertains to the entity being declared.
A bit-field shall not be a static member.
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 constant-expression shall be an integral constant expression with a value greater than or equal to zero and is called the width of the bit-field.
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 ([basic.types.general]).
Allocation of bit-fields within a class object is implementation-defined.
Alignment of bit-fields is implementation-defined.
Bit-fields are packed into some addressable allocation unit.
[Note 1: 
Bit-fields straddle allocation units on some machines and not on others.
Bit-fields are assigned right-to-left on some machines, left-to-right on others.
— end note]
A declaration for a bit-field that omits the identifier declares an unnamed bit-field.
Unnamed bit-fields are not members and cannot be initialized.
An unnamed bit-field shall not be declared with a cv-qualified type.
[Note 2: 
An unnamed bit-field is useful for padding to conform to externally-imposed layouts.
— end note]
As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary.
Only when declaring an unnamed bit-field may the width be zero.
The address-of operator & shall not be applied to a bit-field, so there are no pointers to bit-fields.
A non-const reference shall not bind to a bit-field ([dcl.init.ref]).
[Note 3: 
If the initializer for a reference of type const T& is an lvalue that refers to a bit-field, the reference is bound to a temporary initialized to hold the value of the bit-field; the reference is not bound to the bit-field directly.
— end note]
If a value of integral type (other than bool) is stored into a bit-field of width N and the value would be representable in a hypothetical signed or unsigned integer type with width N and the same signedness as the bit-field's type, the original value and the value of the bit-field compare equal.
If the value true or false is stored into a bit-field of type bool of any size (including a one bit bit-field), the original bool value and the value of the bit-field compare equal.
If a value of an enumeration type is stored into a bit-field of the same type and the width is large enough to hold all the values of that enumeration type ([dcl.enum]), the original value and the value of the bit-field compare equal.
[Example 1: enum BOOL { FALSE=0, TRUE=1 }; struct A { BOOL b:1; }; A a; void f() { a.b = TRUE; if (a.b == TRUE) // yields true { /* ... */ } } — end example]

11.4.11 Allocation and deallocation functions [class.free]

Any allocation function for a class T is a static member (even if not explicitly declared static).
[Example 1: class Arena; struct B { void* operator new(std::size_t, Arena*); }; struct D1 : B { }; Arena* ap; void foo(int i) { new (ap) D1; // calls B​::​operator new(std​::​size_t, Arena*) new D1[i]; // calls ​::​operator new[](std​::​size_t) new D1; // error: ​::​operator new(std​::​size_t) hidden } — end example]
Any deallocation function for a class X is a static member (even if not explicitly declared static).
[Example 2: 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 example]
Since member allocation and deallocation functions are static they cannot be virtual.
[Note 1: 
However, when the cast-expression of a 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.
[Example 3: 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 D​::​operator delete(void*) bp = new E; delete bp; // 2: uses E​::​operator delete(E*, std​::​destroying_delete_t) }
Here, storage for the object of class D is deallocated by D​::​operator delete(), and the object of class E is destroyed and its storage is deallocated by E​::​operator delete(), due to the virtual destructor.
— end example]
— end note]
[Note 2: 
Virtual destructors have no effect on the deallocation function actually called when the cast-expression of a delete-expression refers to an array of objects of class type.
[Example 4: 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 D​::​operator delete[](void*, std​::​size_t) B* bp = new D[i]; delete[] bp; // undefined behavior } — end example]
— end note]
Access to the deallocation function is checked statically, even if a different one is actually executed.
[Example 5: 
For the call on line “// 1” above, if B​::​operator delete() had been private, the delete expression would have been ill-formed.
— end example]
[Note 3: 
If a deallocation function has no explicit noexcept-specifier, it has a non-throwing exception specification ([except.spec]).
— end note]

11.4.12 Nested class declarations [class.nest]

A class can be declared within another class.
A class declared within another is called a nested class.
[Note 1: 
See [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions.
— end note]
[Example 1: int x; int y; struct enclose { int x; static int s; struct inner { void f(int i) { int a = sizeof(x); // OK, operand of sizeof is an unevaluated operand x = i; // error: assign to enclose​::​x s = i; // OK, assign to enclose​::​s ::x = i; // OK, assign to global x y = i; // OK, assign to global y } void g(enclose* p, int i) { p->x = i; // OK, assign to enclose​::​x } }; }; inner* p = 0; // error: inner not found — end example]
[Note 2: 
Nested classes can be defined either in the enclosing class or in an enclosing namespace; member functions and static data members of a nested class can be defined either in the nested class or in an enclosing namespace scope.
[Example 2: struct enclose { struct inner { static int x; void f(int i); }; }; int enclose::inner::x = 1; void enclose::inner::f(int i) { /* ... */ } class E { class I1; // forward declaration of nested class class I2; class I1 { }; // definition of nested class }; class E::I2 { }; // definition of nested class — end example]
— end note]
A friend function ([class.friend]) defined within a nested class has no special access rights to members of an enclosing class.

11.5 Unions [class.union]

11.5.1 General [class.union.general]

A union is a class defined with the class-key union.
In a union, a non-static data member is active if its name refers to an object whose lifetime has begun and has not ended ([basic.life]).
At most one of the non-static data members of an object of union type can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
[Note 1: 
One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence ([class.mem]), and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, the common initial sequence of any of the standard-layout struct members can be inspected; see [class.mem].
— end note]
The size of a union is sufficient to contain the largest of its non-static data members.
Each non-static data member is allocated as if it were the sole member of a non-union class.
[Note 2: 
A union object and its non-static data members are pointer-interconvertible ([basic.compound], [expr.static.cast]).
As a consequence, all non-static data members of a union object have the same address.
— end note]
A union can have member functions (including constructors and destructors), but it shall not have virtual ([class.virtual]) functions.
A union shall not have base classes.
A union shall not be used as a base class.
If a union contains a non-static data member of reference type, the program is ill-formed.
[Note 3: 
Absent default member initializers ([class.mem]), if any non-static data member of a union has a non-trivial default constructor ([class.default.ctor]), copy constructor, move constructor ([class.copy.ctor]), copy assignment operator, move assignment operator ([class.copy.assign]), or destructor ([class.dtor]), the corresponding member function of the union must be user-provided or it will be implicitly deleted ([dcl.fct.def.delete]) for the union.
[Example 1: 
Consider the following union: union U { int i; float f; std::string s; };
Since std​::​string ([string.classes]) declares non-trivial versions of all of the special member functions, U will have an implicitly deleted default constructor, copy/move constructor, copy/move assignment operator, and destructor.
To use U, some or all of these member functions must be user-provided.
— end example]
— end note]
When the left operand of an assignment operator involves a member access expression ([expr.ref]) that nominates a union member, it may begin the lifetime of that union member, as described below.
For an expression E, define the set S(E) of subexpressions of E as follows:
  • If E is of the form A.B, S(E) contains the elements of S(A), and also contains A.B if B names a union member of a non-class, non-array type, or of a class type with a trivial default constructor that is not deleted, or an array of such types.
  • If E is of the form A[B] and is interpreted as a built-in array subscripting operator, S(E) is S(A) if A is of array type, S(B) if B is of array type, and empty otherwise.
  • Otherwise, S(E) is empty.
In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([expr.ass]) or a trivial assignment operator ([class.copy.assign]), for each element X of S(E1) and each anonymous union member X ([class.union.anon]) that is a member of a union and has such an element as an immediate subobject (recursively), if modification of X would have undefined behavior under [basic.life], an object of the type of X is implicitly created in the nominated storage; no initialization is performed and the beginning of its lifetime is sequenced after the value computation of the left and right operands and before the assignment.
[Note 4: 
This ends the lifetime of the previously-active member of the union, if any ([basic.life]).
— end note]
[Example 2: union A { int x; int y[4]; }; struct B { A a; }; 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(c.b.a.y[3]) contains c.b and c.b.a.y; // creates objects to hold union members c.b and c.b.a.y return c.b.a.y[3]; // OK, c.b.a.y refers to newly created object (see [basic.life]) } struct X { const int a; int b; }; union Y { X x; int k; }; void g() { Y y = { { 1, 2 } }; // OK, y.x is active union member ([class.mem]) int n = y.x.a; y.k = 4; // OK, ends lifetime of y.x, y.k is active member of union y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime, // S(y.x.b) is empty because X's default constructor is deleted, // so union member y.x's lifetime does not implicitly start } — end example]
[Note 5: 
In cases where the above rule does not apply, the active member of a union can only be changed by the use of a placement new-expression.
— end note]
[Example 3: 
Consider an object u of a union type U having non-static data members m of type M and n of type N.
If M has a non-trivial destructor and N has a non-trivial constructor (for instance, if they declare or inherit virtual functions), the active member of u can be safely switched from m to n using the destructor and placement new-expression as follows: u.m.~M(); new (&u.n) N;
— end example]

11.5.2 Anonymous unions [class.union.anon]

A union of the form
union { member-specification } ;
is called an anonymous union; it defines an unnamed type and an unnamed object of that type called an anonymous union member if it is a non-static data member or an anonymous union variable otherwise.
Each member-declaration in the member-specification of an anonymous union shall either define one or more public non-static data members or be a static_assert-declaration.
Nested types, anonymous unions, and functions shall not be declared within an anonymous union.
The names of the members of an anonymous union are bound in the scope inhabited by the union declaration.
[Example 1: void f() { union { int a; const char* p; }; a = 1; p = "Jennifer"; }
Here a and p are used like ordinary (non-member) variables, but since they are union members they have the same address.
— end example]
An anonymous union declared in the scope of a namespace with external linkage shall use the storage-class-specifier static.
Anonymous unions declared at block scope shall not use a storage-class-specifier that is not permitted in the declaration of a block variable.
An anonymous union declaration at class scope shall not have a storage-class-specifier.
[Note 1: 
A union for which objects, pointers, or references are declared is not an anonymous union.
[Example 2: void f() { union { int aa; char* p; } obj, *ptr = &obj; aa = 1; // error ptr->aa = 1; // OK }
The assignment to plain aa is ill-formed since the member name is not visible outside the union, and even if it were visible, it is not associated with any particular object.
— end example]
— end note]
[Note 2: 
Initialization of unions with no user-declared constructors is described in [dcl.init.aggr].
— end note]
A union-like class is a union or a class that has an anonymous union as a direct member.
A union-like class X has a set of variant members.
If X is a union, a non-static data member of X that is not an anonymous union is a variant member of X.
In addition, a non-static data member of an anonymous union that is a member of X is also a variant member of X.
At most one variant member of a union may have a default member initializer.
[Example 3: union U { int x = 0; union { int k; }; union { int z; int y = 1; // error: initialization for second variant member of U }; }; — end example]

11.6 Local class declarations [class.local]

A class can be declared within a function definition; such a class is called a local class.
[Note 1: 
A declaration in a local class cannot odr-use ([basic.def.odr]) a local entity from an enclosing scope.
— end note]
[Example 1: int x; void f() { static int s; int x; const int N = 5; extern int q(); int arr[2]; auto [y, z] = arr; struct local { int g() { return x; } // error: odr-use of non-odr-usable variable x 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* n() { return &N; } // error: odr-use of non-odr-usable variable N int p() { return y; } // error: odr-use of non-odr-usable structured binding y }; } local* p = 0; // error: local not found — end example]
An enclosing function has no special access to members of the local class; it obeys the usual access rules ([class.access]).
Member functions of a local class shall be defined within their class definition, if they are defined at all.
A class nested within a local class is a local class.
A member of a local class X shall be declared only in the definition of X or, if the member is a nested class, in the nearest enclosing block scope of X.
[Note 2: 
A local class cannot have static data members ([class.static.data]).
— end note]

11.7 Derived classes [class.derived]

11.7.1 General [class.derived.general]

The component names of a class-or-decltype are those of its nested-name-specifier, type-name, and/or simple-template-id.
A class-or-decltype shall denote a (possibly cv-qualified) class type that is not an incompletely defined class ([class.mem]); any cv-qualifiers are ignored.
The class denoted by the class-or-decltype of a base-specifier is called a direct base class for the class being defined.
The lookup for the component name of the type-name or simple-template-id is type-only ([basic.lookup]).
A class B is a base class of a class D if it is a direct base class of D or a direct base class of one of D's base classes.
A class is an indirect base class of another if it is a base class but not a direct base class.
A class is said to be (directly or indirectly) derived from its (direct or indirect) base classes.
[Note 1: 
See [class.access] for the meaning of access-specifier.
— end note]
Members of a base class are also members of the derived class.
[Note 2: 
Constructors of a base class can be explicitly inherited ([namespace.udecl]).
Base class members can be referred to in expressions in the same manner as other members of the derived class, unless their names are hidden or ambiguous ([class.member.lookup]).
The scope resolution operator ​::​ ([expr.prim.id.qual]) can be used to refer to a direct or indirect base member explicitly, even if it is hidden in the derived class.
A derived class can itself serve as a base class subject to access control; see [class.access.base].
A pointer to a derived class can be implicitly converted to a pointer to an accessible unambiguous base class ([conv.ptr]).
An lvalue of a derived class type can be bound to a reference to an accessible unambiguous base class ([dcl.init.ref]).
— end note]
The base-specifier-list specifies the type of the base class subobjects contained in an object of the derived class type.
[Example 1: struct Base { int a, b, c; };
struct Derived : Base { int b; };
struct Derived2 : Derived { int c; };
Here, an object of class Derived2 will have a subobject of class Derived which in turn will have a subobject of class Base.
— end example]
A base-specifier followed by an ellipsis is a pack expansion ([temp.variadic]).
The order in which the base class subobjects are allocated in the most derived object ([intro.object]) is unspecified.
[Note 3: 
A derived class and its base class subobjects can be represented by a directed acyclic graph (DAG) where an arrow means “directly derived from” (see Figure 3).
An arrow need not have a physical representation in memory.
A DAG of subobjects is often referred to as a “subobject lattice”.
— end note]
dag Base Base Derived1 Derived1 Derived1->Base Derived2 Derived2 Derived2->Derived1
Figure 3 — Directed acyclic graph  [fig:class.dag]
[Note 4: 
Initialization of objects representing base classes can be specified in constructors; see [class.base.init].
— end note]
[Note 5: 
A base class subobject can have a layout different from the layout of a most derived object of the same type.
A base class subobject can have a polymorphic behavior ([class.cdtor]) different from the polymorphic behavior of a most derived object of the same type.
A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address ([intro.object]).
— end note]

11.7.2 Multiple base classes [class.mi]

A class can be derived from any number of base classes.
[Note 1: 
The use of more than one direct base class is often called multiple inheritance.
— end note]
[Example 1: class A { /* ... */ }; class B { /* ... */ }; class C { /* ... */ }; class D : public A, public B, public C { /* ... */ }; — end example]
[Note 2: 
The order of derivation is not significant except as specified by the semantics of initialization by constructor ([class.base.init]), cleanup ([class.dtor]), and storage layout ([class.mem], [class.access.spec]).
— end note]
A class shall not be specified as a direct base class of a derived class more than once.
[Note 3: 
A class can be an indirect base class more than once and can be a direct and an indirect base class.
There are limited things that can be done with such a class; lookup that finds its non-static data members and member functions in the scope of the derived class will be ambiguous.
However, the static members, enumerations and types can be unambiguously referred to.
— end note]
[Example 2: class X { /* ... */ }; class Y : public X, public X { /* ... */ }; // error class L { public: int next; /* ... */ }; class A : public L { /* ... */ }; class B : public L { /* ... */ }; class C : public A, public B { void f(); /* ... */ }; // well-formed class D : public A, public L { void f(); /* ... */ }; // well-formed — end example]
A base class specifier that does not contain the keyword virtual specifies a non-virtual base class.
A base class specifier that contains the keyword virtual specifies a virtual base class.
For each distinct occurrence of a non-virtual base class in the class lattice of the most derived class, the most derived object ([intro.object]) shall contain a corresponding distinct base class subobject of that type.
For each distinct base class that is specified virtual, the most derived object shall contain a single base class subobject of that type.
[Note 4: 
For an object of class type C, each distinct occurrence of a (non-virtual) base class L in the class lattice of C corresponds one-to-one with a distinct L subobject within the object of type C.
Given the class C defined above, an object of class C will have two subobjects of class L as shown in Figure 4.
nonvirt L1 L L2 L A A A->L1 B B B->L2 C C C->A C->B
Figure 4 — Non-virtual base  [fig:class.nonvirt]
In such lattices, explicit qualification can be used to specify which subobject is meant.
The body of function C​::​f can refer to the member next of each L subobject: void C::f() { A::next = B::next; } // well-formed
Without the A​::​ or B​::​ qualifiers, the definition of C​::​f above would be ill-formed because of ambiguity ([class.member.lookup]).
— end note]
[Note 5: 
In contrast, consider the case with a virtual base class: class V { /* ... */ }; class A : virtual public V { /* ... */ }; class B : virtual public V { /* ... */ }; class C : public A, public B { /* ... */ };
virt V V A A A->V B B B->V C C C->A C->B
Figure 5 — Virtual base  [fig:class.virt]
For an object c of class type C, a single subobject of type V is shared by every base class subobject of c that has a virtual base class of type V.
Given the class C defined above, an object of class C will have one subobject of class V, as shown in Figure 5.
— end note]
[Note 6: 
A class can have both virtual and non-virtual base classes of a given type.
class B { /* ... */ }; class X : virtual public B { /* ... */ }; class Y : virtual public B { /* ... */ }; class Z : public B { /* ... */ }; class AA : public X, public Y, public Z { /* ... */ };
For an object of class AA, all virtual occurrences of base class B in the class lattice of AA correspond to a single B subobject within the object of type AA, and every other occurrence of a (non-virtual) base class B in the class lattice of AA corresponds one-to-one with a distinct B subobject within the object of type AA.
Given the class AA defined above, class AA has two subobjects of class B: Z's B and the virtual B shared by X and Y, as shown in Figure 6.
virtnonvirt B1 B B2 B AA AA X X AA->X Y Y AA->Y Z Z AA->Z X->B1 Y->B1 Z->B2
Figure 6 — Virtual and non-virtual base  [fig:class.virtnonvirt]
— end note]

11.7.3 Virtual functions [class.virtual]

A non-static member function is a virtual function if it is first declared with the keyword virtual or if it overrides a virtual member function declared in a base class (see below).92
[Note 1: 
Virtual functions support dynamic binding and object-oriented programming.
— end note]
A class with a virtual member function is called a polymorphic class.93
If a virtual member function F is declared in a class B, and, in a class D derived (directly or indirectly) from B, a declaration of a member function G corresponds ([basic.scope.scope]) to a declaration of F, ignoring trailing requires-clauses, then G overrides94 F.
For convenience, we say that any virtual function overrides itself.
A virtual member function V of a class object S is a final overrider unless the most derived class ([intro.object]) of which S is a base class subobject (if any) has another member function that overrides V.
In a derived class, if a virtual member function of a base class subobject has more than one final overrider, the program is ill-formed.
[Example 1: struct A { virtual void f(); }; struct B : virtual A { virtual void f(); }; struct C : B , virtual A { using A::f; }; void foo() { C c; c.f(); // calls B​::​f, the final overrider c.C::f(); // calls A​::​f because of the using-declaration } — end example]
[Example 2: struct A { virtual void f(); }; struct B : A { }; struct C : A { void f(); }; struct D : B, C { }; // OK, A​::​f and C​::​f are the final overriders // for the B and C subobjects, respectively — end example]
[Note 2: 
A virtual member function does not have to be visible to be overridden, for example, struct B { virtual void f(); }; struct D : B { void f(int); }; struct D2 : D { void f(); }; the function f(int) in class D hides the virtual function f() in its base class B; D​::​f(int) is not a virtual function.
However, f() declared in class D2 has the same name and the same parameter list as B​::​f(), and therefore is a virtual function that overrides the function B​::​f() even though B​::​f() is not visible in class D2.
— end note]
If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived from B a function D​::​f overrides B​::​f, the program is ill-formed.
[Example 3: struct B { virtual void f() const final; }; struct D : B { void f() const; // error: D​::​f attempts to override final B​::​f }; — end example]
If a virtual function is marked with the virt-specifier override and does not override a member function of a base class, the program is ill-formed.
[Example 4: struct B { virtual void f(int); }; struct D : B { virtual void f(long) override; // error: wrong signature overriding B​::​f virtual void f(int) override; // OK }; — end example]
A virtual function shall not have a trailing requires-clause ([dcl.decl]).
[Example 5: template<typename T> struct A { virtual void f() requires true; // error: virtual function cannot be constrained ([temp.constr.decl]) }; — end example]
The ref-qualifier, or lack thereof, of an overriding function shall be the same as that of the overridden function.
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions.
If a function D​::​f overrides a function B​::​f, the return types of the functions are covariant if they satisfy the following criteria:
  • both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes95
  • the class in the return type of B​::​f is the same class as the class in the return type of D​::​f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D​::​f
  • both pointers or references have the same cv-qualification and the class type in the return type of D​::​f has the same cv-qualification as or less cv-qualification than the class type in the return type of B​::​f.
If the class type in the covariant return type of D​::​f differs from that of B​::​f, the class type in the return type of D​::​f shall be complete at the locus ([basic.scope.pdecl]) of the overriding declaration or shall be the class type D.
When the overriding function is called as the final overrider of the overridden function, its result is converted to the type returned by the (statically chosen) overridden function ([expr.call]).
[Example 6: class B { }; class D : private B { friend class Derived; }; struct Base { virtual void vf1(); virtual void vf2(); virtual void vf3(); virtual B* vf4(); virtual B* vf5(); void f(); }; struct No_good : public Base { D* vf4(); // error: B (base class of D) inaccessible }; class A; struct Derived : public Base { void vf1(); // virtual and overrides Base​::​vf1() void vf2(int); // not virtual, hides Base​::​vf2() char vf3(); // error: invalid difference in return type only D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete class void f(); }; void g() { Derived d; Base* bp = &d; // standard conversion: // Derived* to Base* bp->vf1(); // calls Derived​::​vf1() bp->vf2(); // calls Base​::​vf2() bp->f(); // calls Base​::​f() (not virtual) B* p = bp->vf4(); // calls Derived​::​vf4() and converts the // result to B* Derived* dp = &d; D* q = dp->vf4(); // calls Derived​::​vf4() and does not // convert the result to B* dp->vf2(); // error: argument mismatch } — end example]
[Note 3: 
The interpretation of the call of a virtual function depends on the type of the object for which it is called (the dynamic type), whereas the interpretation of a call of a non-virtual member function depends only on the type of the pointer or reference denoting that object (the static type) ([expr.call]).
— end note]
[Note 4: 
The virtual specifier implies membership, so a virtual function cannot be a non-member ([dcl.fct.spec]) function.
Nor can a virtual function be a static member, since a virtual function call relies on a specific object for determining which function to invoke.
A virtual function declared in one class can be declared a friend ([class.friend]) in another class.
— end note]
A virtual function declared in a class shall be defined, or declared pure ([class.abstract]) in that class, or both; no diagnostic is required ([basic.def.odr]).
[Example 7: 
Here are some uses of virtual functions with multiple base classes: struct A { virtual void f(); }; struct B1 : A { // note non-virtual derivation void f(); }; struct B2 : A { void f(); }; struct D : B1, B2 { // D has two separate A subobjects }; void foo() { D d; // A* ap = &d; // would be ill-formed: ambiguous B1* b1p = &d; A* ap = b1p; D* dp = &d; ap->f(); // calls D​::​B1​::​f dp->f(); // error: ambiguous }
In class D above there are two occurrences of class A and hence two occurrences of the virtual member function A​::​f.
The final overrider of B1​::​A​::​f is B1​::​f and the final overrider of B2​::​A​::​f is B2​::​f.
— end example]
[Example 8: 
The following example shows a function that does not have a unique final overrider: struct A { virtual void f(); }; struct VB1 : virtual A { // note virtual derivation void f(); }; struct VB2 : virtual A { void f(); }; struct Error : VB1, VB2 { // error }; struct Okay : VB1, VB2 { void f(); };
Both VB1​::​f and VB2​::​f override A​::​f but there is no overrider of both of them in class Error.
This example is therefore ill-formed.
Class Okay is well-formed, however, because Okay​::​f is a final overrider.
— end example]
[Example 9: 
The following example uses the well-formed classes from above.
struct VB1a : virtual A { // does not declare f }; struct Da : VB1a, VB2 { }; void foe() { VB1a* vb1ap = new Da; vb1ap->f(); // calls VB2​::​f } — end example]
Explicit qualification with the scope operator ([expr.prim.id.qual]) suppresses the virtual call mechanism.
[Example 10: class B { public: virtual void f(); }; class D : public B { public: void f(); }; void D::f() { /* ... */ B::f(); }
Here, the function call in D​::​f really does call B​::​f and not D​::​f.
— end example]
A deleted function ([dcl.fct.def]) shall not override a function that is not deleted.
Likewise, a function that is not deleted shall not override a deleted function.
A consteval virtual function shall not override a virtual function that is not consteval.
A consteval virtual function shall not be overridden by a virtual function that is not consteval.
92)92)
The use of the virtual specifier in the declaration of an overriding function is valid but redundant (has empty semantics).
93)93)
If all virtual functions are immediate functions, the class is still polymorphic even if its internal representation does not otherwise require any additions for that polymorphic behavior.
94)94)
A function with the same name but a different parameter list ([over]) as a virtual function is not necessarily virtual and does not override.
Access control ([class.access]) is not considered in determining overriding.
95)95)
Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.

11.7.4 Abstract classes [class.abstract]

[Note 1: 
The abstract class mechanism supports the notion of a general concept, such as a shape, of which only more concrete variants, such as circle and square, can actually be used.
An abstract class can also be used to define an interface for which derived classes provide a variety of implementations.
— end note]
A virtual function is specified as a pure virtual function by using a pure-specifier ([class.mem]) in the function declaration in the class definition.
[Note 2: 
Such a function might be inherited: see below.
— end note]
A class is an abstract class if it has at least one pure virtual function.
[Note 3: 
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 ([basic.def], [class.mem]).
— end note]
A pure virtual function need be defined only if called with, or as if with ([class.dtor]), the qualified-id syntax ([expr.prim.id.qual]).
[Example 1: class point { /* ... */ }; class shape { // abstract class point center; public: point where() { return center; } void move(point p) { center=p; draw(); } virtual void rotate(int) = 0; // pure virtual virtual void draw() = 0; // pure virtual }; — end example]
[Note 4: 
A function declaration cannot provide both a pure-specifier and a definition.
— end note]
[Example 2: struct C { virtual void f() = 0 { }; // error }; — end example]
[Note 5: 
An abstract class type cannot be used as a parameter or return type of a function being defined ([dcl.fct]) or called ([expr.call]), except as specified in [dcl.type.simple].
Further, an abstract class type cannot be used as the type of an explicit type conversion ([expr.static.cast], [expr.reinterpret.cast], [expr.const.cast]), because the resulting prvalue would be of abstract class type ([basic.lval]).
However, pointers and references to abstract class types can appear in such contexts.
— end note]
A class is abstract if it has at least one pure virtual function for which the final overrider is pure virtual.
[Example 3: class ab_circle : public shape { int radius; public: void rotate(int) { } // ab_circle​::​draw() is a pure virtual };
Since shape​::​draw() is a pure virtual function ab_circle​::​draw() is a pure virtual by default.
The alternative declaration, class circle : public shape { int radius; public: void rotate(int) { } void draw(); // a definition is required somewhere }; would make class circle non-abstract and a definition of circle​::​draw() must be provided.
— end example]
[Note 6: 
An abstract class can be derived from a class that is not abstract, and a pure virtual function can override a virtual function which is not pure.
— end note]
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call ([class.virtual]) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.

11.8 Member access control [class.access]

11.8.1 General [class.access.general]

A member of a class can be
  • private, that is, it can be named only by members and friends of the class in which it is declared;
  • protected, that is, it can be named only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see [class.protected]); or
  • public, that is, it can be named anywhere without access restriction.
[Note 1: 
A constructor or destructor can be named by an expression ([basic.def.odr]) even though it has no name.
— end note]
A member of a class can also access all the members to which the class has access.
A local class of a member function may access the same members that the member function itself may access.96
Members of a class defined with the keyword class are private by default.
Members of a class defined with the keywords struct or union are public by default.
[Example 1: class X { int a; // X​::​a is private by default }; struct S { int a; // S​::​a is public by default }; — end example]
Access control is applied uniformly to declarations and expressions.
[Note 2: 
Access control applies to members nominated by friend declarations ([class.friend]) and using-declarations ([namespace.udecl]).
— end note]
When a using-declarator is named, access control is applied to it, not to the declarations that replace it.
For an overload set, access control is applied only to the function selected by overload resolution.
[Example 2: struct S { void f(int); private: void f(double); }; void g(S* sp) { sp->f(2); // OK, access control applied after overload resolution } — end example]
[Note 3: 
Because access control applies to the declarations named, if access control is applied to a typedef-name, only the accessibility of the typedef or alias declaration itself is considered.
The accessibility of the entity referred to by the typedef-name is not considered.
[Example 3: class A { class B { }; public: typedef B BB; }; void f() { A::BB x; // OK, typedef A​::​BB is public A::B y; // access error, A​::​B is private } — end example]
— end note]
[Note 4: 
Access control does not prevent members from being found by name lookup or implicit conversions to base classes from being considered.
— end note]
The interpretation of a given construct is established without regard to access control.
If the interpretation established makes use of inaccessible members or base classes, the construct is ill-formed.
All access controls in [class.access] affect the ability to name a class member from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification.
[Note 5: 
This access also applies to implicit references to constructors, conversion functions, and destructors.
— end note]
[Example 4: class A { typedef int I; // private member I f(); friend I g(I); static I x; template<int> struct Q; template<int> friend struct R; protected: struct B { }; }; A::I A::f() { return 0; } A::I g(A::I p = A::x); A::I g(A::I p) { return 0; } A::I A::x = 0; template<A::I> struct A::Q { }; template<A::I> struct R { }; struct D: A::B, A { };
Here, all the uses of A​::​I are well-formed because A​::​f, A​::​x, and A​::​Q are members of class A and g and R are friends of class A.
This implies, for example, that access checking on the first use of A​::​I must be deferred until it is determined that this use of A​::​I is as the return type of a member of class A.
Similarly, the use of A​::​B as a base-specifier is well-formed because D is derived from A, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen.
— end example]
Access is checked for a default argument ([dcl.fct.default]) at the point of declaration, rather than at any points of use of the default argument.
Access checking for default arguments in function templates and in member functions of class templates is performed as described in [temp.inst].
Access for a default template-argument ([temp.param]) is checked in the context in which it appears rather than at any points of use of it.
[Example 5: class B { }; template <class T> class C { protected: typedef T TT; }; template <class U, class V = typename U::TT> class D : public U { }; D <C<B> >* d; // access error, C​::​TT is protected — end example]
96)96)
Access permissions are thus transitive and cumulative to nested and local classes.

11.8.2 Access specifiers [class.access.spec]

Member declarations can be labeled by an access-specifier ([class.derived]):
An access-specifier specifies the access rules for members following it until the end of the class or until another access-specifier is encountered.
[Example 1: class X { int a; // X​::​a is private by default: class used public: int b; // X​::​b is public int c; // X​::​c is public }; — end example]
Any number of access specifiers is allowed and no particular order is required.
[Example 2: struct S { int a; // S​::​a is public by default: struct used protected: int b; // S​::​b is protected private: int c; // S​::​c is private public: int d; // S​::​d is public }; — end example]
When a member is redeclared within its class definition, the access specified at its redeclaration shall be the same as at its initial declaration.
[Example 3: struct S { class A; enum E : int; private: class A { }; // error: cannot change access enum E: int { e0 }; // error: cannot change access }; — end example]
[Note 1: 
In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared.
The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared.
— end note]
[Example 4: class A { }; class B : private A { }; class C : public B { A* p; // error: injected-class-name A is inaccessible ::A* q; // OK }; — end example]

11.8.3 Accessibility of base classes and base class members [class.access.base]

If a class is declared to be a base class ([class.derived]) for another class using the public access specifier, the public members of the base class are accessible as public members of the derived class and protected members of the base class are accessible as protected members of the derived class.
If a class is declared to be a base class for another class using the protected access specifier, the public and protected members of the base class are accessible as protected members of the derived class.
If a class is declared to be a base class for another class using the private access specifier, the public and protected members of the base class are accessible as private members of the derived class.97
In the absence of an access-specifier for a base class, public is assumed when the derived class is defined with the class-key struct and private is assumed when the class is defined with the class-key class.
[Example 1: class B { /* ... */ }; class D1 : private B { /* ... */ }; class D2 : public B { /* ... */ }; class D3 : B { /* ... */ }; // B private by default struct D4 : public B { /* ... */ }; struct D5 : private B { /* ... */ }; struct D6 : B { /* ... */ }; // B public by default class D7 : protected B { /* ... */ }; struct D8 : protected B { /* ... */ };
Here B is a public base of D2, D4, and D6, a private base of D1, D3, and D5, and a protected base of D7 and D8.
— end example]
[Note 1: 
A member of a private base class can be inaccessible as inherited, but accessible directly.
Because of the rules on pointer conversions ([conv.ptr]) and explicit casts ([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.
[Example 2: class B { public: int mi; // non-static member static int si; // static member }; class D : private B { }; class DD : public D { void f(); }; void DD::f() { mi = 3; // error: mi is private in D si = 3; // error: si is private in D ::B b; b.mi = 3; // OK (b.mi is different from this->mi) b.si = 3; // OK (b.si is different from this->si) ::B::si = 3; // OK ::B* bp1 = this; // error: B is a private base class ::B* bp2 = (::B*)this; // OK with cast bp2->mi = 3; // OK, access through a pointer to B. } — end example]
— end note]
A base class B of N is accessible at R, if
  • an invented public member of B would be a public member of N, or
  • R occurs in a direct member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a direct member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R.
[Example 3: class B { public: int m; }; class S: private B { friend class N; }; class N: private S { void f() { B* p = this; // OK because class S satisfies the fourth condition above: B is a base class of N // accessible in f() because B is an accessible base class of S and S is an accessible // base class of N. } }; — end example]
If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class ([conv.ptr], [conv.mem]).
[Note 2: 
It follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X.
— end note]
The access to a member is affected by the class in which the member is named.
This naming class is the class in whose scope name lookup performed a search that found the member.
[Note 3: 
This class can be explicit, e.g., when a qualified-id is used, or implicit, e.g., when a class member access operator ([expr.ref]) is used (including cases where an implicit “this->” is added).
If both a class member access operator and a qualified-id are used to name the member (as in p->T​::​m), the class naming the member is the class denoted by the nested-name-specifier of the qualified-id (that is, T).
— end note]
A member m is accessible at the point R when named in class N if
  • m as a member of N is public, or
  • m as a member of N is private, and R occurs in a direct member or friend of class N, or
  • m as a member of N is protected, and R occurs in a direct member or friend of class N, or in a member of a class P derived from N, where m as a member of P is public, private, or protected, or
  • there exists a base class B of N that is accessible at R, and m is accessible at R when named in class B.
    [Example 4: class B; class A { private: int i; friend void f(B*); }; class B : public A { }; void f(B* p) { p->i = 1; // OK, B* can be implicitly converted to A*, and f has access to i in A } — end example]
If a class member access operator, including an implicit “this->”, is used to access a non-static data member or non-static member function, the reference is ill-formed if the left operand (considered as a pointer in the “.” operator case) cannot be implicitly converted to a pointer to the naming class of the right operand.
[Note 4: 
This requirement is in addition to the requirement that the member be accessible as named.
— end note]
97)97)
As specified previously in [class.access], private members of a base class remain inaccessible even to derived classes unless friend declarations within the base class definition are used to grant access explicitly.

11.8.4 Friends [class.friend]

A friend of a class is a function or class that is given permission to name the private and protected members of the class.
A class specifies its friends, if any, by way of friend declarations.
Such declarations give special access rights to the friends, but they do not make the nominated friends members of the befriending class.
[Example 1: 
The following example illustrates the differences between members and friends: class X { int a; friend void friend_set(X*, int); public: void member_set(int); }; void friend_set(X* p, int i) { p->a = i; } void X::member_set(int i) { a = i; } void f() { X obj; friend_set(&obj,10); obj.member_set(10); }
— end example]
Declaring a class to be a friend implies that private and protected members of the class granting friendship can be named in the base-specifiers and member declarations of the befriended class.
[Example 2: class A { class B { }; friend class X; }; struct X : A::B { // OK, A​::​B accessible to friend A::B mx; // OK, A​::​B accessible to member of friend class Y { A::B my; // OK, A​::​B accessible to nested member of friend }; }; — end example]
[Example 3: class X { enum { a=100 }; friend class Y; }; class Y { int v[X::a]; // OK, Y is a friend of X }; class Z { int v[X::a]; // error: X​::​a is private }; — end example]
A friend declaration that does not declare a function shall be a friend-type-declaration.
[Note 1: 
A friend declaration can be the declaration in a template-declaration ([temp.pre], [temp.friend]).
— end note]
If a friend-type-specifier in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend-type-specifier is ignored.
[Example 4: class C; typedef C Ct; class E; class X1 { friend C; // OK, class C is a friend }; class X2 { friend Ct; // OK, class C is a friend friend D; // error: D not found friend class D; // OK, elaborated-type-specifier declares new class }; template <typename ... Ts> class R { friend Ts...; }; template <class... Ts, class... Us> class R<R<Ts...>, R<Us...>> { friend Ts::Nested..., Us...; }; R<C> rc; // class C is a friend of R<C> R<C, E> rce; // classes C and E are friends of R<C, E> R<int> Ri; // OK, “friend int;'' is ignored struct E { struct Nested; }; R<R<E>, R<C, int>> rr; // E​::​Nested and C are friends of R<R<E>, R<C, int>> — end example]
[Note 2: 
A friend declaration refers to an entity, not (all overloads of) a name.
A member function of a class X can be a friend of a class Y.
[Example 5: class Y { friend char* X::foo(int); friend X::X(char); // constructors can be friends friend X::~X(); // destructors can be friends }; — end example]
— end note]
A function may be defined in a friend declaration of a class if and only if the class is a non-local class ([class.local]) and the function name is unqualified.
[Example 6: class M { friend void f() { } // definition of global f, a friend of M, // not the definition of a member function }; — end example]
Such a function is implicitly an inline ([dcl.inline]) function if it is attached to the global module.
[Note 3: 
If a friend function is defined outside a class, it is not in the scope of the class.
— end note]
No storage-class-specifier shall appear in the decl-specifier-seq of a friend declaration.
A member nominated by a friend declaration shall be accessible in the class containing the friend declaration.
The meaning of the friend declaration is the same whether the friend declaration appears in the private, protected, or public ([class.mem]) portion of the class member-specification.
Friendship is neither inherited nor transitive.
[Example 7: class A { friend class B; int a; }; class B { friend class C; }; class C { void f(A* p) { p->a++; // error: C is not a friend of A despite being a friend of a friend } }; class D : public B { void f(A* p) { p->a++; // error: D is not a friend of A despite being derived from a friend } }; — end example]
[Note 4: 
A friend declaration never binds any names ([dcl.meaning], [dcl.type.elab]).
— end note]
[Example 8: // Assume f and g have not yet been declared. void h(int); template <class T> void f2(T); namespace A { class X { friend void f(X); // A​::​f(X) is a friend class Y { friend void g(); // A​::​g is a friend friend void h(int); // A​::​h is a friend // ​::​h not considered friend void f2<>(int); // ​::​f2<>(int) is a friend }; }; // A​::​f, A​::​g and A​::​h are not visible here X x; void g() { f(x); } // definition of A​::​g void f(X) { /* ... */ } // definition of A​::​f void h(int) { /* ... */ } // definition of A​::​h // A​::​f, A​::​g and A​::​h are visible here and known to be friends } using A::x; void h() { A::f(x); A::X::f(x); // error: f is not a member of A​::​X A::X::Y::g(); // error: g is not a member of A​::​X​::​Y } — end example]
[Example 9: class X; void a(); void f() { class Y; extern void b(); class A { friend class X; // OK, but X is a local class, not ​::​X friend class Y; // OK friend class Z; // OK, introduces local class Z friend void a(); // error, ​::​a is not considered friend void b(); // OK friend void c(); // error }; X* px; // OK, but ​::​X is found Z* pz; // error: no Z is found } — end example]

11.8.5 Protected member access [class.protected]

An additional access check beyond those described earlier in [class.access] is applied when a non-static data member or non-static member function is a protected member of its naming class ([class.access.base]).98
As described earlier, access to a protected member is granted because the reference occurs in a friend or direct member of some class C.
If the access is to form a pointer to member ([expr.unary.op]), the nested-name-specifier shall denote C or a class derived from C.
All other accesses involve a (possibly implicit) object expression ([expr.ref]).
In this case, the class of the object expression shall be C or a class derived from C.
[Example 1: class B { protected: int i; static int j; }; class D1 : public B { }; class D2 : public B { friend void fr(B*,D1*,D2*); void mem(B*,D1*); }; void fr(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // OK (access through a D2) p2->B::i = 4; // OK (access through a D2, even though naming class is B) int B::* pmi_B = &B::i; // error int B::* pmi_B2 = &D2::i; // OK (type of &D2​::​i is int B​::​*) B::j = 5; // error: not a friend of naming class B D2::j = 6; // OK (because refers to static member) } void D2::mem(B* pb, D1* p1) { pb->i = 1; // error p1->i = 2; // error i = 3; // OK (access through this) B::i = 4; // OK (access through this, qualification ignored) int B::* pmi_B = &B::i; // error int B::* pmi_B2 = &D2::i; // OK j = 5; // OK (because j refers to static member) B::j = 6; // OK (because B​::​j refers to static member) } void g(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // error } — end example]
98)98)
This additional check does not apply to other members, e.g., static data members or enumerator member constants.

11.8.6 Access to virtual functions [class.access.virt]

The access rules ([class.access]) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it.
[Example 1: class B { public: virtual int f(); }; class D : public B { private: int f(); }; void f() { D d; B* pb = &d; D* pd = &d; pb->f(); // OK, B​::​f() is public, D​::​f() is invoked pd->f(); // error: D​::​f() is private } — end example]
Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above).
The access of the member function in the class in which it was defined (D in the example above) is in general not known.

11.8.7 Multiple access [class.paths]

If a declaration can be reached by several paths through a multiple inheritance graph, the access is that of the path that gives most access.
[Example 1: class W { public: void f(); }; class A : private virtual W { }; class B : public virtual W { }; class C : public A, public B { void f() { W::f(); } // OK };
Since W​::​f() is available to C​::​f() along the public path through B, access is allowed.
— end example]

11.8.8 Nested classes [class.access.nest]

A nested class is a member and as such has the same access rights as any other member.
The members of an enclosing class have no special access to members of a nested class; the usual access rules ([class.access]) shall be obeyed.
[Example 1: class E { int x; class B { }; class I { B b; // OK, E​::​I can access E​::​B int y; void f(E* p, int i) { p->x = i; // OK, E​::​I can access E​::​x } }; int g(I* p) { return p->y; // error: I​::​y is private } }; — end example]

11.9 Initialization [class.init]

11.9.1 General [class.init.general]

When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form (), the object is initialized as specified in [dcl.init].
An object of class type (or array thereof) can be explicitly initialized; see [class.expl.init] and [class.base.init].
When an array of class objects is initialized (either explicitly or implicitly) and the elements are initialized by constructor, the constructor shall be called for each element of the array, following the subscript order; see [dcl.array].
[Note 1: 
Destructors for the array elements are called in reverse order of their construction.
— end note]

11.9.2 Explicit initialization [class.expl.init]

An object of class type can be initialized with a parenthesized expression-list, where the expression-list is construed as an argument list for a constructor that is called to initialize the object.
Alternatively, a single assignment-expression can be specified as an initializer using the = form of initialization.
Either direct-initialization semantics or copy-initialization semantics apply; see [dcl.init].
[Example 1: struct complex { complex(); complex(double); complex(double,double); }; complex sqrt(complex,complex); complex a(1); // initialized by calling complex(double) with argument 1 complex b = a; // initialized as a copy of a complex c = complex(1,2); // initialized by calling complex(double,double) with arguments 1 and 2 complex d = sqrt(b,c); // initialized by calling sqrt(complex,complex) with d as its result object complex e; // initialized by calling complex() complex f = 3; // initialized by calling complex(double) with argument 3 complex g = { 1, 2 }; // initialized by calling complex(double, double) with arguments 1 and 2 — end example]
[Note 1: 
Overloading of the assignment operator ([over.ass]) has no effect on initialization.
— end note]
An object of class type can also be initialized by a braced-init-list.
List-initialization semantics apply; see [dcl.init] and [dcl.init.list].
[Example 2: complex v[6] = { 1, complex(1,2), complex(), 2 };
Here, complex​::​complex(double) is called for the initialization of v[0] and v[3], complex​::​complex(double, double) is called for the initialization of v[1], complex​::​complex() is called for the initialization of v[2], v[4], and v[5].
For another example,
struct X { int i; float f; complex c; } x = { 99, 88.8, 77.7 };
Here, x.i is initialized with 99, x.f is initialized with 88.8, and complex​::​complex(double) is called for the initialization of x.c.
— end example]
[Note 2: 
Braces can be elided in the initializer-list for any aggregate, even if the aggregate has members of a class type with user-defined type conversions; see [dcl.init.aggr].
— end note]
[Note 3: 
If T is a class type with no default constructor, any declaration of an object of type T (or array thereof) is ill-formed if no initializer is explicitly specified (see [class.init] and [dcl.init]).
— end note]
[Note 4: 
The order in which objects with static or thread storage duration are initialized is described in [basic.start.dynamic] and [stmt.dcl].
— end note]

11.9.3 Initializing bases and members [class.base.init]

In the definition of a constructor for a class, initializers for direct and virtual base class subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Lookup for an unqualified name in a mem-initializer-id ignores the constructor's function parameter scope.
[Note 1: 
If the constructor's class contains a member with the same name as a direct or virtual base class of the class, a mem-initializer-id naming the member or base class and composed of a single identifier refers to the class member.
A mem-initializer-id for the hidden base class can be specified using a qualified name.
— end note]
Unless the mem-initializer-id names the constructor's class, a non-static data member of the constructor's class, or a direct or virtual base of that class, the mem-initializer is ill-formed.
A mem-initializer-list can initialize a base class using any class-or-decltype that denotes that base class type.
[Example 1: struct A { A(); }; typedef A global_A; struct B { }; struct C: public A, public B { C(); }; C::C(): global_A() { } // mem-initializer for base A — end example]
If a mem-initializer-id is ambiguous because it designates both a direct non-virtual base class and an indirect virtual base class, the mem-initializer is ill-formed.
[Example 2: struct A { A(); }; struct B: public virtual A { }; struct C: public A, public B { C(); }; C::C(): A() { } // error: which A? — end example]
A ctor-initializer may initialize a variant member of the constructor's class.
If a ctor-initializer specifies more than one mem-initializer for the same member or for the same base class, the ctor-initializer is ill-formed.
A mem-initializer-list can delegate to another constructor of the constructor's class using any class-or-decltype that denotes the constructor's class itself.
If a mem-initializer-id designates the constructor's class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the mem-initializer is the target constructor.
The target constructor is selected by overload resolution.
Once the target constructor returns, the body of the delegating constructor is executed.
If a constructor delegates to itself directly or indirectly, the program is ill-formed, no diagnostic required.
[Example 3: struct C { C( int ) { } // #1: non-delegating constructor C(): C(42) { } // #2: delegates to #1 C( char c ) : C(42.0) { } // #3: ill-formed due to recursion with #4 C( double d ) : C('a') { } // #4: ill-formed due to recursion with #3 }; — end example]
The expression-list or braced-init-list in a mem-initializer is used to initialize the designated subobject (or, in the case of a delegating constructor, the complete class object) according to the initialization rules of [dcl.init] for direct-initialization.
[Example 4: struct B1 { B1(int); /* ... */ }; struct B2 { B2(int); /* ... */ }; struct D : B1, B2 { D(int); B1 b; const int c; }; D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ } D d(10); — end example]
[Note 2: 
The initialization performed by each mem-initializer constitutes a full-expression ([intro.execution]).
Any expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization.
— end note]
A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.
A temporary expression bound to a reference member in a mem-initializer is ill-formed.
[Example 5: struct A { A() : v(42) { } // error const int& v; }; — end example]
In a non-delegating constructor other than an implicitly-defined copy/move constructor ([class.copy.ctor]), if a given potentially constructed subobject is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then
  • if the entity is a non-static data member that has a default member initializer ([class.mem]) and either the entity is initialized from its default member initializer as specified in [dcl.init];
  • otherwise, if the entity is an anonymous union or a variant member ([class.union.anon]), no initialization is performed;
  • otherwise, the entity is default-initialized ([dcl.init]).
[Note 3: 
An abstract class ([class.abstract]) is never a most derived class, thus its constructors never initialize virtual base classes, therefore the corresponding mem-initializers can be omitted.
— end note]
An attempt to initialize more than one non-static data member of a union renders the program ill-formed.
[Note 4: 
After the call to a constructor for class X for an object with automatic or dynamic storage duration has completed, if the constructor was not invoked as part of value-initialization and a member of X is neither initialized nor given a value during execution of the compound-statement of the body of the constructor, the member has an indeterminate or erroneous value ([basic.indet]).
— end note]
[Example 6: struct A { A(); }; struct B { B(int); }; struct C { C() { } // initializes members as follows: A a; // OK, calls A​::​A() const B b; // error: B has no default constructor int i; // OK, i has indeterminate or erroneous value int j = 5; // OK, j has the value 5 }; — end example]
If a given non-static data member has both a default member initializer and a mem-initializer, the initialization specified by the mem-initializer is performed, and the non-static data member's default member initializer is ignored.
[Example 7: 
Given struct A { int i = /* some integer expression with side effects */ ; A(int arg) : i(arg) { } // ... }; the A(int) constructor will simply initialize i to the value of arg, and the side effects in i's default member initializer will not take place.
— end example]
A temporary expression bound to a reference member from a default member initializer is ill-formed.
[Example 8: struct A { A() = default; // OK A(int v) : v(v) { } // OK const int& v = 42; // OK }; A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK, unfortunately — end example]
In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked ([class.dtor]).
[Note 5: 
This provision ensures that destructors can be called for fully-constructed subobjects in case an exception is thrown ([except.ctor]).
— end note]
In a non-delegating constructor, initialization proceeds in the following order:
  • First, and only for the constructor of the most derived class ([intro.object]), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
  • Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
  • Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
  • Finally, the compound-statement of the constructor body is executed.
[Note 6: 
The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization.
— end note]
[Example 9: struct V { V(); V(int); }; struct A : virtual V { A(); A(int); }; struct B : virtual V { B(); B(int); }; struct C : A, B, virtual V { C(); C(int); }; A::A(int i) : V(i) { /* ... */ } B::B(int i) { /* ... */ } C::C(int i) { /* ... */ } V v(1); // use V(int) A a(2); // use V(int) B b(3); // use V() C c(4); // use V() — end example]
[Note 7: 
The expression-list or braced-init-list of a mem-initializer is in the function parameter scope of the constructor and can use this to refer to the object being initialized.
— end note]
[Example 10: class X { int a; int b; int i; int j; public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) { } };
initializes X​::​r to refer to X​::​a, initializes X​::​b with the value of the constructor parameter i, initializes X​::​i with the value of the constructor parameter i, and initializes X​::​j with the value of X​::​i; this takes place each time an object of class X is created.
— end example]
Member functions (including virtual member functions, [class.virtual]) can be called for an object under construction.
Similarly, an object under construction can be the operand of the typeid operator ([expr.typeid]) or of a dynamic_cast ([expr.dynamic.cast]).
However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the program has undefined behavior.
[Example 11: class A { public: A(int); }; class B : public A { int j; public: int f(); B() : A(f()), // undefined behavior: calls member function but base A not yet initialized j(f()) { } // well-defined: bases are all initialized }; class C { public: C(int); }; class D : public B, C { int i; public: D() : C(f()), // undefined behavior: calls member function but base C not yet initialized i(f()) { } // well-defined: bases are all initialized }; — end example]
[Note 8: 
[class.cdtor] describes the results of virtual function calls, typeid and dynamic_casts during construction for the well-defined cases; that is, describes the polymorphic behavior of an object under construction.
— end note]
A mem-initializer followed by an ellipsis is a pack expansion ([temp.variadic]) that initializes the base classes specified by a pack expansion in the base-specifier-list for the class.
[Example 12: template<class... Mixins> class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } }; — end example]

11.9.4 Initialization by inherited constructor [class.inhctor.init]

When a constructor for type B is invoked to initialize an object of a different type D (that is, when the constructor was inherited ([namespace.udecl])), initialization proceeds as if a defaulted default constructor were used to initialize the D object and each base class subobject from which the constructor was inherited, except that the B subobject is initialized by the inherited constructor if the base class subobject were to be initialized as part of the D object ([class.base.init]).
The invocation of the inherited constructor, including the evaluation of any arguments, is omitted if the B subobject is not to be initialized as part of the D object.
The complete initialization is considered to be a single function call; in particular, unless omitted, the initialization of the inherited constructor's parameters is sequenced before the initialization of any part of the D object.
[Example 1: struct B1 { B1(int, ...) { } }; struct B2 { B2(double) { } }; int get(); struct D1 : B1 { using B1::B1; // inherits B1(int, ...) int x; int y = get(); }; void test() { D1 d(2, 3, 4); // OK, B1 is initialized by calling B1(2, 3, 4), // then d.x is default-initialized (no initialization is performed), // then d.y is initialized by calling get() D1 e; // error: D1 has no default constructor } struct D2 : B2 { using B2::B2; B1 b; }; D2 f(1.0); // error: B1 has no default constructor struct W { W(int); }; 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 Y does not invoke default constructor of X template<class T> struct Log : T { using T::T; // inherits all constructors from class T ~Log() { std::clog << "Destroying wrapper" << std::endl; } };
Class template Log wraps any class and forwards all of its constructors, while writing a message to the standard log whenever an object of class Log is destroyed.
— end example]
[Example 2: struct V { V() = default; V(int); }; struct Q { Q(); }; struct A : virtual V, Q { using V::V; A() = delete; }; int bar() { return 42; } struct B : A { B() : A(bar()) {} // OK }; struct C : B {}; void foo() { C c; } // bar is not invoked, because the V subobject is not initialized as part of B — end example]
If the constructor was inherited from multiple base class subobjects of type B, the program is ill-formed.
[Example 3: struct A { A(int); }; struct B : A { using A::A; }; struct C1 : B { using B::B; }; struct C2 : B { using B::B; }; struct D1 : C1, C2 { using C1::C1; using C2::C2; }; struct V1 : virtual B { using B::B; }; struct V2 : virtual B { using B::B; }; struct D2 : V1, V2 { using V1::V1; using V2::V2; }; D1 d1(0); // error: ambiguous D2 d2(0); // OK, initializes virtual B base class, which initializes the A base class // then initializes the V1 and 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 M(0) to initialize N's base class, // use M() to initialize O's base class — end example]
When an object is initialized by an inherited constructor, initialization of the object is complete when the initialization of all subobjects is complete.

11.9.5 Construction and destruction [class.cdtor]

For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior.
For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor finishes execution results in undefined behavior.
[Example 1: struct X { int i; }; struct Y : X { Y(); }; // non-trivial struct A { int a; }; struct B : public A { int j; Y y; }; // non-trivial extern B bobj; B* pb = &bobj; // OK int* p1 = &bobj.a; // undefined behavior: refers to base class member int* p2 = &bobj.y.i; // undefined behavior: refers to member's member A* pa = &bobj; // undefined behavior: upcast to a base class type B bobj; // definition of bobj extern X xobj; int* p3 = &xobj.i; // OK, all constructors of X are trivial X xobj;
For another example, struct W { int j; }; struct X : public virtual W { }; struct Y { int* p; X x; Y() : p(&x.j) { // undefined, x is not yet constructed } };
— end example]
During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this pointer, the value of the object or subobject thus obtained is unspecified.
[Example 2: struct C; void no_opt(C*); struct C { int c; C() : c(0) { no_opt(this); } }; const C cobj; void no_opt(C* cptr) { int i = cobj.c * 100; // value of cobj.c is unspecified cptr->c = 1; cout << cobj.c * 100 // value of cobj.c is unspecified << '\n'; } extern struct D d; struct D { D(int a) : a(a), b(d.a) {} int a, b; }; D d = D(1); // value of d.b is unspecified — end example]
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior.
To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.
[Example 3: struct A { }; struct B : virtual A { }; struct C : B { }; struct D : virtual A { D(A*); }; struct X { X(A*); }; struct E : C, D, X { E() : D(this), // undefined behavior: upcast from E* to A* might use path E* D* A* // but D is not constructed // “D((C*)this)'' would be defined: E* C* is defined because E() has started, // and C* A* is defined because C is fully constructed X(this) {} // defined: upon construction of X, C/B/D/A sublattice is fully constructed }; — end example]
Member functions, including virtual functions ([class.virtual]), can be called during construction or destruction ([class.base.init]).
When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class's non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor's or destructor's class and not one overriding it in a more-derived class.
If the virtual function call uses an explicit class member access ([expr.ref]) and the object expression refers to the complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined.
[Example 4: struct V { virtual void f(); virtual void g(); }; struct A : virtual V { virtual void f(); }; struct B : virtual V { virtual void g(); B(V*, A*); }; struct D : A, B { virtual void f(); virtual void g(); D() : B((A*)this, this) { } }; B::B(V* v, A* a) { f(); // calls V​::​f, not A​::​f g(); // calls B​::​g, not D​::​g v->g(); // v is base of B, the call is well-defined, calls B​::​g a->f(); // undefined behavior: a's type not a base of B } — end example]
The typeid operator ([expr.typeid]) can be used during construction or destruction ([class.base.init]).
When typeid is used in a constructor (including the mem-initializer or default member initializer ([class.mem]) for a non-static data member) or in a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if the operand of typeid refers to the object under construction or destruction, typeid yields the std​::​type_info object representing the constructor or destructor's class.
If the operand of typeid refers to the object under construction or destruction and the static type of the operand is neither the constructor or destructor's class nor one of its bases, the behavior is undefined.
dynamic_casts ([expr.dynamic.cast]) can be used during construction or destruction ([class.base.init]).
When a dynamic_cast is used in a constructor (including the mem-initializer or default member initializer for a non-static data member) or in a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if the operand of the dynamic_cast refers to the object under construction or destruction, this object is considered to be a most derived object that has the type of the constructor or destructor's class.
If the operand of the dynamic_cast refers to the object under construction or destruction and the static type of the operand is not a pointer to or object of the constructor or destructor's own class or one of its bases, the dynamic_cast results in undefined behavior.
[Example 5: struct V { virtual void f(); }; struct A : virtual V { }; struct B : virtual V { B(V*, A*); }; struct D : A, B { D() : B((A*)this, this) { } }; B::B(V* v, A* a) { typeid(*this); // type_info for B typeid(*v); // well-defined: *v has type V, a base of B yields type_info for B typeid(*a); // undefined behavior: type A not a base of B dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B* dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B } — end example]

11.9.6 Copy/move elision [class.copy.elision]

When certain criteria are met, an implementation is allowed to omit the creation of a class object from a source object of the same type (ignoring cv-qualification), even if the selected constructor and/or the destructor for the object have side effects.
In such cases, the implementation treats the source and target of the omitted initialization as simply two different ways of referring to the same object.
If the first parameter of the selected constructor is an rvalue reference to the object's type, the destruction of that object occurs when the target would have been destroyed; otherwise, the destruction occurs at the later of the times when the two objects would have been destroyed without the optimization.
[Note 1: 
Because only one object is destroyed instead of two, and the creation of one object is omitted, there is still one object destroyed for each one constructed.
— end note]
This elision of object creation, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
  • in a return statement ([stmt.return]) in a function with a class return type, when the expression is the name of a non-volatile object o with automatic storage duration (other than a function parameter or a variable introduced by the exception-declaration of a handler ([except.handle])), the copy-initialization of the result object can be omitted by constructing o directly into the function call's result object;
  • in a throw-expression ([expr.throw]), when the operand is the name of a non-volatile object o with automatic storage duration (other than a function parameter or a variable introduced by the exception-declaration of a handler) that belongs to a scope that does not contain the innermost enclosing compound-statement associated with a try-block (if there is one), the copy-initialization of the exception object can be omitted by constructing o directly into the exception object;
  • in a coroutine, a copy of a coroutine parameter can be omitted and references to that copy replaced with references to the corresponding parameter if the meaning of the program will be unchanged except for the execution of a constructor and destructor for the parameter copy object;
  • when the exception-declaration of a handler ([except.handle]) declares an object o, the copy-initialization of o can be omitted by treating the exception-declaration as an alias for the exception object if the meaning of the program will be unchanged except for the execution of constructors and destructors for the object declared by the exception-declaration.
    [Note 2: 
    There cannot be a move from the exception object because it is always an lvalue.
    — end note]
Copy elision is not permitted where an expression is evaluated in a context requiring a constant expression ([expr.const]) and in constant initialization ([basic.start.static]).
[Note 3: 
It is possible that copy elision is performed if the same expression is evaluated in another context.
— end note]
[Example 1: class Thing { public: Thing(); ~Thing(); Thing(const Thing&); }; Thing f() { Thing t; return t; } Thing t2 = f(); struct A { void *p; constexpr A(): p(this) {} }; constexpr A g() { A loc; return loc; } constexpr A a; // well-formed, a.p points to a constexpr A b = g(); // error: b.p would be dangling ([expr.const]) void h() { A c = g(); // well-formed, c.p can point to c or be dangling }
Here the criteria for elision can eliminate the copying of the object t with automatic storage duration into the result object for the function call f(), which is the non-local object t2.
Effectively, the construction of t can be viewed as directly initializing t2, and that object's destruction will occur at program exit.
Adding a move constructor to Thing has the same effect, but it is the move construction from the object with automatic storage duration to t2 that is elided.
— end example]
[Example 2: class Thing { public: Thing(); ~Thing(); Thing(Thing&&); private: Thing(const Thing&); }; Thing f(bool b) { Thing t; if (b) throw t; // OK, Thing(Thing&&) used (or elided) to throw t return t; // OK, Thing(Thing&&) used (or elided) to return t } Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to f struct Weird { Weird(); Weird(Weird&); }; Weird g(bool b) { static Weird w1; Weird w2; if (b) return w1; // OK, uses Weird(Weird&) else return w2; // error: w2 in this context is an xvalue } int& h(bool b, int i) { static int s; if (b) return s; // OK else return i; // error: i is an xvalue } decltype(auto) h2(Thing t) { return t; // OK, t is an xvalue and h2's return type is Thing } decltype(auto) h3(Thing t) { return (t); // OK, (t) is an xvalue and h3's return type is Thing&& } — end example]
[Example 3: template<class T> void g(const T&); template<class T> void f() { T x; try { T y; try { g(x); } catch (...) { if (/*...*/) throw x; // does not move throw y; // moves } g(y); } catch(...) { g(x); g(y); // error: y is not in scope } } — end example]

11.10 Comparisons [class.compare]

11.10.1 Defaulted comparison operator functions [class.compare.default]

A defaulted comparison operator function ([over.binary]) shall be a non-template function that
  • is a non-static member or friend of some class C,
  • is defined as defaulted in C or in a context where C is complete, and
  • either has two parameters of type const C& or two parameters of type C, where the implicit object parameter (if any) is considered to be the first parameter.
Such a comparison operator function is termed a defaulted comparison operator function for class C.
Name lookups and access checks in the implicit definition ([dcl.fct.def.default]) of a comparison operator function are performed from a context equivalent to its function-body.
A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function.
[Example 1: struct S; bool operator==(S, S) = default; // error: S is not complete struct S { friend bool operator==(S, const S&) = default; // error: parameters of different types }; enum E { }; bool operator==(E, E) = default; // error: not a member or friend of a class — end example]
A defaulted <=> or == operator function for class C is defined as deleted if any non-static data member of C is of reference type or C has variant members ([class.union.anon]).
A binary operator expression a @ b is usable if either
  • a or b is of class or enumeration type and overload resolution ([over.match]) as applied to a @ b results in a usable candidate, or
  • neither a nor b is of class or enumeration type and a @ b is a valid expression.
If the member-specification does not explicitly declare any member or friend named operator==, an == operator function is declared implicitly for each three-way comparison operator function defined as defaulted in the member-specification, with the same access and function-definition and in the same class scope as the respective three-way comparison operator function, except that the return type is replaced with bool and the declarator-id is replaced with operator==.
[Note 1: 
Such an implicitly-declared == operator for a class X is defined as defaulted in the definition of X and has the same parameter-declaration-clause and trailing requires-clause as the respective three-way comparison operator.
It is declared with friend, virtual, constexpr, or consteval if the three-way comparison operator function is so declared.
If the three-way comparison operator function has no noexcept-specifier, the implicitly-declared == operator function has an implicit exception specification ([except.spec]) that can differ from the implicit exception specification of the three-way comparison operator function.
— end note]
[Example 2: template<typename T> struct X { friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default; // implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default; [[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default; // implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default; }; — end example]
[Note 2: 
The == operator function is declared implicitly even if the defaulted three-way comparison operator function is defined as deleted.
— end note]
The direct base class subobjects of C, in the order of their declaration in the base-specifier-list of C, followed by the non-static data members of C, in the order of their declaration in the member-specification of C, form a list of subobjects.
In that list, any subobject of array type is recursively expanded to the sequence of its elements, in the order of increasing subscript.
Let be an lvalue denoting the element in the expanded list of subobjects for an object x (of length n), where is formed by a sequence of derived-to-base conversions ([over.best.ics]), class member access expressions ([expr.ref]), and array subscript expressions ([expr.sub]) applied to x.

11.10.2 Equality operator [class.eq]

A defaulted equality operator function ([over.binary]) shall have a declared return type bool.
A defaulted == operator function for a class C is defined as deleted unless, for each in the expanded list of subobjects for an object x of type C, is usable ([class.compare.default]).
The return value of a defaulted == operator function with parameters x and y is determined by comparing corresponding elements and in the expanded lists of subobjects for x and y (in increasing index order) until the first index i where yields a result value which, when contextually converted to bool, yields false.
The return value is false if such an index exists and true otherwise.
[Example 1: struct D { int i; friend bool operator==(const D& x, const D& y) = default; // OK, returns x.i == y.i }; — end example]

11.10.3 Three-way comparison [class.spaceship]

The synthesized three-way comparison of type R ([cmp.categories]) of glvalues a and b of the same type is defined as follows:
  • If a <=> b is usable ([class.compare.default]) and can be explicitly converted to R using static_cast, static_cast<R>(a <=> b).
  • Otherwise, if overload resolution for a <=> b is performed and finds at least one viable candidate, the synthesized three-way comparison is not defined.
  • Otherwise, if R is not a comparison category type, or either the expression a == b or the expression a < b is not usable, the synthesized three-way comparison is not defined.
  • Otherwise, if R is strong_ordering, then a == b ? strong_ordering::equal : a < b ? strong_ordering::less : strong_ordering::greater
  • Otherwise, if R is weak_ordering, then a == b ? weak_ordering::equivalent : a < b ? weak_ordering::less : weak_ordering::greater
  • Otherwise (when R is partial_ordering), a == b ? partial_ordering::equivalent : a < b ? partial_ordering::less : b < a ? partial_ordering::greater : partial_ordering::unordered
[Note 1: 
A synthesized three-way comparison is ill-formed if overload resolution finds usable candidates that do not otherwise meet the requirements implied by the defined expression.
— end note]
Let R be the declared return type of a defaulted three-way comparison operator function, and let be the elements of the expanded list of subobjects for an object x of type C.
  • If R is auto, then let be the type of the expression .
    The operator function is defined as deleted if that expression is not usable or if is not a comparison category type ([cmp.categories.pre]) for any i.
    The return type is deduced as the common comparison type (see below) of , , , .
  • Otherwise, R shall not contain a placeholder type.
    If the synthesized three-way comparison of type R between any objects and is not defined, the operator function is defined as deleted.
The return value of type R of the defaulted three-way comparison operator function with parameters x and y of the same type is determined by comparing corresponding elements and in the expanded lists of subobjects for x and y (in increasing index order) until the first index i where the synthesized three-way comparison of type R between and yields a result value where , contextually converted to bool, yields true.
The return value is a copy of if such an index exists and static_cast<R>(std​::​strong_ordering​::​equal) otherwise.
The common comparison type U of a possibly-empty list of n comparison category types , , , is defined as follows:
  • If at least one is std​::​partial_ordering, U is std​::​partial_ordering ([cmp.partialord]).
  • Otherwise, if at least one is std​::​weak_ordering, U is std​::​weak_ordering ([cmp.weakord]).
  • Otherwise, U is std​::​strong_ordering ([cmp.strongord]).
    [Note 2: 
    In particular, this is the result when n is 0.
    — end note]

11.10.4 Secondary comparison operators [class.compare.secondary]

A secondary comparison operator is a relational operator ([expr.rel]) or the != operator.
A defaulted operator function ([over.binary]) for a secondary comparison operator @ shall have a declared return type bool.
The operator function with parameters x and y is defined as deleted if
  • a first overload resolution ([over.match]), as applied to x @ y,
    • does not result in a usable candidate, or
    • the selected candidate is not a rewritten candidate, or
  • a second overload resolution for the expression resulting from the interpretation of x @ y using the selected rewritten candidate ([over.match.oper]) does not result in a usable candidate (for example, that expression might be (x <=> y) @ 0), or
  • x @ y cannot be implicitly converted to bool.
In any of the two overload resolutions above, the defaulted operator function is not considered as a candidate for the @ operator.
Otherwise, the operator function yields x @ y.
[Example 1: struct HasNoLessThan { }; struct C { friend HasNoLessThan operator<=>(const C&, const C&); bool operator<(const C&) const = default; // OK, function is deleted }; — end example]

12 Overloading [over]

12.1 Preamble [over.pre]

[Note 1: 
Each of two or more entities with the same name in the same scope, which must be functions or function templates, is commonly called an “overload”.
— end note]
When a function is named in a call, which function declaration is being referenced and the validity of the call are determined by comparing the types of the arguments at the point of use with the types of the parameters in the declarations in the overload set.
This function selection process is called overload resolution and is defined in [over.match].
[Example 1: double abs(double); int abs(int); abs(1); // calls abs(int); abs(1.0); // calls abs(double); — end example]

12.2 Overload resolution [over.match]

12.2.1 General [over.match.general]

Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call.
The selection criteria for the best function are the number of arguments, how well the arguments match the parameter-type-list of the candidate function, how well (for non-static member functions) the object matches the object parameter, and certain other properties of the candidate function.
[Note 1: 
The function selected by overload resolution is not guaranteed to be appropriate for the context.
Other restrictions, such as the accessibility of the function, can make its use in the calling context ill-formed.
— end note]
Overload resolution selects the function to call in seven distinct contexts within the language:
Each of these contexts defines the set of candidate functions and the list of arguments in its own unique way.
But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases:
  • First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions ([over.match.viable]).
  • Then the best viable function is selected based on the implicit conversion sequences needed to match each argument to the corresponding parameter of each viable function.
If a best viable function exists and is unique, overload resolution succeeds and produces it as the result.
Otherwise overload resolution fails and the invocation is ill-formed.
When overload resolution succeeds, and the best viable function is not accessible in the context in which it is used, the program is ill-formed.
Overload resolution results in a usable candidate if overload resolution succeeds and the selected candidate is either not a function ([over.built]), or is a function that is not deleted and is accessible from the context in which overload resolution was performed.

12.2.2 Candidate functions and argument lists [over.match.funcs]

12.2.2.1 General [over.match.funcs.general]

The subclauses of [over.match.funcs] describe the set of candidate functions and the argument list submitted to overload resolution in each context in which overload resolution is used.
The source transformations and constructions defined in these subclauses are only for the purpose of describing the overload resolution process.
An implementation is not required to use such transformations and constructions.
The set of candidate functions can contain both member and non-member functions to be resolved against the same argument list.
If a member function is
  • an implicit object member function that is not a constructor, or
  • a static member function and the argument list includes an implied object argument,
it is considered to have an extra first parameter, called the implicit object parameter, which represents the object for which the member function has been called.
Similarly, when appropriate, the context can construct an argument list that contains an implied object argument as the first argument in the list to denote the object to be operated on.
For implicit object member functions, the type of the implicit object parameter is where X is the class of which the function is a direct member and cv is the cv-qualification on the member function declaration.
[Example 1: 
For a const member function of class X, the extra parameter is assumed to have type “lvalue reference to const X.
— end example]
For conversion functions that are implicit object member functions, the function is considered to be a member of the class of the implied object argument for the purpose of defining the type of the implicit object parameter.
For non-conversion functions that are implicit object member functions nominated by a using-declaration in a derived class, the function is considered to be a member of the derived class for the purpose of defining the type of the implicit object parameter.
For static member functions, the implicit object parameter is considered to match any object (since if the function is selected, the object is discarded).
[Note 1: 
No actual type is established for the implicit object parameter of a static member function, and no attempt will be made to determine a conversion sequence for that parameter ([over.match.best]).
— end note]
During overload resolution, the implied object argument is indistinguishable from other arguments.
The implicit object parameter, however, retains its identity since no user-defined conversions can be applied to achieve a type match with it.
For implicit object member functions declared without a ref-qualifier, even if the implicit object parameter is not const-qualified, an rvalue can be bound to the parameter as long as in all other respects the argument can be converted to the type of the implicit object parameter.
[Note 2: 
The fact that such an argument is an rvalue does not affect the ranking of implicit conversion sequences.
— end note]
Because other than in list-initialization only one user-defined conversion is allowed in an implicit conversion sequence, special rules apply when selecting the best user-defined conversion ([over.match.best], [over.best.ics]).
[Example 2: class T { public: T(); }; class C : T { public: C(int); }; T a = 1; // error: no viable conversion (T(C(1)) not considered) — end example]
In each case where conversion functions of a class S are considered for initializing an object or reference of type T, the candidate functions include the result of a search for the conversion-function-id operator T in S.
[Note 3: 
This search can find a specialization of a conversion function template ([basic.lookup]).
— end note]
Each such case also defines sets of permissible types for explicit and non-explicit conversion functions; each (non-template) conversion function that
  • is a non-hidden member of S,
  • yields a permissible type, and,
  • for the former set, is non-explicit
is also a candidate function.
If initializing an object, for any permissible type cv U, any cv2 U, cv2 U&, or cv2 U&& is also a permissible type.
If the set of permissible types for explicit conversion functions is empty, any candidates that are explicit are discarded.
In each case where a candidate is a function template, candidate function template specializations are generated using template argument deduction ([temp.over], [temp.deduct]).
If a constructor template or conversion function template has an explicit-specifier whose constant-expression is value-dependent ([temp.dep]), template argument deduction is performed first and then, if the context admits only candidates that are not explicit and the generated specialization is explicit ([dcl.fct.spec]), it will be removed from the candidate set.
Those candidates are then handled as candidate functions in the usual way.99
A given name can refer to, or a conversion can consider, one or more function templates as well as a set of non-template functions.
In such a case, the candidate functions generated from each function template are combined with the set of non-template candidate functions.
A defaulted move special member function ([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 C ([class.inhctor.init]) that has a first parameter of type “reference to cv1 P” (including such a constructor instantiated from a template) is excluded from the set of candidate functions when constructing an object of type cv2 D if the argument list has exactly one argument and C is reference-related to P and P is reference-related to D.
[Example 3: struct A { A(); // #1 A(A &&); // #2 template<typename T> A(T &&); // #3 }; struct B : A { using A::A; B(const B &); // #4 B(B &&) = default; // #5, implicitly deleted struct X { X(X &&) = delete; } x; }; extern B b1; B b2 = static_cast<B&&>(b1); // calls #4: #1 is not viable, #2, #3, and #5 are not candidates struct C { operator B&&(); }; B b3 = C(); // calls #4 — end example]
99)99)
The process of argument deduction fully determines the parameter types of the function template specializations, i.e., the parameters of function template specializations contain no template parameter types.
Therefore, except where specified otherwise, function template specializations and non-template functions ([dcl.fct]) are treated equivalently for the remainder of overload resolution.

12.2.2.2 Function call syntax [over.match.call]

12.2.2.2.1 General [over.match.call.general]

In a function call if the postfix-expression names at least one function or function template, overload resolution is applied as specified in [over.call.func].
If the postfix-expression denotes an object of class type, overload resolution is applied as specified in [over.call.object].
If the postfix-expression is the address of an overload set, overload resolution is applied using that set as described above.
[Note 1: 
No implied object argument is added in this case.
— end note]
If the function selected by overload resolution is an implicit object member function, the program is ill-formed.
[Note 2: 
The resolution of the address of an overload set in other contexts is described in [over.over].
— end note]

12.2.2.2.2 Call to named function [over.call.func]

Of interest in [over.call.func] are only those function calls in which the postfix-expression ultimately contains an id-expression that denotes one or more functions.
Such a postfix-expression, perhaps nested arbitrarily deep in parentheses, has one of the following forms:
These represent two syntactic subcategories of function calls: qualified function calls and unqualified function calls.
In qualified function calls, the function is named by an id-expression preceded by an -> or . operator.
Since the construct A->B is generally equivalent to (*A).B, the rest of [over] assumes, without loss of generality, that all member function calls have been normalized to the form that uses an object and the . operator.
Furthermore, [over] assumes that the postfix-expression that is the left operand of the . operator has type “cv T” where T denotes a class.100
The function declarations found by name lookup ([class.member.lookup]) constitute the set of candidate functions.
The argument list is the expression-list in the call augmented by the addition of the left operand of the . operator in the normalized member function call as the implied object argument ([over.match.funcs]).
In unqualified function calls, the function is named by a primary-expression.
The function declarations found by name lookup ([basic.lookup]) constitute the set of candidate functions.
Because of the rules for name lookup, the set of candidate functions consists either entirely of non-member functions or entirely of member functions of some class T.
In the former case or if the primary-expression is the address of an overload set, the argument list is the same as the expression-list in the call.
Otherwise, the argument list is the expression-list in the call augmented by the addition of an implied object argument as in a qualified function call.
If the current class is, or is derived from, T, and the keyword this ([expr.prim.this]) refers to it, then the implied object argument is (*this).
Otherwise, a contrived object of type T becomes the implied object argument;101 if overload resolution selects a non-static member function, the call is ill-formed.
[Example 1: struct C { void a(); void b() { a(); // OK, (*this).a() } void c(this const C&); // #1 void c() &; // #2 static void c(int = 0); // #3 void d() { c(); // error: ambiguous between #2 and #3 (C::c)(); // error: as above (&(C::c))(); // error: cannot resolve address of overloaded this->C​::​c ([over.over]) (&C::c)(C{}); // selects #1 (&C::c)(*this); // error: selects #2, and is ill-formed ([over.match.call.general]) (&C::c)(); // selects #3 } void f(this const C&); void g() const { f(); // OK, (*this).f() f(*this); // error: no viable candidate for (*this).f(*this) this->f(); // OK } static void h() { f(); // error: contrived object argument, but overload resolution // picked a non-static member function f(C{}); // error: no viable candidate C{}.f(); // OK } void k(this int); operator int() const; void m(this const C& c) { c.k(); // OK } }; — end example]
100)100)
Note that cv-qualifiers on the type of objects are significant in overload resolution for both glvalue and class prvalue objects.
101)101)
An implied object argument is contrived to correspond to the implicit object parameter attributed to member functions during overload resolution.
It is not used in the call to the selected function.
Since the member functions all have the same implicit object parameter, the contrived object will not be the cause to select or reject a function.

12.2.2.2.3 Call to object of class type [over.call.object]

If the postfix-expression E in the function call syntax evaluates to a class object of type “cv T”, then the set of candidate functions includes at least the function call operators of T.
The function call operators of T are the results of a search for the name operator() in the scope of T.
In addition, for each non-explicit conversion function declared in T of the form where the optional cv-qualifier-seq is the same cv-qualification as, or a greater cv-qualification than, cv, and where conversion-type-id denotes the type “pointer to function of () returning R”, or the type “reference to pointer to function of () returning R”, or the type “reference to function of () returning R”, a surrogate call function with the unique name call-function and having the form
R call-function ( conversion-type-id  F, P a, , P a) { return F (a, , a); }
is also considered as a candidate function.
Similarly, surrogate call functions are added to the set of candidate functions for each non-explicit conversion function declared in a base class of T provided the function is not hidden within T by another intervening declaration.102
The argument list submitted to overload resolution consists of the argument expressions present in the function call syntax preceded by the implied object argument (E).
[Note 1: 
When comparing the call against the function call operators, the implied object argument is compared against the object parameter of the function call operator.
When comparing the call against a surrogate call function, the implied object argument is compared against the first parameter of the surrogate call function.
— end note]
[Example 1: int f1(int); int f2(float); typedef int (*fp1)(int); typedef int (*fp2)(float); struct A { operator fp1() { return f1; } operator fp2() { return f2; } } a; int i = a(1); // calls f1 via pointer returned from conversion function — end example]
102)102)
Note that this construction can yield candidate call functions that cannot be differentiated one from the other by overload resolution because they have identical declarations or differ only in their return type.
The call will be ambiguous if overload resolution cannot select a match to the call that is uniquely better than such undifferentiable functions.

12.2.2.3 Operators in expressions [over.match.oper]

If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to [expr.compound].
[Note 1: 
Because ., .*, and ​::​ cannot be overloaded, these operators are always built-in operators interpreted according to [expr.compound].
?: cannot be overloaded, but the rules in this subclause are used to determine the conversions to be applied to the second and third operands when they have class or enumeration type ([expr.cond]).
— end note]
[Example 1: struct String { String (const String&); String (const char*); operator const char* (); }; String operator + (const String&, const String&); void f() { const char* p= "one" + "two"; // error: cannot add two pointers; overloaded operator+ not considered // because neither operand has class or enumeration type int I = 1 + 1; // always evaluates to 2 even if class or enumeration types exist // that would perform the operation. } — end example]
If either operand has a type that is a class or an enumeration, a user-defined operator function can be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator.
In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator.
Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 18 (where @ denotes one of the operators covered in the specified subclause).
However, the operands are sequenced in the order prescribed for the built-in operator ([expr.compound]).
Table 18 — Relationship between operator and function call notation [tab:over.match.oper]
Subclause
Expression
As member function
As non-member function
@a
(a).operator@ ()
operator@(a)
a@b
(a).operator@ (b)
operator@(a, b)
a=b
(a).operator= (b)
a[b]
(a).operator[](b)
a->
(a).operator->()
a@
(a).operator@ (0)
operator@(a, 0)
For a unary operator @ with an operand of type cv1 T1, and for a binary operator @ with a left operand of type cv1 T1 and a right operand of type cv2 T2, four sets of candidate functions, designated member candidates, non-member candidates, built-in candidates, and rewritten candidates, are constructed as follows:
  • If T1 is a complete class type or a class currently being defined, the set of member candidates is the result of a search for operator@ in the scope of T1; otherwise, the set of member candidates is empty.
  • For the operators =, [], or ->, the set of non-member candidates is empty; otherwise, it includes the result of unqualified lookup for operator@ in the rewritten function call ([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 T1 or “reference to cv T1”, when T1 is an enumeration type, or (if there is a right operand) a second parameter of type T2 or “reference to cv T2”, when T2 is an enumeration type, are candidate functions.
  • For the operator ,, the unary operator &, or the operator ->, the built-in candidates set is empty.
    For all other operators, the built-in candidates include all of the candidate operator functions defined in [over.built] that, compared to the given operator,
    • have the same operator name, and
    • accept the same number of operands, and
    • accept operand types to which the given operand or operands can be converted according to [over.best.ics], and
    • do not have the same parameter-type-list as any non-member candidate or rewritten non-member candidate that is not a function template specialization.
  • The rewritten candidate set is determined as follows:
    • For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.
    • For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y <=> x.
    • For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y that are rewrite targets with first operand x (see below).
    • For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y == x that is a rewrite target with first operand y.
    • For all other operators, the rewritten candidate set is empty.
    [Note 2: 
    A candidate synthesized from a member candidate has its object parameter as the second parameter, thus implicit conversions are considered for the first, but not for the second, parameter.
    — end note]
A non-template function or function template F named operator== is a rewrite target with first operand o unless a search for the name operator!= in the scope S from the instantiation context of the operator expression finds a function or function template that would correspond ([basic.scope.scope]) to F if its name were operator==, where S is the scope of the class type of o if F is a class member, and the namespace scope of which F is a member otherwise.
A function template specialization named operator== is a rewrite target if its function template is a rewrite target.
[Example 2: struct A {}; template<typename T> bool operator==(A, T); // #1 bool a1 = 0 == A(); // OK, calls reversed #1 template<typename T> bool operator!=(A, T); bool a2 = 0 == A(); // error, #1 is not a rewrite target struct B { bool operator==(const B&); // #2 }; struct C : B { C(); C(B); bool operator!=(const B&); // #3 }; bool c1 = B() == C(); // OK, calls #2; reversed #2 is not a candidate // because search for operator!= in C finds #3 bool c2 = C() == B(); // error: ambiguous between #2 found when searching C and // reversed #2 found when searching B struct D {}; template<typename T> bool operator==(D, T); // #4 inline namespace N { template<typename T> bool operator!=(D, T); // #5 } bool d1 = 0 == D(); // OK, calls reversed #4; #5 does not forbid #4 as a rewrite target — end example]
For the first parameter of the built-in assignment operators, only standard conversion sequences ([over.ics.scs]) are considered.
For all other operators, no such restrictions apply.
The set of candidate functions for overload resolution for some operator @ is the union of the member candidates, the non-member candidates, the built-in candidates, and the rewritten candidates for that operator @.
The argument list contains all of the operands of the operator.
The best function from the set of candidate functions is selected according to [over.match.viable] and [over.match.best].103
[Example 3: struct A { operator int(); }; A operator+(const A&, const A&); void m() { A a, b; a + b; // operator+(a, b) chosen over int(a) + int(b) } — end example]
If a rewritten operator<=> candidate is selected by overload resolution for an operator @, x @ y is interpreted as 0 @ (y <=> x) if the selected candidate is a synthesized candidate with reversed order of parameters, or (x <=> y) @ 0 otherwise, using the selected rewritten operator<=> candidate.
Rewritten candidates for the operator @ are not considered in the context of the resulting expression.
If a rewritten operator== candidate is selected by overload resolution for an operator @, its return type shall be cv bool, and x @ y is interpreted as:
  • if @ is != and the selected candidate is a synthesized candidate with reversed order of parameters, !(y == x),
  • otherwise, if @ is !=, !(x == y),
  • otherwise (when @ is ==), y == x,
in each case using the selected rewritten operator== candidate.
If a built-in candidate is selected by overload resolution, the operands of class type are converted to the types of the corresponding parameters of the selected operation function, except that the second standard conversion sequence of a user-defined conversion sequence is not applied.
Then the operator is treated as the corresponding built-in operator and interpreted according to [expr.compound].
[Example 4: struct X { operator double(); }; struct Y { operator int*(); }; int *a = Y() + 100.0; // error: pointer arithmetic requires integral operand int *b = Y() + X(); // error: pointer arithmetic requires integral operand — end example]
The second operand of operator -> is ignored in selecting an operator-> function, and is not an argument when the operator-> function is called.
When operator-> returns, the operator -> is applied to the value returned, with the original second operand.104
If the operator is the operator ,, the unary operator &, or the operator ->, and there are no viable functions, then the operator is assumed to be the built-in operator and interpreted according to [expr.compound].
[Note 3: 
The lookup rules for operators in expressions are different than the lookup rules for operator function names in a function call, as shown in the following example: struct A { }; void operator + (A, A); struct B { void operator + (B); void f (); }; A a; void B::f() { operator+ (a,a); // error: global operator hidden by member a + a; // OK, calls global operator+ }
— end note]
103)103)
If the set of candidate functions is empty, overload resolution is unsuccessful.
104)104)
If the value returned by the operator-> function has class type, this can result in selecting and calling another operator-> function.
The process repeats until an operator-> function returns a value of non-class type.

12.2.2.4 Initialization by constructor [over.match.ctor]

When objects of class type are direct-initialized, copy-initialized from an expression of the same or a derived class type ([dcl.init]), or default-initialized, overload resolution selects the constructor.
For direct-initialization or default-initialization (including default-initialization in the context of copy-list-initialization), the candidate functions are all the constructors of the class of the object being initialized.
Otherwise, the candidate functions are all the converting constructors ([class.conv.ctor]) of that class.
The argument list is the expression-list or assignment-expression of the initializer.
For default-initialization in the context of copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

12.2.2.5 Copy-initialization of class by user-defined conversion [over.match.copy]

Under the conditions specified in [dcl.init], as part of a copy-initialization of an object of class type, a user-defined conversion can be invoked to convert an initializer expression to the type of the object being initialized.
Overload resolution is used to select the user-defined conversion to be invoked.
[Note 1: 
The conversion performed for indirect binding to a reference to a possibly cv-qualified class type is determined in terms of a corresponding non-reference copy-initialization.
— end note]
Assuming that “cv1 T” is the type of the object being initialized, with T a class type, the candidate functions are selected as follows:
  • The converting constructors of T are candidate functions.
  • When the type of the initializer expression is a class type “cv S”, conversion functions are considered.
    The permissible types for non-explicit conversion functions are T and any class derived from T.
    When initializing a temporary object ([class.mem]) to be bound to the first parameter of a constructor where the parameter is of type “reference to cv2 T” and the constructor is called with a single argument in the context of direct-initialization of an object of type “cv3 T”, the permissible types for explicit conversion functions are the same; otherwise there are none.
In both cases, the argument list has one argument, which is the initializer expression.
[Note 2: 
This argument will be compared against the first parameter of the constructors and against the object parameter of the conversion functions.
— end note]

12.2.2.6 Initialization by conversion function [over.match.conv]

Under the conditions specified in [dcl.init], as part of an initialization of an object of non-class type, a conversion function can be invoked to convert an initializer expression of class type to the type of the object being initialized.
Overload resolution is used to select the conversion function to be invoked.
Assuming that “cv T” is the type of the object being initialized, the candidate functions are selected as follows:
  • The permissible types for non-explicit conversion functions are those that can be converted to type T via a standard conversion sequence ([over.ics.scs]).
    For direct-initialization, the permissible types for explicit conversion functions are those that can be converted to type T with a (possibly trivial) qualification conversion ([conv.qual]); otherwise there are none.
The argument list has one argument, which is the initializer expression.
[Note 1: 
This argument will be compared against the object parameter of the conversion functions.
— end note]

12.2.2.7 Initialization by conversion function for direct reference binding [over.match.ref]

Under the conditions specified in [dcl.init.ref], a reference can be bound directly to the result of applying a conversion function to an initializer expression.
Overload resolution is used to select the conversion function to be invoked.
Assuming that “reference to cv1 T” is the type of the reference being initialized, the candidate functions are selected as follows:
  • Let R be a set of types including
    • “lvalue reference to cv2 T2” (when converting to an lvalue) and
    • cv2 T2” and “rvalue reference to cv2 T2” (when converting to an rvalue or an lvalue of function type)
    for any T2.
    The permissible types for non-explicit conversion functions are the members of R where “cv1 T” is reference-compatible ([dcl.init.ref]) with “cv2 T2.
    For direct-initialization, the permissible types for explicit conversion functions are the members of R where T2 can be converted to type T with a (possibly trivial) qualification conversion ([conv.qual]); otherwise there are none.
The argument list has one argument, which is the initializer expression.
[Note 1: 
This argument will be compared against the object parameter of the conversion functions.
— end note]

12.2.2.8 Initialization by list-initialization [over.match.list]

When objects of non-aggregate class type T are list-initialized such that [dcl.init.list] specifies that overload resolution is performed according to the rules in this subclause or when forming a list-initialization sequence according to [over.ics.list], overload resolution selects the constructor in two phases:
  • If the initializer list is not empty or T has no default constructor, overload resolution is first performed where the candidate functions are the initializer-list constructors ([dcl.init.list]) of the class T and the argument list consists of the initializer list as a single argument.
  • Otherwise, or if no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.
In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.
[Note 1: 
This differs from other situations ([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 resolution.
— end note]

12.2.2.9 Class template argument deduction [over.match.class.deduct]

When resolving a placeholder for a deduced class type ([dcl.type.class.deduct]) where the template-name names a primary class template C, a set of functions and function templates, called the guides of C, is formed comprising:
In addition, if C is defined and its definition satisfies the conditions for an aggregate class ([dcl.init.aggr]) with the assumption that any dependent base class has no virtual functions and no virtual base classes, and the initializer is a non-empty braced-init-list or parenthesized expression-list, and there are no deduction-guides for C, the set contains an additional function template, called the aggregate deduction candidate, defined as follows.
Let be the elements of the initializer-list or designated-initializer-list of the braced-init-list, or of the expression-list.
For each , let be the corresponding aggregate element of C or of one of its (possibly recursive) subaggregates that would be initialized by ([dcl.init.aggr]) if
  • brace elision is not considered for any aggregate element that has
    • a dependent non-array type,
    • an array type with a value-dependent bound, or
    • an array type with a dependent array element type and is a string literal; and
  • each non-trailing aggregate element that is a pack expansion is assumed to correspond to no elements of the initializer list, and
  • a trailing aggregate element that is a pack expansion is assumed to correspond to all remaining elements of the initializer list (if any).
If there is no such aggregate element for any , the aggregate deduction candidate is not added to the set.
The aggregate deduction candidate is derived as above from a hypothetical constructor , where
  • if is of array type and is a braced-init-list, is an rvalue reference to the declared type of , and
  • if is of array type and is a string-literal, is an lvalue reference to the const-qualified declared type of , and
  • otherwise, is the declared type of ,
except that additional parameter packs of the form are inserted into the parameter list in their original aggregate element position corresponding to each non-trailing aggregate element of type that was skipped because it was a parameter pack, and the trailing sequence of parameters corresponding to a trailing aggregate element that is a pack expansion (if any) is replaced by a single parameter of the form .
In addition, if C is defined and inherits constructors ([namespace.udecl]) from a direct base class denoted in the base-specifier-list by a class-or-decltype B, let A be an alias template whose template parameter list is that of C and whose defining-type-id is B.
If A is a deducible template ([dcl.type.simple]), the set contains the guides of A with the return type R of each guide replaced with typename CC<R>​::​type given a class template template <typename> class CC; whose primary template is not defined and with a single partial specialization whose template parameter list is that of A and whose template argument list is a specialization of A with the template argument list of A ([temp.dep.type]) having a member typedef type designating a template specialization with the template argument list of A but with C as the template.
[Note 2: 
Equivalently, the template parameter list of the specialization is that of C, the template argument list of the specialization is B, and the member typedef names C with the template argument list of C.
— end note]
[Example 1: template <typename T> struct B { B(T); }; template <typename T> struct C : public B<T> { using B<T>::B; }; template <typename T> struct D : public B<T> {}; C c(42); // OK, deduces C<int> D d(42); // error: deduction failed, no inherited deduction guides B(int) -> B<char>; C c2(42); // OK, deduces C<char> template <typename T> struct E : public B<int> { using B<int>::B; }; E e(42); // error: deduction failed, arguments of E cannot be deduced from introduced guides template <typename T, typename U, typename V> struct F { F(T, U, V); }; template <typename T, typename U> struct G : F<U, T, int> { using G::F::F; } G g(true, 'a', 1); // OK, deduces G<char, bool> template<class T, std::size_t N> struct H { T array[N]; }; template<class T, std::size_t N> struct I { volatile T array[N]; }; template<std::size_t N> struct J { unsigned char array[N]; }; H h = { "abc" }; // OK, deduces H<char, 4> (not T = const char) I i = { "def" }; // OK, deduces I<char, 4> J j = { "ghi" }; // error: cannot bind reference to array of unsigned char to array of char in deduction — end example]
When resolving a placeholder for a deduced class type ([dcl.type.simple]) where the template-name names an alias template A, the defining-type-id of A must be of the form
typename nested-name-specifier template simple-template-id
as specified in [dcl.type.simple].
The guides of A are the set of functions or function templates formed as follows.
For each function or function template f in the guides of the template named by the simple-template-id of the defining-type-id, the template arguments of the return type of f are deduced from the defining-type-id of A according to the process in [temp.deduct.type] with the exception that deduction does not fail if not all template arguments are deduced.
If deduction fails for another reason, proceed with an empty set of deduced template arguments.
Let g denote the result of substituting these deductions into f.
If substitution succeeds, form a function or function template f' with the following properties and add it to the set of guides of A:
  • The function type of f' is the function type of g.
  • If f is a function template, f' is a function template whose template parameter list consists of all the template parameters of A (including their default template arguments) that appear in the above deductions or (recursively) in their default template arguments, followed by the template parameters of f that were not deduced (including their default template arguments), otherwise f' is not a function template.
  • The associated constraints ([temp.constr.decl]) are the conjunction of the associated constraints of g and a constraint that is satisfied if and only if the arguments of A are deducible (see below) from the return type.
  • If f is a copy deduction candidate, then f' is considered to be so as well.
  • If f was generated from a deduction-guide ([temp.deduct.guide]), then f' is considered to be so as well.
  • The explicit-specifier of f' is the explicit-specifier of g (if any).
The arguments of a template A are said to be deducible from a type T if, given a class template template <typename> class AA; with a single partial specialization whose template parameter list is that of A and whose template argument list is a specialization of A with the template argument list of A ([temp.dep.type]), AA<T> matches the partial specialization.
Initialization and overload resolution are performed as described in [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] (as appropriate for the type of initialization performed) for an object of a hypothetical class type, where the guides of the template named by the placeholder are considered to be the constructors of that class type for the purpose of forming an overload set, and the initializer is provided by the context in which class template argument deduction was performed.
The following exceptions apply:
  • The first phase in [over.match.list] (considering initializer-list constructors) is omitted if the initializer list consists of a single expression of type cv U, where U is, or is derived from, a specialization of the class template directly or indirectly named by the placeholder.
  • During template argument deduction for the aggregate deduction candidate, the number of elements in a trailing parameter pack is only deduced from the number of remaining function arguments if it is not otherwise deduced.
If the function or function template was generated from a constructor or deduction-guide that had an explicit-specifier, each such notional constructor is considered to have that same explicit-specifier.
All such notional constructors are considered to be public members of the hypothetical class type.
[Example 2: template <class T> struct A { explicit A(const T&, ...) noexcept; // #1 A(T&&, ...); // #2 }; int i; A a1 = { i, i }; // error: explicit constructor #1 selected in copy-list-initialization during deduction, // cannot deduce from non-forwarding rvalue reference in #2 A a2{i, i}; // OK, #1 deduces to A<int> and also initializes A a3{0, i}; // OK, #2 deduces to A<int> and also initializes A a4 = {0, i}; // OK, #2 deduces to A<int> and also initializes template <class T> A(const T&, const T&) -> A<T&>; // #3 template <class T> explicit A(T&&, T&&) -> A<T>; // #4 A a5 = {0, 1}; // error: explicit deduction guide #4 selected in copy-list-initialization during deduction A a6{0,1}; // OK, #4 deduces to A<int> and #2 initializes A a7 = {0, i}; // error: #3 deduces to A<int&>, #1 and #2 declare same constructor A a8{0,i}; // error: #3 deduces to A<int&>, #1 and #2 declare same constructor template <class T> struct B { template <class U> using TA = T; template <class U> B(U, TA<U>); }; B b{(int*)0, (char*)0}; // OK, deduces B<char*> template <typename T> struct S { T x; T y; }; template <typename T> struct C { S<T> s; T t; }; template <typename T> struct D { S<int> s; T t; }; C c1 = {1, 2}; // error: deduction failed C c2 = {1, 2, 3}; // error: deduction failed C c3 = {{1u, 2u}, 3}; // OK, deduces C<int> D d1 = {1, 2}; // error: deduction failed D d2 = {1, 2, 3}; // OK, braces elided, deduces D<int> template <typename T> struct E { T t; decltype(t) t2; }; E e1 = {1, 2}; // OK, deduces E<int> template <typename... T> struct Types {}; template <typename... T> struct F : Types<T...>, T... {}; struct X {}; struct Y {}; struct Z {}; struct W { operator Y(); }; F f1 = {Types<X, Y, Z>{}, {}, {}}; // OK, F<X, Y, Z> deduced F f2 = {Types<X, Y, Z>{}, X{}, Y{}}; // OK, F<X, Y, Z> deduced F f3 = {Types<X, Y, Z>{}, X{}, W{}}; // error: conflicting types deduced; operator Y not considered — end example]
[Example 3: template <class T, class U> struct C { C(T, U); // #1 }; template<class T, class U> C(T, U) -> C<T, std::type_identity_t<U>>; // #2 template<class V> using A = C<V *, V *>; template<std::integral W> using B = A<W>; int i{}; double d{}; A a1(&i, &i); // deduces A<int> A a2(i, i); // error: cannot deduce V * from i A a3(&i, &d); // error: #1: cannot deduce (V*, V*) from (int *, double *) // #2: cannot deduce A<V> from C<int *, double *> B b1(&i, &i); // deduces B<int> B b2(&d, &d); // error: cannot deduce B<W> from C<double *, double *>
Possible exposition-only implementation of the above procedure: // The following concept ensures a specialization of A is deduced. template <class> class AA; template <class V> class AA<A<V>> { }; template <class T> concept deduces_A = requires { sizeof(AA<T>); }; // f1 is formed from the constructor #1 of C, generating the following function template template<class T, class U> auto f1(T, U) -> C<T, U>; // Deducing arguments for C<T, U> from C<V *, V*> deduces T as V * and U as V *; // f1' is obtained by transforming f1 as described by the above procedure. template<class V> requires deduces_A<C<V *, V *>> auto f1_prime(V *, V*) -> C<V *, V *>; // f2 is formed from the deduction-guide #2 of C template<class T, class U> auto f2(T, U) -> C<T, std::type_identity_t<U>>; // Deducing arguments for C<T, std​::​type_identity_t<U>> from C<V *, V*> deduces T as V *; // f2' is obtained by transforming f2 as described by the above procedure. template<class V, class U> requires deduces_A<C<V *, std::type_identity_t<U>>> auto f2_prime(V *, U) -> C<V *, std::type_identity_t<U>>; // The following concept ensures a specialization of B is deduced. template <class> class BB; template <class V> class BB<B<V>> { }; template <class T> concept deduces_B = requires { sizeof(BB<T>); }; // The guides for B derived from the above f1' and f2' for A are as follows: template<std::integral W> requires deduces_A<C<W *, W *>> && deduces_B<C<W *, W *>> auto f1_prime_for_B(W *, W *) -> C<W *, W *>; template<std::integral W, class U> requires deduces_A<C<W *, std::type_identity_t<U>>> && deduces_B<C<W *, std::type_identity_t<U>>> auto f2_prime_for_B(W *, U) -> C<W *, std::type_identity_t<U>>;
— end example]

12.2.3 Viable functions [over.match.viable]

From the set of candidate functions constructed for a given context ([over.match.funcs]), a set of viable functions is chosen, from which the best function will be selected by comparing argument conversion sequences and associated constraints ([temp.constr.decl]) for the best fit ([over.match.best]).
The selection of viable functions considers associated constraints, if any, and relationships between arguments and function parameters other than the ranking of conversion sequences.
First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.
  • If there are m arguments in the list, all candidate functions having exactly m parameters are viable.
  • A candidate function having fewer than m parameters is viable only if it has an ellipsis in its parameter list ([dcl.fct]).
    For the purposes of overload resolution, any argument for which there is no corresponding parameter is considered to “match the ellipsis” ([over.ics.ellipsis]).
  • A candidate function having more than m parameters is viable only if all parameters following the have default arguments ([dcl.fct.default]).
    For the purposes of overload resolution, the parameter list is truncated on the right, so that there are exactly m parameters.
Second, for a function to be viable, if it has associated constraints ([temp.constr.decl]), those constraints shall be satisfied ([temp.constr.constr]).
Third, for F to be a viable function, there shall exist for each argument an implicit conversion sequence that converts that argument to the corresponding parameter of F.
If the parameter has reference type, the implicit conversion sequence includes the operation of binding the reference, and the fact that an lvalue reference to non-const cannot bind to an rvalue and that an rvalue reference cannot bind to an lvalue can affect the viability of the function (see [over.ics.ref]).

12.2.4 Best viable function [over.match.best]

12.2.4.1 General [over.match.best.general]

Define as the implicit conversion sequence that converts the argument in the list to the type of the parameter of viable function F.
[over.best.ics] defines the implicit conversion sequences and [over.ics.rank] defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.
Given these definitions, a viable function is defined to be a better function than another viable function if for all arguments i, is not a worse conversion sequence than , and then
  • for some argument j, is a better conversion sequence than , or, if not that,
  • the context is an initialization by user-defined conversion (see [dcl.init], [over.match.conv], and [over.match.ref]) and the standard conversion sequence from the result of to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the result of to the destination type
    [Example 1: struct A { A(); operator int(); operator double(); } a; int i = a; // a.operator int() followed by no conversion is better than // a.operator double() followed by a conversion to int float x = a; // ambiguous: both possibilities require conversions, // and neither is better than the other — end example]
    or, if not that,
  • the context is an initialization by conversion function for direct reference binding of a reference to function type, the return type of is the same kind of reference (lvalue or rvalue) as the reference being initialized, and the return type of is not
    [Example 2: template <class T> struct A { operator T&(); // #1 operator T&&(); // #2 }; typedef int Fn(); A<Fn> a; Fn& lf = a; // calls #1 Fn&& rf = a; // calls #2 — end example]
    or, if not that,
  • is not a function template specialization and is a function template specialization, or, if not that,
  • and are function template specializations, and the function template for is more specialized than the template for according to the partial ordering rules described in [temp.func.order], or, if not that,
  • and are non-template functions and is more partial-ordering-constrained than ([temp.constr.order])
    [Example 3: template <typename T = int> struct S { constexpr void f(); // #1 constexpr void f(this S&) requires true; // #2 }; void test() { S<> s; s.f(); // calls #2 } — end example]
    or, if not that,
  • is a constructor for a class D, is a constructor for a base class B of D, and for all arguments the corresponding parameters of and have the same type
    [Example 4: struct A { A(int = 0); }; struct B: A { using A::A; B(); }; int main() { B b; // OK, B​::​B() } — end example]
    or, if not that,
  • is a rewritten candidate ([over.match.oper]) and is not
    [Example 5: struct S { friend auto operator<=>(const S&, const S&) = default; // #1 friend bool operator<(const S&, const S&); // #2 }; bool b = S() < S(); // calls #2 — end example]
    or, if not that,
  • and are rewritten candidates, and is a synthesized candidate with reversed order of parameters and is not
    [Example 6: struct S { friend std::weak_ordering operator<=>(const S&, int); // #1 friend std::weak_ordering operator<=>(int, const S&); // #2 }; bool b = 1 < S(); // calls #2 — end example]
    or, if not that,
  • and are generated from class template argument deduction ([over.match.class.deduct]) for a class D, and is generated from inheriting constructors from a base class of D while is not, and for each explicit function argument, the corresponding parameters of and are either both ellipses or have the same type, or, if not that,
  • is generated from a deduction-guide ([over.match.class.deduct]) and is not, or, if not that,
  • is the copy deduction candidate and is not, or, if not that,
  • is generated from a non-template constructor and is generated from a constructor template.
    [Example 7: template <class T> struct A { using value_type = T; A(value_type); // #1 A(const A&); // #2 A(T, T, int); // #3 template<class U> A(int, T, U); // #4 // #5 is the copy deduction candidate, A(A) }; A x(1, 2, 3); // uses #3, generated from a non-template constructor template <class T> A(T) -> A<T>; // #6, less specialized than #5 A a(42); // uses #6 to deduce A<int> and #1 to initialize A b = a; // uses #5 to deduce A<int> and #2 to initialize template <class T> A(A<T>) -> A<A<T>>; // #7, as specialized as #5 A b2 = a; // uses #7 to deduce A<A<int>> and #1 to initialize — end example]
If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed.105
[Example 8: void Fcn(const int*, short); void Fcn(int*, int); int i; short s = 0; void f() { Fcn(&i, s); // is ambiguous because &i int* is better than &i const int* // but s short is also better than s int Fcn(&i, 1L); // calls Fcn(int*, int), because &i int* is better than &i const int* // and 1L short and 1L int are indistinguishable Fcn(&i, 'c'); // calls Fcn(int*, int), because &i int* is better than &i const int* // and 'c' int is better than 'c' short } — end example]
If the best viable function resolves to a function for which multiple declarations were found, and if any two of these declarations inhabit different scopes and specify a default argument that made the function viable, the program is ill-formed.
[Example 9: namespace A { extern "C" void f(int = 5); } namespace B { extern "C" void f(int = 5); } using A::f; using B::f; void use() { f(3); // OK, default argument was not used for viability f(); // error: found default argument twice } — end example]
105)105)
The algorithm for selecting the best viable function is linear in the number of viable functions.
Run a simple tournament to find a function W that is not worse than any opponent it faced.
Although it is possible that another function F that W did not face is at least as good as W, F cannot be the best function because at some point in the tournament F encountered another function G such that F was not better than G.
Hence, either W is the best function or there is no best function.
So, make a second pass over the viable functions to verify that W is better than all other functions.

12.2.4.2 Implicit conversion sequences [over.best.ics]

12.2.4.2.1 General [over.best.ics.general]

An implicit conversion sequence is a sequence of conversions used to convert an argument in a function call to the type of the corresponding parameter of the function being called.
The sequence of conversions is an implicit conversion as defined in [conv], which means it is governed by the rules for initialization of an object or reference by a single expression ([dcl.init], [dcl.init.ref]).
Implicit conversion sequences are concerned only with the type, cv-qualification, and value category of the argument and how these are converted to match the corresponding properties of the parameter.
[Note 1: 
Other properties, such as the lifetime, storage duration, linkage, alignment, accessibility of the argument, whether the argument is a bit-field, and whether a function is deleted, are ignored.
So, although an implicit conversion sequence can be defined for a given argument-parameter pair, the conversion from the argument to the parameter might still be ill-formed in the final analysis.
— end note]
A well-formed implicit conversion sequence is one of the following forms:
However, if the target is
  • the first parameter of a constructor or
  • the object parameter of a user-defined conversion function
and the constructor or user-defined conversion function is a candidate by user-defined conversion sequences are not considered.
[Note 2: 
These rules prevent more than one user-defined conversion from being applied during overload resolution, thereby avoiding infinite recursion.
— end note]
[Example 1: struct Y { Y(int); }; struct A { operator int(); }; Y y1 = A(); // error: A​::​operator int() is not a candidate struct X { X(); }; struct B { operator X(); }; B b; X x{{b}}; // error: B​::​operator X() is not a candidate — end example]
For the case where the parameter type is a reference, see [over.ics.ref].
When the parameter type is not a reference, the implicit conversion sequence models a copy-initialization of the parameter from the argument expression.
The implicit conversion sequence is the one required to convert the argument expression to a prvalue of the type of the parameter.
[Note 3: 
When the parameter has a class type, this is a conceptual conversion defined for the purposes of [over]; the actual initialization is defined in terms of constructors and is not a conversion.
— end note]
Any difference in top-level cv-qualification is subsumed by the initialization itself and does not constitute a conversion.
[Example 2: 
A parameter of type A can be initialized from an argument of type const A.
The implicit conversion sequence for that case is the identity sequence; it contains no “conversion” from const A to A.
— end example]
When the parameter has a class type and the argument expression has the same type, the implicit conversion sequence is an identity conversion.
When the parameter has a class type and the argument expression has a derived class type, the implicit conversion sequence is a derived-to-base conversion from the derived class to the base class.
A derived-to-base conversion has Conversion rank ([over.ics.scs]).
[Note 4: 
There is no such standard conversion; this derived-to-base conversion exists only in the description of implicit conversion sequences.
— end note]
When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence.
In all contexts, when converting to the implicit object parameter or when converting to the left operand of an assignment operation only standard conversion sequences are allowed.
[Note 5: 
When a conversion to the explicit object parameter occurs, it can include user-defined conversion sequences.
— end note]
If no conversions are required to match an argument to a parameter type, the implicit conversion sequence is the standard conversion sequence consisting of the identity conversion ([over.ics.scs]).
If no sequence of conversions can be found to convert an argument to a parameter type, an implicit conversion sequence cannot be formed.
If there are multiple well-formed implicit conversion sequences converting the argument to the parameter type, the implicit conversion sequence associated with the parameter is defined to be the unique conversion sequence designated the ambiguous conversion sequence.
For the purpose of ranking implicit conversion sequences as described in [over.ics.rank], the ambiguous conversion sequence is treated as a user-defined conversion sequence that is indistinguishable from any other user-defined conversion sequence.
[Note 6: 
This rule prevents a function from becoming non-viable because of an ambiguous conversion sequence for one of its parameters.
[Example 3: class B; class A { A (B&);}; class B { operator A (); }; class C { C (B&); }; void f(A) { } void f(C) { } B b; f(b); // error: ambiguous because there is a conversion b C (via constructor) // and an (ambiguous) conversion b A (via constructor or conversion function) void f(B) { } f(b); // OK, unambiguous — end example]
— end note]
If a function that uses the ambiguous conversion sequence is selected as the best viable function, the call will be ill-formed because the conversion of one of the arguments in the call is ambiguous.
The three forms of implicit conversion sequences mentioned above are defined in the following subclauses.

12.2.4.2.2 Standard conversion sequences [over.ics.scs]

Table 19 summarizes the conversions defined in [conv] and partitions them into four disjoint categories: Lvalue Transformation, Qualification Adjustment, Promotion, and Conversion.
[Note 1: 
These categories are orthogonal with respect to value category, cv-qualification, and data representation: the Lvalue Transformations do not change the cv-qualification or data representation of the type; the Qualification Adjustments do not change the value category or data representation of the type; and the Promotions and Conversions do not change the value category or cv-qualification of the type.
— end note]
[Note 2: 
As described in [conv], a standard conversion sequence either is the Identity conversion by itself (that is, no conversion) or consists of one to three conversions from the other four categories.
If there are two or more conversions in the sequence, the conversions are applied in the canonical order: Lvalue Transformation, Promotion or Conversion, Qualification Adjustment.
— end note]
Each conversion in Table 19 also has an associated rank (Exact Match, Promotion, or Conversion).
The rank of a conversion sequence is determined by considering the rank of each conversion in the sequence and the rank of any reference binding.
If any of those has Conversion rank, the sequence has Conversion rank; otherwise, if any of those has Promotion rank, the sequence has Promotion rank; otherwise, the sequence has Exact Match rank.
Table 19 — Conversions [tab:over.ics.scs]
Conversion
Category
Rank
Subclause
No conversions required
Identity
Lvalue-to-rvalue conversion
Array-to-pointer conversion
Lvalue Transformation
Function-to-pointer conversion
Exact Match
Qualification conversions
Function pointer conversion
Qualification Adjustment
Integral promotions
Floating-point promotion
Promotion
Promotion
Integral conversions
Floating-point conversions
Floating-integral conversions
Pointer conversions
Conversion
Conversion
Pointer-to-member conversions
Boolean conversions

12.2.4.2.3 User-defined conversion sequences [over.ics.user]

A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion ([class.conv]) followed by a second standard conversion sequence.
If the user-defined conversion is specified by a constructor ([class.conv.ctor]), the initial standard conversion sequence converts the source type to the type of the first parameter of that constructor.
If the user-defined conversion is specified by a conversion function, the initial standard conversion sequence converts the source type to the type of the object parameter of that conversion function.
The second standard conversion sequence converts the result of the user-defined conversion to the target type for the sequence; any reference binding is included in the second standard conversion sequence.
Since an implicit conversion sequence is an initialization, the special rules for initialization by user-defined conversion apply when selecting the best user-defined conversion for a user-defined conversion sequence (see [over.match.best] and [over.best.ics]).
If the user-defined conversion is specified by a specialization of a conversion function template, the second standard conversion sequence shall have Exact Match rank.
A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that a constructor (i.e., a user-defined conversion function) is called for those cases.

12.2.4.2.4 Ellipsis conversion sequences [over.ics.ellipsis]

An ellipsis conversion sequence occurs when an argument in a function call is matched with the ellipsis parameter specification of the function called (see [expr.call]).

12.2.4.2.5 Reference binding [over.ics.ref]

When a parameter of type “reference to cv T” binds directly ([dcl.init.ref]) to an argument expression:
  • If the argument expression has a type that is a derived class of the parameter type, the implicit conversion sequence is a derived-to-base conversion ([over.best.ics]).
  • Otherwise, if the type of the argument is possibly cv-qualified T, or if T is an array type of unknown bound with element type U and the argument has an array type of known bound whose element type is possibly cv-qualified U, the implicit conversion sequence is the identity conversion.
  • Otherwise, if T is a function type, the implicit conversion sequence is a function pointer conversion.
  • Otherwise, the implicit conversion sequence is a qualification conversion.
[Example 1: struct A {}; struct B : public A {} b; int f(A&); int f(B&); int i = f(b); // calls f(B&), an exact match, rather than f(A&), a conversion void g() noexcept; int h(void (&)() noexcept); // #1 int h(void (&)()); // #2 int j = h(g); // calls #1, an exact match, rather than #2, a function pointer conversion — end 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 ([over.ics.user]) whose second standard conversion sequence is determined by the above rules.
When a parameter of reference type is not bound directly to an argument expression, the conversion sequence is the one required to convert the argument expression to the referenced type according to [over.best.ics].
Conceptually, this conversion sequence corresponds to copy-initializing a temporary of the referenced type with the argument expression.
Any difference in top-level cv-qualification is subsumed by the initialization itself and does not constitute a conversion.
Except for an implicit object parameter, for which see [over.match.funcs], an implicit conversion sequence cannot be formed if it requires binding an lvalue reference other than a reference to a non-volatile const type to an rvalue or binding an rvalue reference to an lvalue of object type.
[Note 1: 
This means, for example, that a candidate function cannot be a viable function if it has a non-const lvalue reference parameter (other than the implicit object parameter) and the corresponding argument would require a temporary to be created to initialize the lvalue reference (see [dcl.init.ref]).
— end note]
Other restrictions on binding a reference to a particular argument that are not based on the types of the reference and the argument do not affect the formation of an implicit conversion sequence, however.
[Example 2: 
A function with an “lvalue reference to int” parameter can be a viable candidate even if the corresponding argument is an int bit-field.
The formation of implicit conversion sequences treats the int bit-field as an int lvalue and finds an exact match with the parameter.
If the function is selected by overload resolution, the call will nonetheless be ill-formed because of the prohibition on binding a non-const lvalue reference to a bit-field ([dcl.init.ref]).
— end example]

12.2.4.2.6 List-initialization sequence [over.ics.list]

When an argument is an initializer list ([dcl.init.list]), it is not an expression and special rules apply for converting it to a parameter type.
If the initializer list is a designated-initializer-list and the parameter is not a reference, a conversion is only possible if the parameter has an aggregate type that can be initialized from the initializer list according to the rules for aggregate initialization ([dcl.init.aggr]), in which case the implicit conversion sequence is a user-defined conversion sequence whose second standard conversion sequence is an identity conversion.
[Note 1: 
Aggregate initialization does not require that the members are declared in designation order.
If, after overload resolution, the order does not match for the selected overload, the initialization of the parameter will be ill-formed ([dcl.init.list]).
[Example 1: struct A { int x, y; }; struct B { int y, x; }; void f(A a, int); // #1 void f(B b, ...); // #2 void g(A a); // #3 void g(B b); // #4 void h() { f({.x = 1, .y = 2}, 0); // OK; calls #1 f({.y = 2, .x = 1}, 0); // error: selects #1, initialization of a fails // due to non-matching member order ([dcl.init.list]) g({.x = 1, .y = 2}); // error: ambiguous between #3 and #4 } — end example]
— end note]
Otherwise, if the parameter type is an aggregate class X and the initializer list has a single element of type cv U, where U is X or a class derived from X, the implicit conversion sequence is the one required to convert the element to the parameter type.
Otherwise, if the parameter type is a character array106 and the initializer list has a single element that is an appropriately-typed string-literal ([dcl.init.string]), the implicit conversion sequence is the identity conversion.
Otherwise, if the parameter type is std​::​initializer_list<X> and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X, or if the initializer list has no elements, the identity conversion.
This conversion can be a user-defined conversion even in the context of a call to an initializer-list constructor.
[Example 2: void f(std::initializer_list<int>); f( {} ); // OK, f(initializer_list<int>) identity conversion f( {1,2,3} ); // OK, f(initializer_list<int>) identity conversion f( {'a','b'} ); // OK, f(initializer_list<int>) integral promotion f( {1.0} ); // error: narrowing struct A { A(std::initializer_list<double>); // #1 A(std::initializer_list<std::complex<double>>); // #2 A(std::initializer_list<std::string>); // #3 }; A a{ 1.0,2.0 }; // OK, uses #1 void g(A); g({ "foo", "bar" }); // OK, uses #3 typedef int IA[3]; void h(const IA&); h({ 1, 2, 3 }); // OK, identity conversion — end example]
Otherwise, if the parameter type is “array of N X” or “array of unknown bound of X”, if there exists an implicit conversion sequence from each element of the initializer list (and from {} in the former case if N exceeds the number of elements in the initializer list) to X, the implicit conversion sequence is the worst such implicit conversion sequence.
Otherwise, if the parameter is a non-aggregate class X and overload resolution per [over.match.list] chooses a single best constructor C of X to perform the initialization of an object of type X from the argument initializer list:
  • If C is not an initializer-list constructor and the initializer list has a single element of type cv U, where U is X or a class derived from X, the implicit conversion sequence has Exact Match rank if U is X, or Conversion rank if U is derived from X.
  • Otherwise, the implicit conversion sequence is a user-defined conversion sequence whose second standard conversion sequence is an identity conversion.
If multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence.
User-defined conversions are allowed for conversion of the initializer list elements to the constructor parameter types except as noted in [over.best.ics].
[Example 3: struct A { A(std::initializer_list<int>); }; void f(A); f( {'a', 'b'} ); // OK, f(A(std​::​initializer_list<int>)) user-defined conversion struct B { B(int, double); }; void g(B); g( {'a', 'b'} ); // OK, g(B(int, double)) user-defined conversion g( {1.0, 1.0} ); // error: narrowing void f(B); f( {'a', 'b'} ); // error: ambiguous f(A) or f(B) struct C { C(std::string); }; void h(C); h({"foo"}); // OK, h(C(std​::​string("foo"))) struct D { D(A, C); }; void i(D); i({ {1,2}, {"bar"} }); // OK, i(D(A(std​::​initializer_list<int>{1,2}), C(std​::​string("bar")))) — end example]
Otherwise, if the parameter has an aggregate type which can be initialized from the initializer list according to the rules for aggregate initialization ([dcl.init.aggr]), the implicit conversion sequence is a user-defined conversion sequence whose second standard conversion sequence is an identity conversion.
[Example 4: struct A { int m1; double m2; }; void f(A); f( {'a', 'b'} ); // OK, f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing — end example]
Otherwise, if the parameter is a reference, see [over.ics.ref].
[Note 2: 
The rules in this subclause will apply for initializing the underlying temporary for the reference.
— end note]
[Example 5: struct A { int m1; double m2; }; void f(const A&); f( {'a', 'b'} ); // OK, f(A(int,double)) user-defined conversion f( {1.0} ); // error: narrowing void g(const double &); g({1}); // same conversion as int to double — end example]
Otherwise, if the parameter type is not a class:
  • if the initializer list has one element that is not itself an initializer list, the implicit conversion sequence is the one required to convert the element to the parameter type;
    [Example 6: void f(int); f( {'a'} ); // OK, same conversion as char to int f( {1.0} ); // error: narrowing — end example]
  • if the initializer list has no elements, the implicit conversion sequence is the identity conversion.
    [Example 7: void f(int); f( { } ); // OK, identity conversion — end example]
In all cases other than those enumerated above, no conversion is possible.
106)106)
Since there are no parameters of array type, this will only occur as the referenced type of a reference parameter.

12.2.4.3 Ranking implicit conversion sequences [over.ics.rank]

This subclause defines a partial ordering of implicit conversion sequences based on the relationships better conversion sequence and better conversion.
If an implicit conversion sequence S1 is defined by these rules to be a better conversion sequence than S2, then it is also the case that S2 is a worse conversion sequence than S1.
If conversion sequence S1 is neither better than nor worse than conversion sequence S2, S1 and S2 are said to be indistinguishable conversion sequences.
When comparing the basic forms of implicit conversion sequences (as defined in [over.best.ics])
Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:
  • List-initialization sequence L1 is a better conversion sequence than list-initialization sequence L2 if
    • L1 converts to std​::​initializer_list<X> for some X and L2 does not, or, if not that,
    • L1 and L2 convert to arrays of the same element type, and either the number of elements initialized by L1 is less than the number of elements initialized by L2, or and L2 converts to an array of unknown bound and L1 does not,
    even if one of the other rules in this paragraph would otherwise apply.
    [Example 1: void f1(int); // #1 void f1(std::initializer_list<long>); // #2 void g1() { f1({42}); } // chooses #2 void f2(std::pair<const char*, const char*>); // #3 void f2(std::initializer_list<std::string>); // #4 void g2() { f2({"foo","bar"}); } // chooses #4 — end example]
    [Example 2: void f(int (&&)[] ); // #1 void f(double (&&)[] ); // #2 void f(int (&&)[2]); // #3 f( {1} ); // Calls #1: Better than #2 due to conversion, better than #3 due to bounds f( {1.0} ); // Calls #2: Identity conversion is better than floating-integral conversion f( {1.0, 2.0} ); // Calls #2: Identity conversion is better than floating-integral conversion f( {1, 2} ); // Calls #3: Converting to array of known bound is better than to unknown bound, // and an identity conversion is better than floating-integral conversion — end example]
  • Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
    • S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that,
    • the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that,
    • S1 and S2 include reference bindings ([dcl.init.ref]) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference
      [Example 3: int i; int f1(); int&& f2(); int g(const int&); int g(const int&&); int j = g(i); // calls g(const int&) int k = g(f1()); // calls g(const int&&) int l = g(f2()); // calls g(const int&&) struct A { A& operator<<(int); void p() &; void p() &&; }; A& operator<<(A&&, char); A() << 1; // calls A​::​operator<<(int) A() << 'c'; // calls operator<<(A&&, char) A a; a << 1; // calls A​::​operator<<(int) a << 'c'; // calls A​::​operator<<(int) A().p(); // calls A​::​p()&& a.p(); // calls A​::​p()& — end example]
      or, if not that,
    • S1 and S2 include reference bindings ([dcl.init.ref]) and S1 binds an lvalue reference to an lvalue of function type and S2 binds an rvalue reference to an lvalue of function type
      [Example 4: int f(void(&)()); // #1 int f(void(&&)()); // #2 void g(); int i1 = f(g); // calls #1 — end example]
      or, if not that,
    • S1 and S2 differ only in their qualification conversion ([conv.qual]) and yield similar types T1 and T2, respectively (where a standard conversion sequence that is a reference binding is considered to yield the cv-unqualified referenced type), where T1 and T2 are not the same type, and const T2 is reference-compatible with T1 ([dcl.init.ref])
      [Example 5: int f(const volatile int *); int f(const int *); int i; int j = f(&i); // calls f(const int*) int g(const int*); int g(const volatile int* const&); int* p; int k = g(p); // calls g(const int*) — end example]
      or, if not that,
    • S1 and S2 bind “reference to T1” and “reference to T2”, respectively ([dcl.init.ref]), where T1 and T2 are not the same type, and T2 is reference-compatible with T1
      [Example 6: int f(const int &); int f(int &); int g(const int &); int g(int); int i; int j = f(i); // calls f(int &) int k = g(i); // ambiguous struct X { void f() const; void f(); }; void g(const X& a, X b) { a.f(); // calls X​::​f() const b.f(); // calls X​::​f() } int h(int (&)[]); int h(int (&)[1]); void g2() { int a[1]; h(a); // calls h(int (&)[1]) } — end example]
      or, if not that,
    • S1 and S2 bind the same reference type “reference to T” and have source types V1 and V2, respectively, where the standard conversion sequence from V1* to T* is better than the standard conversion sequence from V2* to T*.
      [Example 7: struct Z {}; struct A { operator Z&(); operator const Z&(); // #1 }; struct B { operator Z(); operator const Z&&(); // #2 }; const Z& r1 = A(); // OK, uses #1 const Z&& r2 = B(); // OK, uses #2 — end example]
  • User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.
    [Example 8: struct A { operator short(); } a; int f(int); int f(float); int i = f(a); // calls f(int), because short int is // better than short float. — end example]
Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion, which is a better conversion than a Conversion.
Two conversion sequences with the same rank are indistinguishable unless one of the following rules applies:
  • A conversion that does not convert a pointer or a pointer to member to bool is better than one that does.
  • A conversion that promotes an enumeration whose underlying type is fixed to its underlying type is better than one that promotes to the promoted underlying type, if the two are different.
  • A conversion in either direction between floating-point type FP1 and floating-point type FP2 is better than a conversion in the same direction between FP1 and arithmetic type T3 if
    • the floating-point conversion rank ([conv.rank]) of FP1 is equal to the rank of FP2, and
    • T3 is not a floating-point type, or T3 is a floating-point type whose rank is not equal to the rank of FP1, or the floating-point conversion subrank ([conv.rank]) of FP2 is greater than the subrank of T3.
      [Example 9: int f(std::float32_t); int f(std::float64_t); int f(long long); float x; std::float16_t y; int i = f(x); // calls f(std​::​float32_t) on implementations where // float and std​::​float32_t have equal conversion ranks int j = f(y); // error: ambiguous, no equal conversion rank — end example]
  • If class B is derived directly or indirectly from class A, conversion of B* to A* is better than conversion of B* to void*, and conversion of A* to void* is better than conversion of B* to void*.
  • If class B is derived directly or indirectly from class A and class C is derived directly or indirectly from B,
    • conversion of C* to B* is better than conversion of C* to A*,
      [Example 10: struct A {}; struct B : public A {}; struct C : public B {}; C* pc; int f(A*); int f(B*); int i = f(pc); // calls f(B*) — end example]
    • binding of an expression of type C to a reference to type B is better than binding an expression of type C to a reference to type A,
    • conversion of A​::​* to B​::​* is better than conversion of A​::​* to C​::​*,
    • conversion of C to B is better than conversion of C to A,
    • conversion of B* to A* is better than conversion of C* to A*,
    • binding of an expression of type B to a reference to type A is better than binding an expression of type C to a reference to type A,
    • conversion of B​::​* to C​::​* is better than conversion of A​::​* to C​::​*, and
    • conversion of B to A is better than conversion of C to A.
    [Note 1: 
    Compared conversion sequences will have different source types only in the context of comparing the second standard conversion sequence of an initialization by user-defined conversion (see [over.match.best]); in all other contexts, the source types will be the same and the target types will be different.
    — end note]

12.3 Address of an overload set [over.over]

An id-expression whose terminal name refers to an overload set S and that appears without arguments is resolved to a function, a pointer to function, or a pointer to member function for a specific function that is chosen from a set of functions selected from S determined based on the target type required in the context (if any), as described below.
The target can be
If the target type contains a placeholder type, placeholder type deduction is performed ([dcl.type.auto.deduct]), and the remainder of this subclause uses the target type so deduced.
The id-expression can be preceded by the & operator.
[Note 1: 
Any redundant set of parentheses surrounding the function name is ignored ([expr.prim.paren]).
— end note]
If there is no target, all non-template functions named are selected.
Otherwise, a non-template function with type F is selected for the function type FT of the target type if F (after possibly applying the function pointer conversion ([conv.fctptr])) is identical to FT.
[Note 2: 
That is, the class of which the function is a member is ignored when matching a pointer-to-member-function type.
— end note]
The specialization, if any, generated by template argument deduction ([temp.over], [temp.deduct.funcaddr], [temp.arg.explicit]) for each function template named is added to the set of selected functions considered.
Non-member functions, static member functions, and explicit object member functions match targets of function pointer type or reference to function type.
Implicit object member functions match targets of pointer-to-member-function type.
[Note 3: 
If an implicit object member function is chosen, the result can be used only to form a pointer to member ([expr.unary.op]).
— end note]
All functions with associated constraints that are not satisfied ([temp.constr.decl]) are eliminated from the set of selected functions.
If more than one function in the set remains, all function template specializations in the set are eliminated if the set also contains a function that is not a function template specialization.
Any given non-template function F0 is eliminated if the set contains a second non-template function that is more partial-ordering-constrained than F0 ([temp.constr.order]).
Any given function template specialization F1 is eliminated if the set contains a second function template specialization whose function template is more specialized than the function template of F1 according to the partial ordering rules of [temp.func.order].
After such eliminations, if any, there shall remain exactly one selected function.
[Example 1: int f(double); int f(int); int (*pfd)(double) = &f; // selects f(double) int (*pfi)(int) = &f; // selects f(int) int (*pfe)(...) = &f; // error: type mismatch int (&rfi)(int) = f; // selects f(int) int (&rfd)(double) = f; // selects f(double) void g() { (int (*)(int))&f; // cast expression as selector }
The initialization of pfe is ill-formed because no f() with type int(...) has been declared, and not because of any ambiguity.
— end example]
[Example 2: struct X { int f(int); static int f(long); }; int (X::*p1)(int) = &X::f; // OK int (*p2)(int) = &X::f; // error: mismatch int (*p3)(long) = &X::f; // OK int (X::*p4)(long) = &X::f; // error: mismatch int (X::*p5)(int) = &(X::f); // error: wrong syntax for // pointer to member int (*p6)(long) = &(X::f); // OK — end example]
[Example 3: template<bool B> struct X { void f(short) requires B; void f(long); template<typename> void g(short) requires B; template<typename> void g(long); }; void test() { &X<true>::f; // error: ambiguous; constraints are not considered &X<true>::g<int>; // error: ambiguous; constraints are not considered } — end example]
[Note 4: 
If f and g are both overload sets, the Cartesian product of possibilities is considered to resolve f(&g), or the equivalent expression f(g).
— end note]
[Note 5: 
Even if B is a public base of D, we have D* f(); B* (*p1)() = &f; // error void g(D*); void (*p2)(B*) = &g; // error
— end note]

12.4 Overloaded operators [over.oper]

12.4.1 General [over.oper.general]

A declaration whose declarator-id is an operator-function-id shall declare a function or function template or an explicit instantiation or specialization of a function template.
A function so declared is an operator function.
A function template so declared is an operator function template.
A specialization of an operator function template is also an operator function.
An operator function is said to implement the operator named in its operator-function-id.
operator: one of
new delete new[] delete[] co_await () [] -> ->*
~ ! + - * / % ^ &
| = += -= *= /= %= ^= &=
|= == != < > <= >= <=> &&
|| << >> <<= >>= ++ -- ,
[Note 1: 
The operators new[], delete[], (), and [] are formed from more than one token.
The latter two operators are function call and subscripting.
— end note]
Both the unary and binary forms of
+ - * &
can be overloaded.
[Note 2: 
The following operators cannot be overloaded:
. .* :: ?:
nor can the preprocessing symbols # ([cpp.stringize]) and ## ([cpp.concat]).
— end note]
Operator functions are usually not called directly; instead they are invoked to evaluate the operators they implement ([over.unary][over.inc]).
They can be explicitly called, however, using the operator-function-id as the name of the function in the function call syntax ([expr.call]).
[Example 1: complex z = a.operator+(b); // complex z = a+b; void* p = operator new(sizeof(int)*n); — end example]
The allocation and deallocation functions, operator new, operator new[], operator delete, and operator delete[], are described completely in [basic.stc.dynamic].
The attributes and restrictions found in the rest of [over.oper] do not apply to them unless explicitly stated in [basic.stc.dynamic].
The co_await operator is described completely in [expr.await].
The attributes and restrictions found in the rest of [over.oper] do not apply to it unless explicitly stated in [expr.await].
An operator function shall have at least one function parameter or implicit object parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.
It is not possible to change the precedence, grouping, or number of operands of operators.
The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class types by defining operator functions that implement these operators.
Likewise, the meaning of the operators (unary) & and , (comma) can be changed for specific enumeration types.
Operator functions are inherited in the same manner as other base class functions.
An operator function shall be a prefix unary, binary, function call, subscripting, class member access, increment, or decrement operator function.
[Note 3: 
The identities among certain predefined operators applied to fundamental types (for example, ++a a+=1) need not hold for operator functions.
Some predefined operators, such as +=, require an operand to be an lvalue when applied to fundamental types; this is not required by operator functions.
— end note]
An operator function cannot have default arguments, except where explicitly stated below.
Operator functions cannot have more or fewer parameters than the number required for the corresponding operator, as described in the rest of [over.oper].
Operators not mentioned explicitly in subclauses [over.ass] through [over.inc] act as ordinary unary and binary operators obeying the rules of [over.unary] or [over.binary].

12.4.2 Unary operators [over.unary]

A prefix unary operator function is a function named operator@ for a prefix unary-operator @ ([expr.unary.op]) that is either a non-static member function ([class.mfct]) with no non-object parameters or a non-member function with one parameter.
For a unary-expression of the form @ cast-expression, the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
cast-expression . operator @ ()
Otherwise, if a non-member function is selected, the expression is interpreted as
operator @ ( cast-expression )
[Note 1: 
The operators ++ and -- ([expr.pre.incr]) are described in [over.inc].
— end note]
[Note 2: 
The unary and binary forms of the same operator have the same name.
Consequently, a unary operator can hide a binary operator from an enclosing scope, and vice versa.
— end note]

12.4.3 Binary operators [over.binary]

12.4.3.1 General [over.binary.general]

A binary operator function is a function named operator@ for a binary operator @ that is either a non-static member function ([class.mfct]) with one non-object parameter or a non-member function with two parameters.
For an expression x @ y with subexpressions x and y, the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
x . operator @ ( y )
Otherwise, if a non-member function is selected, the expression is interpreted as
operator @ ( x , y )
An equality operator function is an operator function for an equality operator ([expr.eq]).
A relational operator function is an operator function for a relational operator ([expr.rel]).
A three-way comparison operator function is an operator function for the three-way comparison operator ([expr.spaceship]).
A comparison operator function is an equality operator function, a relational operator function, or a three-way comparison operator function.

12.4.3.2 Simple assignment [over.ass]

A simple assignment operator function is a binary operator function named operator=.
A simple assignment operator function shall be a non-static member function.
[Note 1: 
Because only standard conversion sequences are considered when converting to the left operand of an assignment operation ([over.best.ics]), an expression x = y with a subexpression x of class type is always interpreted as x.operator=(y).
— end note]
[Note 2: 
Since a copy assignment operator is implicitly declared for a class if not declared by the user ([class.copy.assign]), a base class assignment operator function is always hidden by the copy assignment operator function of the derived class.
— end note]
[Note 3: 
Any assignment operator function, even the copy and move assignment operators, can be virtual.
For a derived class D with a base class B for which a virtual copy/move assignment has been declared, the copy/move assignment operator in D does not override B's virtual copy/move assignment operator.
[Example 1: struct B { virtual int operator= (int); virtual B& operator= (const B&); }; struct D : B { virtual int operator= (int); virtual D& operator= (const B&); }; D dobj1; D dobj2; B* bptr = &dobj1; void f() { bptr->operator=(99); // calls D​::​operator=(int) *bptr = 99; // ditto bptr->operator=(dobj2); // calls D​::​operator=(const B&) *bptr = dobj2; // ditto dobj1 = dobj2; // calls implicitly-declared D​::​operator=(const D&) } — end example]
— end note]

12.4.4 Function call [over.call]

A function call operator function is a function named operator() that is a member function with an arbitrary number of parameters.
It may have default arguments.
For an expression of the form where the postfix-expression is of class type, the operator function is selected by overload resolution ([over.call.object]).
If a surrogate call function is selected, let e be the result of invoking the corresponding conversion operator function on the postfix-expression;
the expression is interpreted as
e ( expression-list )
Otherwise, the expression is interpreted as
postfix-expression . operator () ( expression-list )

12.4.5 Subscripting [over.sub]

A subscripting operator function is a member function named operator[] with an arbitrary number of parameters.
It may have default arguments.
For an expression of the form the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
postfix-expression . operator [] ( expression-list )
[Example 1: struct X { Z operator[](std::initializer_list<int>); Z operator[](auto...); }; X x; x[{1,2,3}] = 7; // OK, meaning x.operator[]({1,2,3}) x[1,2,3] = 7; // OK, meaning x.operator[](1,2,3) int a[10]; a[{1,2,3}] = 7; // error: built-in subscript operator a[1,2,3] = 7; // error: built-in subscript operator — end example]

12.4.6 Class member access [over.ref]

A class member access operator function is a function named operator-> that is a non-static member function taking no non-object parameters.
For an expression of the form the operator function is selected by overload resolution ([over.match.oper]), and the expression is interpreted as
( postfix-expression . operator -> () ) -> template id-expression

12.4.7 Increment and decrement [over.inc]

An increment operator function is a function named operator++.
If this function is a non-static member function with no non-object parameters, or a non-member function with one parameter, it defines the prefix increment operator ++ for objects of that type.
If the function is a non-static member function with one non-object parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type.
When the postfix increment is called as a result of using the ++ operator, the int argument will have value zero.107
[Example 1: struct X { X& operator++(); // prefix ++a X operator++(int); // postfix a++ }; struct Y { }; Y& operator++(Y&); // prefix ++b Y operator++(Y&, int); // postfix b++ void f(X a, Y b) { ++a; // a.operator++(); a++; // a.operator++(0); ++b; // operator++(b); b++; // operator++(b, 0); a.operator++(); // explicit call: like ++a; a.operator++(0); // explicit call: like a++; operator++(b); // explicit call: like ++b; operator++(b, 0); // explicit call: like b++; } — end example]
A decrement operator function is a function named operator-- and is handled analogously to an increment operator function.
107)107)
Calling operator++ explicitly, as in expressions like a.operator++(2), has no special properties: The argument to operator++ is 2.

12.5 Built-in operators [over.built]

The candidate operator functions that represent the built-in operators defined in [expr.compound] are specified in this subclause.
These candidate functions participate in the operator overload resolution process as described in [over.match.oper] and are used for no other purpose.
[Note 1: 
Because built-in operators take only operands with non-class type, and operator overload resolution occurs only when an operand expression originally has class or enumeration type, operator overload resolution can resolve to a built-in operator only when an operand has a class type that has a user-defined conversion to a non-class type appropriate for the operator, or when an operand has an enumeration type that can be converted to a type appropriate for the operator.
Also note that some of the candidate operator functions given in this subclause are more permissive than the built-in operators themselves.
As described in [over.match.oper], after a built-in operator is selected by overload resolution the expression is subject to the requirements for the built-in operator given in [expr.compound], and therefore to any additional semantic constraints given there.
In some cases, user-written candidates with the same name and parameter types as a built-in candidate operator function cause the built-in operator function to not be included in the set of candidate functions.
— end note]
In this subclause, the term promoted integral type is used to refer to those cv-unqualified integral types which are preserved by integral promotion (including e.g. int and long but excluding e.g. char).
[Note 2: 
In all cases where a promoted integral type is required, an operand of unscoped enumeration type will be acceptable by way of the integral promotions.
— end note]
In the remainder of this subclause, vq represents either volatile or no cv-qualifier.
For every pair (T, vq), where T is a cv-unqualified arithmetic type other than bool or a cv-unqualified pointer to (possibly cv-qualified) object type, there exist candidate operator functions of the form vq T& operator++(vq T&); T operator++(vq T&, int); vq T& operator--(vq T&); T operator--(vq T&, int);
For every (possibly cv-qualified) object type T and for every function type T that has neither cv-qualifiers nor a ref-qualifier, there exist candidate operator functions of the form T& operator*(T*);
For every type T there exist candidate operator functions of the form T* operator+(T*);
For every cv-unqualified floating-point or promoted integral type T, there exist candidate operator functions of the form T operator+(T); T operator-(T);
For every promoted integral type T, there exist candidate operator functions of the form T operator~(T);
For every quintuple (C1, C2, T, cv1, cv2), where C2 is a class type, C1 is the same type as C2 or is a derived class of C2, and T is an object type or a function type, there exist candidate operator functions of the form cv12 T& operator->*(cv1 C1*, cv2 T C2::*); where cv12 is the union of cv1 and cv2.
The return type is shown for exposition only; see [expr.mptr.oper] for the determination of the operator's result type.
For every pair of types L and R, where each of L and R is a floating-point or promoted integral type, there exist candidate operator functions of the form LR operator*(L, R); LR operator/(L, R); LR operator+(L, R); LR operator-(L, R); bool operator==(L, R); bool operator!=(L, R); bool operator<(L, R); bool operator>(L, R); bool operator<=(L, R); bool operator>=(L, R); where LR is the result of the usual arithmetic conversions ([expr.arith.conv]) between types L and R.
For every integral type T there exists a candidate operator function of the form std::strong_ordering operator<=>(T, T);
For every pair of floating-point types L and R, there exists a candidate operator function of the form std::partial_ordering operator<=>(L, R);
For every cv-qualified or cv-unqualified object type T there exist candidate operator functions of the form T* operator+(T*, std::ptrdiff_t); T& operator[](T*, std::ptrdiff_t); T* operator-(T*, std::ptrdiff_t); T* operator+(std::ptrdiff_t, T*); T& operator[](std::ptrdiff_t, T*);
For every T, where T is a pointer to object type, there exist candidate operator functions of the form std::ptrdiff_t operator-(T, T);
For every T, where T is an enumeration type or a pointer type, there exist candidate operator functions of the form bool operator==(T, T); bool operator!=(T, T); bool operator<(T, T); bool operator>(T, T); bool operator<=(T, T); bool operator>=(T, T); R operator<=>(T, T); where R is the result type specified in [expr.spaceship].
For every T, where T is a pointer-to-member type or std​::​nullptr_t, there exist candidate operator functions of the form bool operator==(T, T); bool operator!=(T, T);
For every pair of promoted integral types L and R, there exist candidate operator functions of the form LR operator%(L, R); LR operator&(L, R); LR operator^(L, R); LR operator|(L, R); L operator<<(L, R); L operator>>(L, R); where LR is the result of the usual arithmetic conversions ([expr.arith.conv]) between types L and R.
For every triple (L, vq, R), where L is an arithmetic type, and R is a floating-point or promoted integral type, there exist candidate operator functions of the form vq L& operator=(vq L&, R); vq L& operator*=(vq L&, R); vq L& operator/=(vq L&, R); vq L& operator+=(vq L&, R); vq L& operator-=(vq L&, R);
For every pair (T, vq), where T is any type, there exist candidate operator functions of the form T*vq& operator=(T*vq&, T*);
For every pair (T, vq), where T is an enumeration or pointer-to-member type, there exist candidate operator functions of the form vq T& operator=(vq T&, T);
For every pair (T, vq), where T is a cv-qualified or cv-unqualified object type, there exist candidate operator functions of the form T*vq& operator+=(T*vq&, std::ptrdiff_t); T*vq& operator-=(T*vq&, std::ptrdiff_t);
For every triple (L, vq, R), where L is an integral type, and R is a promoted integral type, there exist candidate operator functions of the form vq L& operator%=(vq L&, R); vq L& operator<<=(vq L&, R); vq L& operator>>=(vq L&, R); vq L& operator&=(vq L&, R); vq L& operator^=(vq L&, R); vq L& operator|=(vq L&, R);
There also exist candidate operator functions of the form bool operator!(bool); bool operator&&(bool, bool); bool operator||(bool, bool);
For every pair of types L and R, where each of L and R is a floating-point or promoted integral type, there exist candidate operator functions of the form LR operator?:(bool, L, R); where LR is the result of the usual arithmetic conversions ([expr.arith.conv]) between types L and R.
[Note 3: 
As with all these descriptions of candidate functions, this declaration serves only to describe the built-in operator for purposes of overload resolution.
The operator “?:” cannot be overloaded.
— end note]
For every type T, where T is a pointer, pointer-to-member, or scoped enumeration type, there exist candidate operator functions of the form T operator?:(bool, T, T);

12.6 User-defined literals [over.literal]

The first form of literal-operator-id is deprecated ([depr.lit]).
Some literal suffix identifiers are reserved for future standardization; see [usrlit.suffix].
A declaration whose literal-operator-id uses such a literal suffix identifier is ill-formed, no diagnostic required.
A declaration whose declarator-id is a literal-operator-id shall declare a function or function template that belongs to a namespace (it could be a friend function ([class.friend])) or an explicit instantiation or specialization of a function template.
A function declared with a literal-operator-id is a literal operator.
A function template declared with a literal-operator-id is a literal operator template.
The declaration of a literal operator shall have a parameter-declaration-clause equivalent to one of the following: const char* unsigned long long int long double char wchar_t char8_t char16_t char32_t const char*, std::size_t const wchar_t*, std::size_t const char8_t*, std::size_t const char16_t*, std::size_t const char32_t*, std::size_t
If a parameter has a default argument ([dcl.fct.default]), the program is ill-formed.
A raw literal operator is a literal operator with a single parameter whose type is const char*.
A numeric literal operator template is a literal operator template whose template-parameter-list has a single template-parameter that is a non-type template parameter pack ([temp.variadic]) with element type char.
A string literal operator template is a literal operator template whose template-parameter-list comprises a single non-type template-parameter of class type.
The declaration of a literal operator template shall have an empty parameter-declaration-clause and shall declare either a numeric literal operator template or a string literal operator template.
Literal operators and literal operator templates shall not have C language linkage.
[Note 1: 
Literal operators and literal operator templates are usually invoked implicitly through user-defined literals ([lex.ext]).
However, except for the constraints described above, they are ordinary namespace-scope functions and function templates.
In particular, they are looked up like ordinary functions and function templates and they follow the same overload resolution rules.
Also, they can be declared inline or constexpr, they can have internal, module, or external linkage, they can be called explicitly, their addresses can be taken, etc.
— end note]
[Example 1: void operator ""_km(long double); // OK string operator "" _i18n(const char*, std::size_t); // OK, deprecated template <char...> 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 ([usrlit.suffix], [lex.ext]) double operator""_Bq(long double); // OK, does not use the reserved identifier _Bq ([lex.name]) double operator"" _Bq(long double); // ill-formed, no diagnostic required: // uses the reserved identifier _Bq ([lex.name]) float operator " "B(const char*); // error: non-empty string-literal string operator ""5X(const char*, std::size_t); // error: invalid literal suffix identifier double operator ""_miles(double); // error: invalid parameter-declaration-clause template <char...> int operator ""_j(const char*); // error: invalid parameter-declaration-clause extern "C" void operator ""_m(long double); // error: C language linkage — end example]

13 Templates [temp]

13.1 Preamble [temp.pre]

The declaration in a template-declaration (if any) shall
A declaration introduced by a template declaration of a variable is a variable template.
A variable template at class scope is a static data member template.
[Example 1: template<class T> constexpr T pi = T(3.1415926535897932385L); template<class T> T circular_area(T r) { return pi<T> * r * r; } struct matrix_constants { template<class T> using pauli = hermitian_matrix<T, 2>; template<class T> constexpr static pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } }; template<class T> constexpr static pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } }; template<class T> constexpr static pauli<T> sigma3 = { { 1, 0 }, { 0, -1 } }; }; — end example]
[Note 2: 
A template-declaration can appear only as a namespace scope or class scope declaration.
— end note]
Its declaration shall not be an export-declaration.
In a function template declaration, the unqualified-id of the declarator-id shall be a name.
[Note 3: 
A class or variable template declaration of a simple-template-id declares a partial specialization ([temp.spec.partial]).
— end note]
In a template-declaration, explicit specialization, or explicit instantiation, the init-declarator-list in the declaration shall contain at most one declarator.
When such a declaration is used to declare a class template, no declarator is permitted.
A specialization (explicit or implicit) of one template is distinct from all specializations of any other template.
A template, an explicit specialization ([temp.expl.spec]), and a partial specialization shall not have C language linkage.
[Note 4: 
Default arguments for function templates and for member functions of class templates are considered definitions for the purpose of template instantiation ([temp.decls]) and must obey the one-definition rule ([basic.def.odr]).
— end note]
[Note 5: 
A template cannot have the same name as any other name bound in the same scope ([basic.scope.scope]), except that a function template can share a name with using-declarators, a type, non-template functions ([dcl.fct]) and/or function templates ([temp.over]).
Specializations, including partial specializations ([temp.spec.partial]), do not reintroduce or bind names.
Their target scope is the target scope of the primary template, so all specializations of a template belong to the same scope as it does.
[Example 2: void f() {} class f {}; // OK namespace N { void f(int) {} } using N::f; // OK template<typename> void f(long) {} // #1, OK template<typename> void f(long) {} // error: redefinition of #1 template<typename> void f(long long) {} // OK template<> void f<int>(long long) {} // OK, doesn't bind a name — end example]
— end note]
An entity is templated if it is
[Note 6: 
A local class, a local or block variable, or a friend function defined in a templated entity is a templated entity.
— end note]
A templated function is a function template or a function that is templated.
A templated class is a class template or a class that is templated.
A templated variable is a variable template or a variable that is templated.
A template-declaration is written in terms of its template parameters.
The optional requires-clause following a template-parameter-list allows the specification of constraints ([temp.constr.decl]) on template arguments ([temp.arg]).
The requires-clause introduces the constraint-expression that results from interpreting the constraint-logical-or-expression as a constraint-expression.
[Note 7: 
The expression in a requires-clause uses a restricted grammar to avoid ambiguities.
Parentheses can be used to specify arbitrary expressions in a requires-clause.
[Example 3: template<int N> requires N == sizeof new unsigned short int f(); // error: parentheses required around == expression — end example]
— end note]
A definition of a function template, member function of a class template, variable template, or static data member of a class template shall be reachable from the end of every definition domain ([basic.def.odr]) in which it is implicitly instantiated ([temp.inst]) unless the corresponding specialization is explicitly instantiated ([temp.explicit]) in some translation unit; no diagnostic is required.

13.2 Template parameters [temp.param]

There is no semantic difference between class and typename in a type-parameter-key.
typename followed by an unqualified-id names a template type parameter.
typename followed by a qualified-id denotes the type in a non-type108 parameter-declaration.
[Example 1: class T { /* ... */ }; int i; template<class T, T i> void f(T t) { T t1 = i; // template-parameters T and i ::T t2 = ::i; // global namespace members T and i }
Here, the template f has a type-parameter called T, rather than an unnamed non-type template-parameter of class T.
— end example]
A template-parameter declaration shall not have a storage-class-specifier.
Types shall not be defined in a template-parameter declaration.
The identifier in a type-parameter is not looked up.
A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared without template) or template-name (if declared with template) in the scope of the template declaration.
[Note 2: 
A template argument can be a class template or alias template.
For example,
template<class T> class myarray { /* ... */ }; template<class K, class V, template<class T> class C = myarray> class Map { C<K> key; C<V> value; }; — end note]
A type-constraint Q that designates a concept C can be used to constrain a contextually-determined type or template type parameter pack T with a constraint-expression E defined as follows.
If Q is of the form C<A, , A>, then let E be C<T, A, , A>.
Otherwise, let E be C<T>.
If T is not a pack, then E is E, otherwise E is (E && ...).
The concept designated by a type-constraint shall be a type concept ([temp.concept]).
A type-parameter that starts with a type-constraint introduces the immediately-declared constraint of the type-constraint for the parameter.
[Example 2: template<typename T> concept C1 = true; template<typename... Ts> concept C2 = true; template<typename T, typename U> concept C3 = true; template<C1 T> struct s1; // associates C1<T> template<C1... T> struct s2; // associates (C1<T> && ...) template<C2... T> struct s3; // associates (C2<T> && ...) template<C3<int> T> struct s4; // associates C3<T, int> template<C3<int>... T> struct s5; // associates (C3<T, int> && ...) — end example]
A non-type template-parameter shall have one of the following (possibly cv-qualified) types:
The top-level cv-qualifiers on the template-parameter are ignored when determining its type.
A structural type is one of the following:
  • a scalar type, or
  • an lvalue reference type, or
  • a literal class type with the following properties:
    • all base classes and non-static data members are public and non-mutable and
    • the types of all base classes and non-static data members are structural types or (possibly multidimensional) arrays thereof.
An id-expression naming a non-type template-parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object, which is template-argument-equivalent ([temp.type]) to the corresponding template argument after it has been converted to the type of the template-parameter ([temp.arg.nontype]).
No two template parameter objects are template-argument-equivalent.
[Note 3: 
If an id-expression names a non-type non-reference template-parameter, then it is a prvalue if it has non-class type.
Otherwise, if it is of class type T, it is an lvalue and has type const T ([expr.prim.id.unqual]).
— end note]
[Example 3: using X = int; struct A {}; template<const X& x, int i, A a> void f() { i++; // error: change of template-parameter value &x; // OK &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 } — end example]
[Note 4: 
A non-type template-parameter cannot be declared to have type cv void.
[Example 4: template<void v> class X; // error template<void* pv> class Y; // OK — end example]
— end note]
A non-type template-parameter of type “array of T” or of function type T is adjusted to be of type “pointer to T.
[Example 5: template<int* a> struct R { /* ... */ }; template<int b[5]> struct S { /* ... */ }; int p; R<&p> w; // OK S<&p> x; // OK due to parameter adjustment int v[5]; R<v> y; // OK due to implicit argument conversion S<v> z; // OK due to both adjustment and conversion — end example]
A non-type template parameter declared with a type that contains a placeholder type with a type-constraint introduces the immediately-declared constraint of the type-constraint for the invented type corresponding to the placeholder ([dcl.fct]).
A default template argument is a template argument ([temp.arg]) specified after = in a template-parameter.
A default template argument may be specified for any kind of template-parameter (type, non-type, template) that is not a template parameter pack ([temp.variadic]).
A default template argument may be specified in a template declaration.
A default template argument shall not be specified in the template-parameter-lists of the definition of a member of a class template that appears outside of the member's class.
A default template argument shall not be specified in a friend class template declaration.
If a friend function template declaration D specifies a default template argument, that declaration shall be a definition and there shall be no other declaration of the function template which is reachable from D or from which D is reachable.
The set of default template arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are ([dcl.fct.default]).
[Example 6: 
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A; is equivalent to template<class T1 = int, class T2 = int> class A;
— end example]
If a template-parameter of a class template, variable template, or alias template has a default template argument, each subsequent template-parameter shall either have a default template argument supplied or be a template parameter pack.
If a template-parameter of a primary class template, primary variable template, or alias template is a template parameter pack, it shall be the last template-parameter.
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).
A template parameter of a deduction guide template ([temp.deduct.guide]) that does not have a default argument shall be deducible from the parameter-type-list of the deduction guide template.
[Example 7: template<class T1 = int, class T2> class B; // error // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error template<class... T, class U> void g() { } // error — end example]
When parsing a default template argument for a non-type template-parameter, the first non-nested > is taken as the end of the template-parameter-list rather than a greater-than operator.
[Example 8: template<int i = 3 > 4 > // syntax error class X { /* ... */ }; template<int i = (3 > 4) > // OK class Y { /* ... */ }; — end example]
A template-parameter of a template template-parameter is permitted to have a default template argument.
When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter.
[Example 9: template <template <class TT = float> class T> struct A { inline void f(); inline void g(); }; template <template <class TT> class T> void A<T>::f() { T<> t; // error: TT has no default template argument } template <template <class TT = char> class T> void A<T>::g() { T<> t; // OK, T<char> } — end example]
If a template-parameter is a type-parameter with an ellipsis prior to its optional identifier or is a parameter-declaration that declares a pack ([dcl.fct]), then the template-parameter is a template parameter pack.
A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion.
Similarly, a template parameter pack that is a type-parameter with a template-parameter-list containing one or more unexpanded packs is a pack expansion.
A type parameter pack with a type-constraint that contains an unexpanded parameter pack is a pack expansion.
A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the same template-parameter-list.
[Example 10: template <class... Types> // Types is a template type parameter pack class Tuple; // but not a pack expansion template <class T, int... Dims> // Dims is a non-type template parameter pack struct multi_array; // but not a pack expansion template <class... T> struct value_holder { template <T... Values> struct apply { }; // Values is a non-type template parameter pack }; // and a pack expansion template <class... T, T... Values> // error: Values expands template type parameter struct static_array; // pack T within the same template parameter list — end example]
108)108)
Since template template-parameters and template template-arguments are treated as types for descriptive purposes, the terms non-type parameter and non-type argument are used to refer to non-type, non-template parameters and arguments.

13.3 Names of template specializations [temp.names]

The component name of a simple-template-id, template-id, or template-name is the first name in it.
A < is interpreted as the delimiter of a template-argument-list if it follows a name that is not a conversion-function-id and
[Note 1: 
If the name is an identifier, it is then interpreted as a template-name.
The keyword template is used to indicate that a dependent qualified name ([temp.dep.type]) denotes a template where an expression might appear.
— end note]
[Example 1: struct X { template<std::size_t> X* alloc(); template<std::size_t> static X* adjust(); }; template<class T> void f(T* p) { T* p1 = p->alloc<200>(); // error: < means less than T* p2 = p->template alloc<200>(); // OK, < starts template argument list T::adjust<100>(); // error: < means less than T::template adjust<100>(); // OK, < starts template argument list } — end example]
When parsing a template-argument-list, the first non-nested >109 is taken as the ending delimiter rather than a greater-than operator.
Similarly, the first non-nested >> is treated as two consecutive but distinct > tokens, the first of which is taken as the end of the template-argument-list and completes the template-id.
[Note 2: 
The second > token produced by this replacement rule can terminate an enclosing template-id construct or it can be part of a different construct (e.g., a cast).
— end note]
[Example 2: template<int i> class X { /* ... */ }; X< 1>2 > x1; // syntax error X<(1>2)> x2; // OK template<class T> class Y { /* ... */ }; Y<X<1>> x3; // OK, same as Y<X<1> > x3; Y<X<6>>1>> x4; // syntax error Y<X<(6>>1)>> x5; // OK — end example]
The keyword template shall not appear immediately after a declarative nested-name-specifier ([expr.prim.id.qual]).
A name prefixed by the keyword template shall be followed by a template argument list or refer to a class template or an alias template.
The latter case is deprecated ([depr.template.template]).
The keyword template shall not appear immediately before a ~ token (as to name a destructor).
[Note 3: 
The keyword template cannot be applied to non-template members of class templates.
— end note]
[Note 4: 
As is the case with the typename prefix, the template prefix is well-formed even when lookup for the name would already find a template.
— end note]
[Example 3: template <class T> struct A { void f(int); template <class U> void f(U); }; template <class T> void f(T t) { A<T> a; a.template f<>(t); // OK, calls template a.template f(t); // error: not a template-id } template <class T> struct B { template <class T2> struct C { }; }; // deprecated: T​::​C is assumed to name a class template: template <class T, template <class X> class TT = T::template C> struct D { }; D<B<int> > db; — end example]
A template-id is valid if
A simple-template-id shall be valid unless it names a function template specialization ([temp.deduct]).
[Example 4: template<class T, T::type n = 0> class X; struct S { using type = int; }; using T1 = X<S, int, int>; // error: too many arguments using T2 = X<>; // error: no default argument for first template parameter using T3 = X<1>; // error: value 1 does not match type-parameter using T4 = X<int>; // error: substitution failure for second template parameter using T5 = X<S>; // OK — end example]
When the template-name of a simple-template-id names a constrained non-function template or a constrained template template-parameter, and all template-arguments in the simple-template-id are non-dependent ([temp.dep.temp]), the associated constraints ([temp.constr.decl]) of the constrained template shall be satisfied ([temp.constr.constr]).
[Example 5: template<typename T> concept C1 = sizeof(T) != sizeof(int); template<C1 T> struct S1 { }; template<C1 T> using Ptr = T*; S1<int>* p; // error: constraints not satisfied Ptr<int> p; // error: constraints not satisfied template<typename T> struct S2 { Ptr<int> x; }; // ill-formed, no diagnostic required template<typename T> struct S3 { Ptr<T> x; }; // OK, satisfaction is not required S3<int> x; // error: constraints not satisfied template<template<C1 T> class X> struct S4 { X<int> x; // ill-formed, no diagnostic required }; template<typename T> concept C2 = sizeof(T) == 1; template<C2 T> struct S { }; template struct S<char[2]>; // error: constraints not satisfied template<> struct S<char[2]> { }; // error: constraints not satisfied — end example]
A concept-id is a prvalue of type bool, and does not name a template specialization.
A concept-id evaluates to true if the concept's normalized constraint-expression ([temp.constr.decl]) is satisfied ([temp.constr.constr]) by the specified template arguments and false otherwise.
[Note 5: 
Since a constraint-expression is an unevaluated operand, a concept-id appearing in a constraint-expression is not evaluated except as necessary to determine whether the normalized constraints are satisfied.
— end note]
[Example 6: template<typename T> concept C = true; static_assert(C<int>); // OK — end example]
109)109)
A > that encloses the type-id of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description.

13.4 Template arguments [temp.arg]

13.4.1 General [temp.arg.general]

There are three forms of template-argument, corresponding to the three forms of template-parameter: type, non-type and template.
The type and form of each template-argument specified in a template-id shall match the type and form specified for the corresponding parameter declared by the template in its template-parameter-list.
When the parameter declared by the template is a template parameter pack, it will correspond to zero or more template-arguments.
[Example 1: template<class T> class Array { T* v; int sz; public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } }; Array<int> v1(20); typedef std::complex<double> dcomplex; // std​::​complex is a standard library template Array<dcomplex> v2(30); Array<dcomplex> v3(40); void bar() { v1[3] = 7; v2[3] = v3.elem(4) = dcomplex(7,8); } — end example]
The template argument list of a template-head is a template argument list in which the template argument has the value of the template parameter of the template-head.
If the template parameter is a template parameter pack ([temp.variadic]), the template argument is a pack expansion whose pattern is the name of the template parameter pack.
In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter.110
[Example 2: template<class T> void f(); template<int I> void f(); void g() { f<int()>(); // int() is a type-id: call the first f() } — end example]
[Note 1: 
Names used in a template-argument are subject to access control where they appear.
Because a template-parameter is not a class member, no access control applies.
— end note]
[Example 3: template<class T> class X { static T t; }; class Y { private: struct S { /* ... */ }; X<S> x; // OK, S is accessible // X<Y​::​S> has a static member of type Y​::​S // OK, even though Y​::​S is private }; X<Y::S> y; // error: S not accessible — end example]
For a template argument that is a class type or a class template, the template definition has no special access rights to the members of the template argument.
[Example 4: template <template <class TT> class T> class A { typename T<int>::S s; }; template <class U> class B { private: struct S { /* ... */ }; }; A<B> b; // error: A has no access to B​::​S — end example]
When template argument packs or default template arguments are used, a template-argument list can be empty.
In that case the empty <> brackets shall still be used as the template-argument-list.
[Example 5: template<class T = char> class String; String<>* p; // OK, String<char> String* q; // syntax error template<class ... Elements> class Tuple; Tuple<>* t; // OK, Elements is empty Tuple* u; // syntax error — end example]
An explicit destructor call ([class.dtor]) for an object that has a type that is a class template specialization may explicitly specify the template-arguments.
[Example 6: template<class T> struct A { ~A(); }; void f(A<int>* p, A<int>* q) { p->A<int>::~A(); // OK, destructor call q->A<int>::~A<int>(); // OK, destructor call } — end example]
If the use of a template argument gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.
When name lookup for the component name of a template-id finds an overload set, both non-template functions in the overload set and function templates in the overload set for which the template-arguments do not match the template-parameters are ignored.
[Note 2: 
If none of the function templates have matching template-parameters, the program is ill-formed.
— end note]
When a simple-template-id does not name a function, a default template-argument is implicitly instantiated when the value of that default argument is needed.
[Example 7: template<typename T, typename U = int> struct S { }; S<bool>* p; // the type of p is S<bool, int>*
The default argument for U is instantiated to form the type S<bool, int>*.
— end example]
A template-argument followed by an ellipsis is a pack expansion.
110)110)
There is no such ambiguity in a default template-argument because the form of the template-parameter determines the allowable forms of the template-argument.

13.4.2 Template type arguments [temp.arg.type]

A template-argument for a template-parameter which is a type shall be a type-id.
[Example 1: template <class T> class X { }; template <class T> void f(T t) { } struct { } unnamed_obj; void f() { struct A { }; enum { e1 }; typedef struct { } B; B b; X<A> x1; // OK X<A*> x2; // OK X<B> x3; // OK f(e1); // OK f(unnamed_obj); // OK f(b); // OK } — end example]
[Note 1: 
A template type argument can be an incomplete type ([basic.types.general]).
— end note]

13.4.3 Template non-type arguments [temp.arg.nontype]

A template argument E for a non-type template-parameter with declared type T shall be such that the invented declaration T x = E ; satisfies the semantic constraints for the definition of a constexpr variable with static storage duration ([dcl.constexpr]).
If T contains a placeholder type ([dcl.spec.auto]) or a placeholder for a deduced class type ([dcl.type.class.deduct]), the type of the parameter is deduced from the above declaration.
[Note 1: 
E is a template-argument or (for a default template argument) an initializer-clause.
— end note]
If the parameter type thus deduced is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.
The value of a non-type template-parameter P of (possibly deduced) type T is determined from its template argument A as follows.
If T is not a class type and A is not a braced-init-list, A shall be a converted constant expression ([expr.const]) of type T; the value of P is A (as converted).
Otherwise, a temporary variable constexpr T v = A; is introduced.
The lifetime of v ends immediately after initializing it and any template parameter object (see below).
For each such variable, the id-expression v is termed a candidate initializer.
If T is a class type, a template parameter object ([temp.param]) exists that is constructed so as to be template-argument-equivalent to v; P denotes that template parameter object.
P is copy-initialized from an unspecified candidate initializer that is template-argument-equivalent to v.
If, for the initialization from any candidate initializer, the program is ill-formed.
Otherwise, the value of P is that of v.
For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer or point to (respectively):
[Example 1: template <int& r> class A{}; extern int x; A<x> a; // OK void f(int p) { constexpr int& r = p; // OK A<r> a; // error: a static constexpr int& variable cannot be initialized to refer to p here } — end example]
[Example 2: template<const int* pci> struct X { /* ... */ }; int ai[10]; X<ai> xi; // array to pointer and qualification conversions struct Y { /* ... */ }; template<const Y& b> struct Z { /* ... */ }; Y y; Z<y> z; // no conversion, but note extra cv-qualification template<int (&pa)[5]> struct W { /* ... */ }; int b[5]; W<b> w; // no conversion void f(char); void f(int); template<void (*pf)(int)> struct A { /* ... */ }; A<&f> a; // selects f(int) template<auto n> struct B { /* ... */ }; B<5> b1; // OK, template parameter type is int B<'a'> b2; // OK, template parameter type is char B<2.5> b3; // OK, template parameter type is double B<void(0)> b4; // error: template parameter type cannot be void template<int i> struct C { /* ... */ }; C<{ 42 }> c1; // OK struct J1 { J1 *self = this; }; B<J1{}> j1; // error: initialization of template parameter object is not a constant expression struct J2 { J2 *self = this; constexpr J2() {} constexpr J2(const J2&) {} }; B<J2{}> j2; // error: template parameter object not template-argument-equivalent to introduced temporary — end example]
[Note 2: 
A string-literal ([lex.string]) is not an acceptable template-argument for a template-parameter of non-class type.
[Example 3: template<class T, T p> class X { /* ... */ }; X<const char*, "Studebaker"> x; // error: string literal object as template-argument X<const char*, "Knope" + 1> x2; // error: subobject of string literal object as template-argument const char p[] = "Vivisectionist"; X<const char*, p> y; // OK struct A { constexpr A(const char*) {} }; X<A, "Pyrophoricity"> z; // OK, string-literal is a constructor argument to A — end example]
— end note]
[Note 3: 
A temporary object is not an acceptable template-argument when the corresponding template-parameter has reference type.
[Example 4: template<const int& CRI> struct B { /* ... */ }; B<1> b1; // error: temporary would be required for template argument int c = 1; B<c> b2; // OK struct X { int n; }; struct Y { const int &r; }; template<Y y> struct C { /* ... */ }; C<Y{X{1}.n}> c; // error: subobject of temporary object used to initialize // reference member of template parameter — end example]
— end note]

13.4.4 Template template arguments [temp.arg.template]

A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.
Only primary templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template parameter.
Any partial specializations ([temp.spec.partial]) associated with the primary template are considered when a specialization based on the template template-parameter is instantiated.
If a specialization is not reachable from the point of instantiation, and it would have been selected had it been reachable, the program is ill-formed, no diagnostic required.
[Example 1: template<class T> class A { // primary template int x; }; template<class T> class A<T*> { // partial specialization long x; }; template<template<class U> class V> class C { V<int> y; V<int*> z; }; C<A> c; // V<int> within C<A> uses the primary template, so c.y.x has type int // V<int*> within C<A> uses the partial specialization, so c.z.x has type long — end example]
A template-argument matches a template template-parameter P when P is at least as specialized as the template-argument A.
In this comparison, if P is unconstrained, the constraints on A are not considered.
If P contains a template parameter pack, then A also matches P if each of A's template parameters matches the corresponding template parameter in the template-head of P.
Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent ([temp.over.link]), and for template template-parameters, each of their corresponding template-parameters matches, recursively.
When P's template-head contains a template parameter pack ([temp.variadic]), the template parameter pack will match zero or more template parameters or template parameter packs in the template-head of A with the same type and form as the template parameter pack in P (ignoring whether those template parameters are template parameter packs).
[Example 2: template<class T> class A { /* ... */ }; template<class T, class U = T> class B { /* ... */ }; template<class ... Types> class C { /* ... */ }; template<auto n> class D { /* ... */ }; template<template<class> class P> class X { /* ... */ }; template<template<class ...> class Q> class Y { /* ... */ }; template<template<int> class R> class Z { /* ... */ }; X<A> xa; // OK X<B> xb; // OK X<C> xc; // OK Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK Z<D> zd; // OK — end example]
[Example 3: template <class T> struct eval; template <template <class, class...> class TT, class T1, class... Rest> struct eval<TT<T1, Rest...>> { }; template <class T1> struct A; template <class T1, class T2> struct B; template <int N> struct C; template <class T1, int N> struct D; template <class T1, class T2, int N = 17> struct E; eval<A<int>> eA; // OK, matches partial specialization of eval eval<B<int, float>> eB; // OK, matches partial specialization of eval eval<C<17>> eC; // error: C does not match TT in partial specialization eval<D<int, 17>> eD; // error: D does not match TT in partial specialization eval<E<int, float>> eE; // error: E does not match TT in partial specialization — end example]
[Example 4: template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> concept D = C<T> && requires (T t) { t.g(); }; template<template<C> class P> struct S { }; template<C> struct X { }; template<D> struct Y { }; template<typename T> struct Z { }; S<X> s1; // OK, X and P have equivalent constraints S<Y> s2; // error: P is not at least as specialized as Y S<Z> s3; // OK, P is at least as specialized as Z — end example]
A template template-parameter P is at least as specialized as a template template-argument A if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates.
Given an invented class template X with the template-head of A (including default arguments and requires-clause, if any):
  • Each of the two function templates has the same template parameters and requires-clause (if any), respectively, as P or A.
  • Each function template has a single function parameter whose type is a specialization of X with template arguments corresponding to the template parameters from the respective function template where, for each template parameter PP in the template-head of the function template, a corresponding template argument AA is formed.
    If PP declares a template parameter pack, then AA is the pack expansion PP... ([temp.variadic]); otherwise, AA is the id-expression PP.
If the rewrite produces an invalid type, then P is not at least as specialized as A.

13.5 Template constraints [temp.constr]

13.5.1 General [temp.constr.general]

[Note 1: 
Subclause [temp.constr] defines the meaning of constraints on template arguments.
The abstract syntax and satisfaction rules are defined in [temp.constr.constr].
Constraints are associated with declarations in [temp.constr.decl].
Declarations are partially ordered by their associated constraints ([temp.constr.order]).
— end note]

13.5.2 Constraints [temp.constr.constr]

13.5.2.1 General [temp.constr.constr.general]

A constraint is a sequence of logical operations and operands that specifies requirements on template arguments.
The operands of a logical operation are constraints.
There are four different kinds of constraints:
In order for a constrained template to be instantiated ([temp.spec]), its associated constraints shall be satisfied as described in the following subclauses.
[Note 1: 
Forming the name of a specialization of a class template, a variable template, or an alias template ([temp.names]) requires the satisfaction of its constraints.
Overload resolution requires the satisfaction of constraints on functions and function templates.
— end note]

13.5.2.2 Logical operations [temp.constr.op]

There are two binary logical operations on constraints: conjunction and disjunction.
[Note 1: 
These logical operations have no corresponding C++ syntax.
For the purpose of exposition, conjunction is spelled using the symbol  ∧  and disjunction is spelled using the symbol  ∨ .
The operands of these operations are called the left and right operands.
In the constraint A  ∧ B, A is the left operand, and B is the right operand.
— end note]
A conjunction is a constraint taking two operands.
To determine if a conjunction is satisfied, the satisfaction of the first operand is checked.
If that is not satisfied, the conjunction is not satisfied.
Otherwise, the conjunction is satisfied if and only if the second operand is satisfied.
A disjunction is a constraint taking two operands.
To determine if a disjunction is satisfied, the satisfaction of the first operand is checked.
If that is satisfied, the disjunction is satisfied.
Otherwise, the disjunction is satisfied if and only if the second operand is satisfied.
[Example 1: template<typename T> constexpr bool get_value() { return T::value; } template<typename T> requires (sizeof(T) > 1) && (get_value<T>()) void f(T); // has associated constraint sizeof(T) > 1  ∧  get_value<T>() void f(int); f('a'); // OK, calls f(int)
In the satisfaction of the associated constraints of f, the constraint sizeof(char) > 1 is not satisfied; the second operand is not checked for satisfaction.
— end example]
[Note 2: 
A logical negation expression ([expr.unary.op]) is an atomic constraint; the negation operator is not treated as a logical operation on constraints.
As a result, distinct negation constraint-expressions that are equivalent under [temp.over.link] do not subsume one another under [temp.constr.order].
Furthermore, if substitution to determine whether an atomic constraint is satisfied ([temp.constr.atomic]) encounters a substitution failure, the constraint is not satisfied, regardless of the presence of a negation operator.
[Example 2: template <class T> concept sad = false; template <class T> int f1(T) requires (!sad<T>); template <class T> int f1(T) requires (!sad<T>) && true; int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([temp.constr.atomic]) // are not formed from the same expression template <class T> concept not_sad = !sad<T>; template <class T> int f2(T) requires not_sad<T>; template <class T> int f2(T) requires not_sad<T> && true; int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sad template <class T> int f3(T) requires (!sad<typename T::type>); int i3 = f3(42); // error: associated constraints not satisfied due to substitution failure template <class T> concept sad_nested_type = sad<typename T::type>; template <class T> int f4(T) requires (!sad_nested_type<T>); int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
Here, requires (!sad<typename T​::​type>) requires that there is a nested type that is not sad, whereas requires (!sad_nested_type<T>) requires that there is no sad nested type.
— end example]
— end note]

13.5.2.3 Atomic constraints [temp.constr.atomic]

An atomic constraint is formed from an expression E and a mapping from the template parameters that appear within E to template arguments that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the parameter mapping ([temp.constr.decl]).
[Note 1: 
Atomic constraints are formed by constraint normalization.
— end note]
Two atomic constraints, and , are identical if they are formed from the same appearance of the same expression and if, given a hypothetical template A whose template-parameter-list consists of template-parameters corresponding and equivalent ([temp.over.link]) to those mapped by the parameter mappings of the expression, a template-id naming A whose template-arguments are the targets of the parameter mapping of is the same ([temp.type]) as a template-id naming A whose template-arguments are the targets of the parameter mapping of .
[Note 2: 
The comparison of parameter mappings of atomic constraints operates in a manner similar to that of declaration matching with alias template substitution ([temp.alias]).
[Example 1: template <unsigned N> constexpr bool Atomic = true; template <unsigned N> concept C = Atomic<N>; template <unsigned N> concept Add1 = C<N + 1>; template <unsigned N> concept AddOne = C<N + 1>; template <unsigned M> void f() requires Add1<2 * M>; template <unsigned M> int f() requires AddOne<2 * M> && true; int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N> // with mapping similar to template <unsigned N> struct WrapN; template <unsigned N> using Add1Ty = WrapN<N + 1>; template <unsigned N> using AddOneTy = WrapN<N + 1>; template <unsigned M> void g(Add1Ty<2 * M> *); template <unsigned M> void g(AddOneTy<2 * M> *); void h() { g<0>(nullptr); // OK, there is only one g } — end example]
As specified in [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.
[Example 2: template <unsigned N> void f2() requires Add1<2 * N>; template <unsigned N> int f2() requires Add1<N * 2> && true; void h2() { f2<0>(); // ill-formed, no diagnostic required: // requires determination of subsumption between atomic constraints that are // functionally equivalent but not equivalent } — end example]
— end note]
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression.
If substitution results in an invalid type or expression in the immediate context of the atomic constraint ([temp.deduct.general]), the constraint is not satisfied.
Otherwise, the lvalue-to-rvalue conversion is performed if necessary, and E shall be a constant expression of type bool.
The constraint is satisfied if and only if evaluation of E results in true.
If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required.
[Example 3: template<typename T> concept C = sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !true template<typename T> struct S { constexpr operator bool() const { return true; } }; template<typename T> requires (S<T>{}) void f(T); // #1 void f(int); // #2 void g() { f(0); // error: expression S<int>{} does not have type bool } // while checking satisfaction of deduced arguments of #1; // call is ill-formed even though #2 is a better match — end example]

13.5.2.4 Fold expanded constraint [temp.constr.fold]

A fold expanded constraint is formed from a constraint C and a fold-operator which can either be && or ||.
A fold expanded constraint is a pack expansion ([temp.variadic]).
Let N be the number of elements in the pack expansion parameters ([temp.variadic]).
A fold expanded constraint whose fold-operator is && is satisfied if it is a valid pack expansion and if or if for each i where in increasing order, C is satisfied when replacing each pack expansion parameter with the corresponding element.
No substitution takes place for any i greater than the smallest i for which the constraint is not satisfied.
A fold expanded constraint whose fold-operator is || is satisfied if it is a valid pack expansion, , and if for i where in increasing order, there is a smallest i for which C is satisfied when replacing each pack expansion parameter with the corresponding element.
No substitution takes place for any i greater than the smallest i for which the constraint is satisfied.
[Note 1: 
If the pack expansion expands packs of different size, then it is invalid and the fold expanded constraint is not satisfied.
— end note]
Two fold expanded constraints are compatible for subsumption if their respective constraints both contain an equivalent unexpanded pack ([temp.over.link]).

13.5.3 Constrained declarations [temp.constr.decl]

A template declaration ([temp.pre]) or templated function declaration ([dcl.fct]) can be constrained by the use of a requires-clause.
This allows the specification of constraints for that declaration as an expression:
Constraints can also be associated with a declaration through the use of type-constraints in a template-parameter-list or parameter-type-list.
Each of these forms introduces additional constraint-expressions that are used to constrain the declaration.
A declaration's associated constraints are defined as follows:
The formation of the associated constraints establishes the order in which constraints are instantiated when checking for satisfaction ([temp.constr.constr]).
[Example 1: template<typename T> concept C = true; template<C T> void f1(T); template<typename T> requires C<T> void f2(T); template<typename T> void f3(T) requires C<T>;
The functions f1, f2, and f3 have the associated constraint C<T>.
template<typename T> concept C1 = true; template<typename T> concept C2 = sizeof(T) > 0; template<C1 T> void f4(T) requires C2<T>; template<typename T> requires C1<T> && C2<T> void f5(T);
The associated constraints of f4 and f5 are C1<T>  ∧  C2<T>.
template<C1 T> requires C2<T> void f6(); template<C2 T> requires C1<T> void f7();
The associated constraints of f6 are C1<T>  ∧  C2<T>, and those of f7 are C2<T>  ∧  C1<T>.
— end example]
When determining whether a given introduced constraint-expression of a declaration in an instantiated specialization of a templated class is equivalent ([temp.over.link]) to the corresponding constraint-expression of a declaration outside the class body, is instantiated.
If the instantiation results in an invalid expression, the constraint-expressions are not equivalent.
[Note 1: 
This can happen when determining which member template is specialized by an explicit specialization declaration.
— end note]
[Example 2: template <class T> concept C = true; template <class T> struct A { template <class U> U f(U) requires C<typename T::type>; // #1 template <class U> U f(U) requires C<T>; // #2 }; template <> template <class U> U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
Substituting int for T in C<typename T​::​type> produces an invalid expression, so the specialization does not match #1.
Substituting int for T in C<T> produces C<int>, which is equivalent to the constraint-expression for the specialization, so it does match #2.
— end example]

13.5.4 Constraint normalization [temp.constr.normal]

The normal form of an expression E is a constraint that is defined as follows:
  • The normal form of an expression ( E ) is the normal form of E.
  • The normal form of an expression E1 || E2 is the disjunction of the normal forms of E1 and E2.
  • The normal form of an expression E1 && E2 is the conjunction of the normal forms of E1 and E2.
  • The normal form of a concept-id C<A, A, ..., A> is the normal form of the constraint-expression of C, after substituting A, A, ..., A for C's respective template parameters in the parameter mappings in each atomic constraint.
    If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.
    [Example 1: template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; template<typename V> concept C = B<V&>;
    Normalization of B's constraint-expression is valid and results in T​::​value (with the mapping )  ∨  true (with an empty mapping), despite the expression T​::​value being ill-formed for a pointer type T.
    Normalization of C's constraint-expression results in the program being ill-formed, because it would form the invalid type V&* in the parameter mapping.
    — end example]
  • For a fold-operator ([expr.prim.fold]) that is either && or ||, the normal form of an expression ( ... fold-operator E ) is the normal form of ( E fold-operator ... ).
  • For a fold-operator that is either && or ||, the normal form of an expression ( E1 fold-operator ... fold-operator E2 ) is the normal form of
  • The normal form of ( E && ... ) is a fold expanded constraint ([temp.constr.fold]) whose constraint is the normal form of E and whose fold-operator is &&.
  • The normal form of ( E || ... ) is a fold expanded constraint whose constraint is the normal form of E and whose fold-operator is ||.
  • The normal form of any other expression E is the atomic constraint whose expression is E and whose parameter mapping is the identity mapping.
The process of obtaining the normal form of a constraint-expression is called normalization.
[Note 1: 
Normalization of constraint-expressions is performed when determining the associated constraints ([temp.constr.constr]) of a declaration and when evaluating the value of an id-expression that names a concept specialization ([expr.prim.id]).
— end note]
[Example 2: template<typename T> concept C1 = sizeof(T) == 1; template<typename T> concept C2 = C1<T> && 1 == 2; template<typename T> concept C3 = requires { typename T::type; }; template<typename T> concept C4 = requires (T x) { ++x; }; template<C2 U> void f1(U); // #1 template<C3 U> void f2(U); // #2 template<C4 U> void f3(U); // #3
The associated constraints of #1 are sizeof(T) == 1 (with mapping )  ∧  1 == 2.

The associated constraints of #2 are requires { typename T​::​type; } (with mapping ).

The associated constraints of #3 are requires (T x) { ++x; } (with mapping ).
— end example]

13.5.5 Partial ordering by constraints [temp.constr.order]

A constraint P subsumes a constraint Q if and only if, for every disjunctive clause in the disjunctive normal form111 of P, subsumes every conjunctive clause in the conjunctive normal form112 of Q, where
  • a disjunctive clause subsumes a conjunctive clause if and only if there exists an atomic constraint in for which there exists an atomic constraint in such that subsumes ,
  • an atomic constraint A subsumes another atomic constraint B if and only if A and B are identical using the rules described in [temp.constr.atomic], and
  • a fold expanded constraint A subsumes another fold expanded constraint B if they are compatible for subsumption, have the same fold-operator, and the constraint of A subsumes that of B.
[Example 1: 
Let A and B be atomic constraints.
The constraint A  ∧ B subsumes A, but A does not subsume A  ∧ B.
The constraint A subsumes A  ∨ B, but A  ∨ B does not subsume A.
Also note that every constraint subsumes itself.
— end example]
[Note 1: 
The subsumption relation defines a partial ordering on constraints.
This partial ordering is used to determine
— end note]
A declaration D1 is at least as constrained as a declaration D2 if
  • D1 and D2 are both constrained declarations and D1's associated constraints subsume those of D2; or
  • D2 has no associated constraints.
A declaration D1 is more constrained than another declaration D2 when D1 is at least as constrained as D2, and D2 is not at least as constrained as D1.
[Example 2: template<typename T> concept C1 = requires(T t) { --t; }; template<typename T> concept C2 = C1<T> && requires(T t) { *t; }; template<C1 T> void f(T); // #1 template<C2 T> void f(T); // #2 template<typename T> void g(T); // #3 template<C1 T> void g(T); // #4 f(0); // selects #1 f((int*)0); // selects #2 g(true); // selects #3 because C1<bool> is not satisfied g(0); // selects #4 — end example]
A non-template function F1 is more partial-ordering-constrained than a non-template function F2 if
  • they have the same non-object-parameter-type-lists ([dcl.fct]), and
  • if they are member functions, both are direct members of the same class, and
  • if both are non-static member functions, they have the same types for their object parameters, and
  • the declaration of F1 is more constrained than the declaration of F2.
111)111)
A constraint is in disjunctive normal form when it is a disjunction of clauses where each clause is a conjunction of fold expanded or atomic constraints.
For atomic constraints A, B, and C, the disjunctive normal form of the constraint A  ∧ (B  ∨ C) is (A  ∧ B)  ∨ (A  ∧ C).
Its disjunctive clauses are (A  ∧ B) and (A  ∧ C).
112)112)
A constraint is in conjunctive normal form when it is a conjunction of clauses where each clause is a disjunction of fold expanded or atomic constraints.
For atomic constraints A, B, and C, the constraint A  ∧ (B  ∨ C) is in conjunctive normal form.
Its conjunctive clauses are A and (B  ∨ C).

13.6 Type equivalence [temp.type]

Two template-ids are the same if
Two template-ids that are the same refer to the same class, function, or variable.
Two values are template-argument-equivalent if they are of the same type and
  • they are of integral type and their values are the same, or
  • they are of floating-point type and their values are identical, or
  • they are of type std​::​nullptr_t, or
  • they are of enumeration type and their values are the same,113 or
  • they are of pointer type and they have the same pointer value, or
  • they are of pointer-to-member type and they refer to the same class member or are both the null member pointer value, or
  • they are of reference type and they refer to the same object or function, or
  • they are of array type and their corresponding elements are template-argument-equivalent,114 or
  • they are of union type and either they both have no active member or they have the same active member and their active members are template-argument-equivalent, or
  • they are of a closure type ([expr.prim.lambda.closure]), or
  • they are of class type and their corresponding direct subobjects and reference members are template-argument-equivalent.
[Example 1: 
template<class E, int size> class buffer { /* ... */ }; buffer<char,2*512> x; buffer<char,1024> y; declares x and y to be of the same type, and template<class T, void(*err_fct)()> class list { /* ... */ }; list<int,&error_handler1> x1; list<int,&error_handler2> x2; list<int,&error_handler2> x3; list<char,&error_handler2> x4; declares x2 and x3 to be of the same type.
Their type differs from the types of x1 and x4.
template<class T> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y<int> > y; X<Z<int> > z; declares y and z to be of the same type.
— end example]
If an expression e is type-dependent, decltype(e) denotes a unique dependent type.
Two such decltype-specifiers refer to the same type only if their expressions are equivalent ([temp.over.link]).
[Note 1: 
However, such a type might be aliased, e.g., by a typedef-name.
— end note]
For a type template parameter pack T, T...[constant-expression] denotes a unique dependent type.
If the constant-expression of a pack-index-specifier is value-dependent, two such pack-index-specifiers refer to the same type only if their constant-expressions are equivalent ([temp.over.link]).
Otherwise, two such pack-index-specifiers refer to the same type only if their indexes have the same value.
113)113)
The identity of enumerators is not preserved.
114)114)
An array as a template-parameter decays to a pointer.

13.7 Template declarations [temp.decls]

13.7.1 General [temp.decls.general]

The template parameters of a template are specified in the angle bracket enclosed list that immediately follows the keyword template.
A primary template declaration is one in which the name of the template is not followed by a template-argument-list.
The template argument list of a primary template is the template argument list of its template-head ([temp.arg]).
A template declaration in which the name of the template is followed by a template-argument-list is a partial specialization ([temp.spec.partial]) of the template named in the declaration, which shall be a class or variable template.
For purposes of name lookup and instantiation, default arguments, type-constraints, requires-clauses ([temp.pre]), and noexcept-specifiers of function templates and of member functions of class templates are considered definitions; each default argument, type-constraint, requires-clause, or noexcept-specifier is a separate definition which is unrelated to the templated function definition or to any other default arguments, type-constraints, requires-clauses, or noexcept-specifiers.
For the purpose of instantiation, the substatements of a constexpr if statement are considered definitions.
Because an alias-declaration cannot declare a template-id, it is not possible to partially or explicitly specialize an alias template.

13.7.2 Class templates [temp.class]

13.7.2.1 General [temp.class.general]

A class template defines the layout and operations for an unbounded set of related types.
[Example 1: 
It is possible for a single class template List to provide an unbounded set of class definitions: one class List<T> for every type T, each describing a linked list of elements of type T.
Similarly, a class template Array describing a contiguous, dynamic array can be defined like this: template<class T> class Array { T* v; int sz; public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } };
The prefix template<class T> specifies that a template is being declared and that a type-name T can be used in the declaration.
In other words, Array is a parameterized type with T as its parameter.
— end example]
[Note 1: 
When a member of a class template is defined outside of the class template definition, the member definition is defined as a template definition with the template-head equivalent to that of the class template.
The names of the template parameters used in the definition of the member can differ from the template parameter names used in the class template definition.
The class template name in the member definition is followed by the template argument list of the template-head ([temp.arg]).
[Example 2: template<class T1, class T2> struct A { void f1(); void f2(); }; template<class T2, class T1> void A<T2,T1>::f1() { } // OK template<class T2, class T1> void A<T1,T2>::f2() { } // error
template<class ... Types> struct B { void f3(); void f4(); }; template<class ... Types> void B<Types ...>::f3() { } // OK template<class ... Types> void B<Types>::f4() { } // error
template<typename T> concept C = true; template<typename T> concept D = true; template<C T> struct S { void f(); void g(); void h(); template<D U> struct Inner; }; template<C A> void S<A>::f() { } // OK, template-heads match template<typename T> void S<T>::g() { } // error: no matching declaration for S<T> template<typename T> requires C<T> // ill-formed, no diagnostic required: template-heads are void S<T>::h() { } // functionally equivalent but not equivalent template<C X> template<D Y> struct S<X>::Inner { }; // OK — end example]
— end note]
In a partial specialization, explicit specialization or explicit instantiation of a class template, the class-key shall agree in kind with the original class template declaration ([dcl.type.elab]).

13.7.2.2 Member functions of class templates [temp.mem.func]

A member function of a class template may be defined outside of the class template definition in which it is declared.
[Example 1: template<class T> class Array { T* v; int sz; public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } };
declares three member functions of a class template.
The subscript function can be defined like this: template<class T> T& Array<T>::operator[](int i) { if (i<0 || sz<=i) error("Array: range error"); return v[i]; }
A constrained member function can be defined out of line: template<typename T> concept C = requires { typename T::type; }; template<typename T> struct S { void f() requires C<T>; void g() requires C<T>; }; template<typename T> void S<T>::f() requires C<T> { } // OK template<typename T> void S<T>::g() { } // error: no matching function in S<T>
— end example]
The template-arguments for a member function of a class template are determined by the template-arguments of the type of the object for which the member function is called.
[Example 2: 
The template-argument for Array<T>​::​operator[] will be determined by the Array to which the subscripting operation is applied.
Array<int> v1(20); Array<dcomplex> v2(30); v1[3] = 7; // Array<int>​::​operator[] v2[3] = dcomplex(7,8); // Array<dcomplex>​::​operator[] — end example]

13.7.2.3 Deduction guides [temp.deduct.guide]

Deduction guides are used when a template-name appears as a type specifier for a deduced class type ([dcl.type.class.deduct]).
Deduction guides are not found by name lookup.
Instead, when performing class template argument deduction ([over.match.class.deduct]), all reachable deduction guides declared for the class template are considered.
[Example 1: template<class T, class D = int> struct S { T data; }; template<class U> S(U) -> S<typename U::type>; struct A { using type = short; operator type(); }; S x{A()}; // x is of type S<short, int> — end example]
The same restrictions apply to the parameter-declaration-clause of a deduction guide as in a function declaration ([dcl.fct]), except that a generic parameter type placeholder ([dcl.spec.auto]) shall not appear in the parameter-declaration-clause of a deduction guide.
The simple-template-id shall name a class template specialization.
The template-name shall be the same identifier as the template-name of the simple-template-id.
A deduction-guide shall inhabit the scope to which the corresponding class template belongs and, for a member class template, have the same access.
Two deduction guide declarations for the same class template shall not have equivalent parameter-declaration-clauses if either is reachable from the other.

13.7.2.4 Member classes of class templates [temp.mem.class]

A member class of a class template may be defined outside the class template definition in which it is declared.
[Note 1: 
The member class must be defined before its first use that requires an instantiation ([temp.inst]).
For example, template<class T> struct A { class B; }; A<int>::B* b1; // OK, requires A to be defined but not A​::​B template<class T> class A<T>::B { }; A<int>::B b2; // OK, requires A​::​B to be defined
— end note]

13.7.2.5 Static data members of class templates [temp.static]

A definition for a static data member or static data member template may be provided in a namespace scope enclosing the definition of the static member's class template.
[Example 1: template<class T> class X { static T s; }; template<class T> T X<T>::s = 0; struct limits { template<class T> static const T min; // declaration }; template<class T> const T limits::min = { }; // definition — end example]
An explicit specialization of a static data member declared as an array of unknown bound can have a different bound from its definition, if any.
[Example 2: template <class T> struct A { static int i[]; }; template <class T> int A<T>::i[4]; // 4 elements template <> int A<int>::i[] = { 1 }; // OK, 1 element — end example]

13.7.2.6 Enumeration members of class templates [temp.mem.enum]

An enumeration member of a class template may be defined outside the class template definition.
[Example 1: template<class T> struct A { enum E : T; }; A<int> a; template<class T> enum A<T>::E : T { e1, e2 }; A<int>::E e = A<int>::e1; — end example]

13.7.3 Member templates [temp.mem]

A template can be declared within a class or class template; such a template is called a member template.
A member template can be defined within or outside its class definition or class template definition.
A member template of a class template that is defined outside of its class template definition shall be specified with a template-head equivalent to that of the class template followed by a template-head equivalent to that of the member template ([temp.over.link]).
[Example 1: template<class T> struct string { template<class T2> int compare(const T2&); template<class T2> string(const string<T2>& s) { /* ... */ } }; template<class T> template<class T2> int string<T>::compare(const T2& s) { } — end example]
[Example 2: template<typename T> concept C1 = true; template<typename T> concept C2 = sizeof(T) <= 4; template<C1 T> struct S { template<C2 U> void f(U); template<C2 U> void g(U); }; template<C1 T> template<C2 U> void S<T>::f(U) { } // OK template<C1 T> template<typename U> void S<T>::g(U) { } // error: no matching function in S<T> — end example]
A local class of non-closure type shall not have member templates.
Access control rules apply to member template names.
A destructor shall not be a member template.
A non-template member function ([dcl.fct]) with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class.
When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.
[Example 3: template <class T> struct A { void f(int); template <class T2> void f(T2); }; template <> void A<int>::f(int) { } // non-template member function template <> template <> void A<int>::f<>(int) { } // member function template specialization int main() { A<char> ac; ac.f(1); // non-template ac.f('c'); // template ac.f<>(1); // template } — end example]
A member function template shall not be declared virtual.
[Example 4: template <class T> struct AA { template <class C> virtual void g(C); // error virtual void f(); // OK }; — end example]
A specialization of a member function template does not override a virtual function from a base class.
[Example 5: class B { virtual void f(int); }; class D : public B { template <class T> void f(T); // does not override B​::​f(int) void f(int i) { f<>(i); } // overriding function that calls the function template specialization }; — end example]
[Note 1: 
A specialization of a conversion function template is referenced in the same way as a non-template conversion function that converts to the same type ([class.conv.fct]).
[Example 6: struct A { template <class T> operator T*(); }; template <class T> A::operator T*() { return 0; } template <> A::operator char*() { return 0; } // specialization template A::operator void*(); // explicit instantiation int main() { A a; int* ip; ip = a.operator int*(); // explicit call to template operator A​::​operator int*() } — end example]
There is no syntax to form a template-id ([temp.names]) by providing an explicit template argument list ([temp.arg.explicit]) for a conversion function template.
— end note]

13.7.4 Variadic templates [temp.variadic]

A template parameter pack is a template parameter that accepts zero or more template arguments.
[Example 1: template<class ... Types> struct Tuple { }; Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Types contains one argument: int Tuple<int, float> t2; // Types contains two arguments: int and float Tuple<0> error; // error: 0 is not a type — end example]
A function parameter pack is a function parameter that accepts zero or more function arguments.
[Example 2: template<class ... Types> void f(Types ... args); f(); // args contains no arguments f(1); // args contains one argument: int f(2, 1.0); // args contains two arguments: int and double — end example]
An init-capture pack is a lambda capture that introduces an init-capture for each of the elements in the pack expansion of its initializer.
[Example 3: template <typename... Args> void foo(Args... args) { [...xs=args]{ bar(xs...); // xs is an init-capture pack }; } foo(); // xs contains zero init-captures foo(1); // xs contains one init-capture — end example]
A structured binding pack is an sb-identifier that introduces zero or more structured bindings ([dcl.struct.bind]).
[Example 4: auto foo() -> int(&)[2]; template <class T> void g() { auto [...a] = foo(); // a is a structured binding pack containing two elements auto [b, c, ...d] = foo(); // d is a structured binding pack containing zero elements } — end example]
A pack is a template parameter pack, a function parameter pack, an init-capture pack, or a structured binding pack.
The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack.
The number of elements of an init-capture pack is the number of elements in the pack expansion of its initializer.
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below).
The form of the pattern depends on the context in which the expansion occurs.
Pack expansions can occur in the following contexts:
[Example 5: template<class ... Types> void f(Types ... rest); template<class ... Types> void g(Types ... rest) { f(&rest ...); // “&rest ...'' is a pack expansion; “&rest'' is its pattern } — end example]
For the purpose of determining whether a pack satisfies a rule regarding entities other than packs, the pack is considered to be the entity that would result from an instantiation of the pattern in which it appears.
A pack whose name appears within the pattern of a pack expansion is expanded by that pack expansion.
An appearance of the name of a pack is only expanded by the innermost enclosing pack expansion.
The pattern of a pack expansion shall name one or more packs that are not expanded by a nested pack expansion; such packs are called unexpanded packs in the pattern.
All of the packs expanded by a pack expansion shall have the same number of arguments specified.
An appearance of a name of a pack that is not expanded is ill-formed.
[Example 6: template<typename...> struct Tuple {}; template<typename T1, typename T2> struct Pair {}; template<class ... Args1> struct zip { template<class ... Args2> struct with { typedef Tuple<Pair<Args1, Args2> ... > type; }; }; typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> typedef zip<short>::with<unsigned short, unsigned>::type T2; // error: different number of arguments specified for Args1 and Args2 template<class ... Args> void g(Args ... args) { // OK, Args is expanded by the function parameter pack args f(const_cast<const Args*>(&args)...); // OK, “Args'' and “args'' are expanded f(5 ...); // error: pattern does not contain any packs f(args); // error: pack “args'' is not expanded f(h(args ...) + args ...); // OK, first “args'' expanded within h, // second “args'' expanded within f } — end example]
The instantiation of a pack expansion considers items , where N is the number of elements in the pack expansion parameters.
Each is generated by instantiating the pattern and replacing each pack expansion parameter with its element.
Such an element, in the context of the instantiation, is interpreted as follows:
  • if the pack is a template parameter pack, the element is an id-expression (for a non-type template parameter pack), a typedef-name (for a type template parameter pack declared without template), or a template-name (for a type template parameter pack declared with template), designating the corresponding type or value template argument;
  • if the pack is a function parameter pack, the element is an id-expression designating the function parameter that resulted from instantiation of the function parameter pack declaration;
  • if the pack is an init-capture pack, the element is an id-expression designating the variable introduced by the init-capture that resulted from instantiation of the init-capture pack declaration; otherwise
  • if the pack is a structured binding pack, the element is an id-expression designating the structured binding in the pack that resulted from the structured binding declaration.
When N is zero, the instantiation of a pack expansion does not alter the syntactic interpretation of the enclosing construct, even in cases where omitting the pack expansion entirely would otherwise be ill-formed or would result in an ambiguity in the grammar.
The instantiation of a sizeof... expression ([expr.sizeof]) produces an integral constant with value N.
When instantiating a pack-index-expression P, let K be the index of P.
The instantiation of P is the id-expression .
When instantiating a pack-index-specifier P, let K be the index of P.
The instantiation of P is the typedef-name .
The instantiation of an alignment-specifier with an ellipsis produces .
The instantiation of a fold-expression ([expr.prim.fold]) produces:
  • ( (( op ) op ) op ) for a unary left fold,
  • ( op ( op ( op )) ) for a unary right fold,
  • ( (((E op ) op ) op ) op ) for a binary left fold, and
  • ( op ( op ( op ( op E))) ) for a binary right fold.
In each case, op is the fold-operator.
For a binary fold, E is generated by instantiating the cast-expression that did not contain an unexpanded pack.
[Example 7: template<typename ...Args> bool all(Args ...args) { return (... && args); } bool b = all(true, true, true, false);
Within the instantiation of all, the returned expression expands to ((true && true) && true) && false, which evaluates to false.
— end example]
If N is zero for a unary fold, the value of the expression is shown in Table 20; if the operator is not listed in Table 20, the instantiation is ill-formed.
Table 20 — Value of folding empty sequences [tab:temp.fold.empty]
Operator
Value when pack is empty
&&
true
||
false
,
void()
A fold expanded constraint is not instantiated ([temp.constr.fold]).
The instantiation of any other pack expansion produces a list of elements .
[Note 1: 
The variety of list varies with the context: expression-list, base-specifier-list, template-argument-list, etc.
— end note]
When N is zero, the instantiation of the expansion produces an empty list.
[Example 8: template<class... T> struct X : T... { }; template<class... T> void f(T... values) { X<T...> x(values...); } template void f<>(); // OK, X<> has no base classes // x is a variable of type X<> that is value-initialized — end example]

13.7.5 Friends [temp.friend]

A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class.
[Example 1: template<class T> class task; template<class T> task<T>* preempt(task<T>*); template<class T> class task { friend void next_time(); friend void process(task<T>*); friend task<T>* preempt<T>(task<T>*); template<class C> friend int func(C); friend class task<int>; template<class P> friend class frd; };
Here, each specialization of the task class template has the function next_time as a friend; because process does not have explicit template-arguments, each specialization of the task class template has an appropriately typed function process as a friend, and this friend is not a function template specialization; because the friend preempt has an explicit template-argument T, each specialization of the task class template has the appropriate specialization of the function template preempt as a friend; and each specialization of the task class template has all specializations of the function template func as friends.
Similarly, each specialization of the task class template has the class template specialization task<int> as a friend, and has all specializations of the class template frd as friends.
— end example]
Friend classes, class templates, functions, or function templates can be declared within a class template.
When a template is instantiated, its friend declarations are found by name lookup as if the specialization had been explicitly declared at its point of instantiation.
[Note 1: 
They can introduce entities that belong to an enclosing namespace scope ([dcl.meaning]), in which case they are attached to the same module as the class template ([module.unit]).
— end note]
A friend template may be declared within a class or class template.
A friend function template may be defined within a class or class template, but a friend class template may not be defined in a class or class template.
In these cases, all specializations of the friend class or friend function template are friends of the class or class template granting friendship.
[Example 2: class A { template<class T> friend class B; // OK template<class T> friend void f(T) { /* ... */ } // OK }; — end example]
A template friend declaration specifies that all specializations of that template, whether they are implicitly instantiated ([temp.inst]), partially specialized ([temp.spec.partial]) or explicitly specialized ([temp.expl.spec]), are friends of the class containing the template friend declaration.
[Example 3: class X { template<class T> friend struct A; class Y { }; }; template<class T> struct A { X::Y ab; }; // OK template<class T> struct A<T*> { X::Y ab; }; // OK — end example]
A template friend declaration may declare a member of a dependent type to be a friend.
The friend declaration shall declare a function or specify a type with an elaborated-type-specifier, in either case with a nested-name-specifier ending with a simple-template-id, C, whose template-name names a class template.
The template parameters of the template friend declaration shall be deducible from C ([temp.deduct.type]).
In this case, a member of a specialization S of the class template is a friend of the class granting friendship if deduction of the template parameters of C from S succeeds, and substituting the deduced template arguments into the friend declaration produces a declaration that corresponds to the member of the specialization.
[Example 4: template<class T> struct A { struct B { }; void f(); struct D { void g(); }; T h(); template<T U> T i(); }; template<> struct A<int> { struct B { }; int f(); struct D { void g(); }; template<int U> int i(); }; template<> struct A<float*> { int *h(); }; class C { template<class T> friend struct A<T>::B; // grants friendship to A<int>​::​B even though // it is not a specialization of A<T>​::​B template<class T> friend void A<T>::f(); // does not grant friendship to A<int>​::​f() // because its return type does not match template<class T> friend void A<T>::D::g(); // error: A<T>​::​D does not end with a simple-template-id template<class T> friend int *A<T*>::h(); // grants friendship to A<int*>​::​h() and A<float*>​::​h() template<class T> template<T U> // grants friendship to instantiations of A<T>​::​i() and friend T A<T>::i(); // to A<int>​::​i(), and thereby to all specializations }; // of those function templates — end example]
A friend template shall not be declared in a local class.
Friend declarations shall not declare partial specializations.
[Example 5: template<class T> class A { }; class X { template<class T> friend class A<T*>; // error }; — end example]
When a friend declaration refers to a specialization of a function template, the function parameter declarations shall not include default arguments, nor shall the inline, constexpr, or consteval specifiers be used in such a declaration.
A non-template friend declaration with a requires-clause shall be a definition.
A friend function template with a constraint that depends on a template parameter from an enclosing template shall be a definition.
Such a constrained friend function or function template declaration does not declare the same function or function template as a declaration in any other scope.

13.7.6 Partial specialization [temp.spec.partial]

13.7.6.1 General [temp.spec.partial.general]

A partial specialization of a template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization ([temp.spec.partial.match]).
A declaration of the primary template shall precede any partial specialization of that template.
A partial specialization shall be reachable from any use of a template specialization that would make use of the partial specialization as the result of an implicit or explicit instantiation; no diagnostic is required.
Two partial specialization declarations declare the same entity if they are partial specializations of the same template and have equivalent template-heads and template argument lists ([temp.over.link]).
Each partial specialization is a distinct template.
[Example 1: template<class T1, class T2, int I> class A { }; template<class T, int I> class A<T, T*, I> { }; template<class T1, class T2, int I> class A<T1*, T2, I> { }; template<class T> class A<int, T*, 5> { }; template<class T1, class T2, int I> class A<T1, T2*, I> { };
The first declaration declares the primary (unspecialized) class template.
The second and subsequent declarations declare partial specializations of the primary template.
— end example]
A partial specialization may be constrained ([temp.constr]).
[Example 2: template<typename T> concept C = true; template<typename T> struct X { }; template<typename T> struct X<T*> { }; // #1 template<C T> struct X<T> { }; // #2
Both partial specializations are more specialized than the primary template.
#1 is more specialized because the deduction of its template arguments from the template argument list of the class template specialization succeeds, while the reverse does not.
#2 is more specialized because the template arguments are equivalent, but the partial specialization is more constrained ([temp.constr.order]).
— end example]
The template argument list of a partial specialization is the template-argument-list following the name of the template.
A partial specialization may be declared in any scope in which the corresponding primary template may be defined ([dcl.meaning], [class.mem], [temp.mem]).
[Example 3: template<class T> struct A { struct C { template<class T2> struct B { }; template<class T2> struct B<T2**> { }; // partial specialization #1 }; }; // partial specialization of A<T>​::​C​::​B<T2> template<class T> template<class T2> struct A<T>::C::B<T2*> { }; // #2 A<short>::C::B<int*> absip; // uses partial specialization #2 — end example]
Partial specialization declarations do not introduce a name.
Instead, when the primary template name is used, any reachable partial specializations of the primary template are also considered.
[Note 1: 
One consequence is that a using-declaration which refers to a class template does not restrict the set of partial specializations that are found through the using-declaration.
— end note]
[Example 4: namespace N { template<class T1, class T2> class A { }; // primary template } using N::A; // refers to the primary template namespace N { template<class T> class A<T, T*> { }; // partial specialization } A<int,int*> a; // uses the partial specialization, which is found through the using-declaration // which refers to the primary template — end example]
A non-type argument is non-specialized if it is the name of a non-type parameter.
All other non-type arguments are specialized.
Within the argument list of a partial specialization, the following restrictions apply:
  • The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the partial specialization.
    [Example 5: template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error — end example]
  • The partial specialization shall be more specialized than the primary template ([temp.spec.partial.order]).
  • The template parameter list of a partial specialization shall not contain default template argument values.115
  • An argument shall not contain an unexpanded pack.
    If an argument is a pack expansion ([temp.variadic]), it shall be the last argument in the template argument list.
The usual access checking rules do not apply to non-dependent names used to specify template arguments of the simple-template-id of the partial specialization.
[Note 2: 
The template arguments can be private types or objects that would normally not be accessible.
Dependent names cannot be checked when declaring the partial specialization, but will be checked when substituting into the partial specialization.
— end note]
115)115)
There is no context in which they would be used.

13.7.6.2 Matching of partial specializations [temp.spec.partial.match]

When a template is used in a context that requires an instantiation of the template, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations.
This is done by matching the template arguments of the template specialization with the template argument lists of the partial specializations.
  • If exactly one matching partial specialization is found, the instantiation is generated from that partial specialization.
  • If more than one matching partial specialization is found, the partial order rules ([temp.spec.partial.order]) are used to determine whether one of the partial specializations is more specialized than the others.
    If such a partial specialization exists, the instantiation is generated from that partial specialization; otherwise, the use of the template is ambiguous and the program is ill-formed.
  • If no matches are found, the instantiation is generated from the primary template.
A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list, and the deduced template arguments satisfy the associated constraints of the partial specialization, if any.
[Example 1: template<class T1, class T2, int I> class A { }; // #1 template<class T, int I> class A<T, T*, I> { }; // #2 template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3 template<class T> class A<int, T*, 5> { }; // #4 template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 — end example]
[Example 2: template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> struct S { }; // #1 template<C T> struct S<T> { }; // #2 struct Arg { void f(); }; S<int> s1; // uses #1; the constraints of #2 are not satisfied S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized — end example]
If the template arguments of a partial specialization cannot be deduced because of the structure of its template-parameter-list and the template-id, the program is ill-formed.
[Example 3: template <int I, int J> struct A {}; template <int I> struct A<I+5, I*2> {}; // error template <int I> struct A<I, I> {}; // OK template <int I, int J, int K> struct B {}; template <int I> struct B<I, I*2, 2> {}; // OK — end example]
In a name that refers to a specialization of a class or variable template (e.g., A<int, int, 1>), the argument list shall match the template parameter list of the primary template.
The template arguments of a partial specialization are deduced from the arguments of the primary template.

13.7.6.3 Partial ordering of partial specializations [temp.spec.partial.order]

For two partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second according to the ordering rules for function templates:
  • Each of the two function templates has the same template parameters and associated constraints as the corresponding partial specialization.
  • Each function template has a single function parameter whose type is a class template specialization where the template arguments are the corresponding template parameters from the function template for each template argument in the template-argument-list of the simple-template-id of the partial specialization.
[Example 1: template<int I, int J, class T> class X { }; template<int I, int J> class X<I, J, int> { }; // #1 template<int I> class X<I, I, int> { }; // #2 template<int I0, int J0> void f(X<I0, J0, int>); // A template<int I0> void f(X<I0, I0, int>); // B template <auto v> class Y { }; template <auto* p> class Y<p> { }; // #3 template <auto** pp> class Y<pp> { }; // #4 template <auto* p0> void g(Y<p0>); // C template <auto** pp0> void g(Y<pp0>); // D
According to the ordering rules for function templates, the function template B is more specialized than the function template A and the function template D is more specialized than the function template C.
Therefore, the partial specialization #2 is more specialized than the partial specialization #1 and the partial specialization #4 is more specialized than the partial specialization #3.
— end example]
[Example 2: template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> concept D = C<T> && requires (T t) { t.f(); }; template<typename T> class S { }; template<C T> class S<T> { }; // #1 template<D T> class S<T> { }; // #2 template<C T> void f(S<T>); // A template<D T> void f(S<T>); // B
The partial specialization #2 is more specialized than #1 because B is more specialized than A.
— end example]

13.7.6.4 Members of class template partial specializations [temp.spec.partial.member]

The members of the class template partial specialization are unrelated to the members of the primary template.
Class template partial specialization members that are used in a way that requires a definition shall be defined; the definitions of members of the primary template are never used as definitions for members of a class template partial specialization.
An explicit specialization of a member of a class template partial specialization is declared in the same way as an explicit specialization of a member of the primary template.
[Example 1: // primary class template template<class T, int I> struct A { void f(); }; // member of primary class template template<class T, int I> void A<T,I>::f() { } // class template partial specialization template<class T> struct A<T,2> { void f(); void g(); void h(); }; // member of class template partial specialization template<class T> void A<T,2>::g() { } // explicit specialization template<> void A<char,2>::h() { } int main() { A<char,0> a0; A<char,2> a2; a0.f(); // OK, uses definition of primary template's member a2.g(); // OK, uses definition of partial specialization's member a2.h(); // OK, uses definition of explicit specialization's member a2.f(); // error: no definition of f for A<T,2>; the primary template is not used here } — end example]
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 ([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.
If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template.
If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.
[Example 2: template<class T> struct A { template<class T2> struct B {}; // #1 template<class T2> struct B<T2*> {}; // #2 }; template<> template<class T2> struct A<short>::B {}; // #3 A<char>::B<int*> abcip; // uses #2 A<short>::B<int*> absip; // uses #3 A<char>::B<int> abci; // uses #1 — end example]

13.7.7 Function templates [temp.fct]

13.7.7.1 General [temp.fct.general]

A function template defines an unbounded set of related functions.
[Example 1: 
A family of sort functions can be declared like this: template<class T> class Array { }; template<class T> void sort(Array<T>&);
— end example]
[Note 1: 
A function template can have the same name as other function templates and non-template functions ([dcl.fct]) in the same scope.
— end note]
A non-template function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.116
116)116)
That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name.
If such a non-template function is odr-used ([basic.def.odr]) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.

13.7.7.3 Partial ordering of function templates [temp.func.order]

If multiple function templates share a name, the use of that name can be ambiguous because template argument deduction ([temp.deduct]) may identify a specialization for more than one function template.
Partial ordering of overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization refers:
Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type.
The deduction process determines whether one of the templates is more specialized than the other.
If so, the more specialized template is the one chosen by the partial ordering process.
If both deductions succeed, the partial ordering selects the more constrained template (if one exists) as determined below.
To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.
[Note 1: 
The type replacing the placeholder in the type of the value synthesized for a non-type template parameter is also a unique synthesized type.
— end note]
Each function template M that is a member function is considered to have a new first parameter of type X(M), described below, inserted in its function parameter list.
If exactly one of the function templates was considered by overload resolution via a rewritten candidate ([over.match.oper]) with a reversed order of parameters, then the order of the function parameters in its transformed template is reversed.
For a function template M with cv-qualifiers cv that is a member of a class A:
  • The type X(M) is “rvalue reference to cv A” if the optional ref-qualifier of M is && or if M has no ref-qualifier and the positionally-corresponding parameter of the other transformed template has rvalue reference type; if this determination depends recursively upon whether X(M) is an rvalue reference type, it is not considered to have rvalue reference type.
  • Otherwise, X(M) is “lvalue reference to cv A.
[Note 2: 
This allows a non-static member to be ordered with respect to a non-member function and for the results to be equivalent to the ordering of two equivalent non-members.
— end note]
[Example 1: struct A { }; template<class T> struct B { template<class R> int operator*(R&); // #1 }; template<class T, class R> int operator*(T&, R&); // #2 // The declaration of B​::​operator* is transformed into the equivalent of // template<class R> int operator*(B<A>&, R&);      // #1a int main() { A a; B<A> b; b * a; // calls #1 } — end example]
Using the transformed function template's function type, perform type deduction against the other template as described in [temp.deduct.partial].
[Example 2: template<class T> struct A { A(); }; template<class T> void f(T); template<class T> void f(T*); template<class T> void f(const T*); template<class T> void g(T); template<class T> void g(T&); template<class T> void h(const T&); template<class T> void h(A<T>&); void m() { const int* p; f(p); // f(const T*) is more specialized than f(T) or f(T*) float x; g(x); // ambiguous: g(T) or g(T&) A<int> z; h(z); // overload resolution selects h(A<T>&) const A<int> z2; h(z2); // h(const T&) is called because h(A<T>&) is not callable } — end example]
[Note 3: 
Since, in a call context, such type deduction considers only parameters for which there are explicit call arguments, some parameters are ignored (namely, function parameter packs, parameters with default arguments, and ellipsis parameters).
[Example 3: template<class T> void f(T); // #1 template<class T> void f(T*, int=1); // #2 template<class T> void g(T); // #3 template<class T> void g(T*, ...); // #4 int main() { int* ip; f(ip); // calls #2 g(ip); // calls #4 } — end example]
[Example 4: template<class T, class U> struct A { }; template<class T, class U> void f(U, A<U, T>* p = 0); // #1 template< class U> void f(U, A<U, U>* p = 0); // #2 template<class T > void g(T, T = T()); // #3 template<class T, class... U> void g(T, U ...); // #4 void h() { f<int>(42, (A<int, int>*)0); // calls #2 f<int>(42); // error: ambiguous g(42); // error: ambiguous } — end example]
[Example 5: template<class T, class... U> void f(T, U...); // #1 template<class T > void f(T); // #2 template<class T, class... U> void g(T*, U...); // #3 template<class T > void g(T); // #4 void h(int i) { f(&i); // OK, calls #2 g(&i); // OK, calls #3 } — end example]
— end note]
If deduction against the other template succeeds for both transformed templates, constraints can be considered as follows:
  • If their template-parameter-lists (possibly including template-parameters invented for an abbreviated function template ([dcl.fct])) or function parameter lists differ in length, neither template is more specialized than the other.
  • Otherwise:
    • If exactly one of the templates was considered by overload resolution via a rewritten candidate with reversed order of parameters:
      • If, for either template, some of the template parameters are not deducible from their function parameters, neither template is more specialized than the other.
      • If there is either no reordering or more than one reordering of the associated template-parameter-list such that neither template is more specialized than the other.
    • Otherwise, if the corresponding template-parameters of the template-parameter-lists are not equivalent ([temp.over.link]) or if the function parameters that positionally correspond between the two templates are not of the same type, neither template is more specialized than the other.
  • Otherwise, if the context in which the partial ordering is done is that of a call to a conversion function and the return types of the templates are not the same, then neither template is more specialized than the other.
  • Otherwise, if one template is more constrained than the other ([temp.constr.order]), the more constrained template is more specialized than the other.
  • Otherwise, neither template is more specialized than the other.
[Example 6: template <typename> constexpr bool True = true; template <typename T> concept C = True<T>; void f(C auto &, auto &) = delete; template <C Q> 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 } template <typename T, typename U> struct X {}; template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete; template <C T, C U, C V> bool operator==(T, X<U, V>); void h() { X<void *, int>{} == 0; // OK, correspondence of [T, U, V] and [U, V, T] } — end example]

13.7.8 Alias templates [temp.alias]

An alias template is a name for a family of types.
The name of the alias template is a template-name.
When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the defining-type-id of the alias template.
[Note 1: 
An alias template name is never deduced.
— end note]
[Example 1: template<class T> struct Alloc { /* ... */ }; template<class T> using Vec = vector<T, Alloc<T>>; Vec<int> v; // same as vector<int, Alloc<int>> v; template<class T> void process(Vec<T>& v) { /* ... */ } template<class T> void process(vector<T, Alloc<T>>& w) { /* ... */ } // error: redefinition template<template<class> class TT> void f(TT<int>); f(v); // error: Vec not deduced template<template<class,class> class TT> void g(TT<int, Alloc<int>>); g(v); // OK, TT = vector — end example]
However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id.
[Example 2: template<typename...> using void_t = void; template<typename T> void_t<typename T::foo> f(); f<int>(); // error: int does not have a nested type foo — end example]
The defining-type-id in an alias template declaration shall not refer to the alias template being declared.
The type produced by an alias template specialization shall not directly or indirectly make use of that specialization.
[Example 3: template <class T> struct A; template <class T> using B = typename A<T>::U; template <class T> struct A { typedef B<T> U; }; B<short> b; // error: instantiation of B<short> uses own type via A<short>​::​U — end example]
The type of a lambda-expression appearing in an alias template declaration is different between instantiations of that template, even when the lambda-expression is not dependent.
[Example 4: template <class T> using A = decltype([] { }); // A<int> and A<char> refer to different closure types — end example]

13.7.9 Concept definitions [temp.concept]

A concept is a template that defines constraints on its template arguments.
A concept-definition declares a concept.
Its identifier becomes a concept-name referring to that concept within its scope.
The optional attribute-specifier-seq appertains to the concept.
[Example 1: template<typename T> concept C = requires(T x) { { x == x } -> std::convertible_to<bool>; }; template<typename T> requires C<T> // C constrains f1(T) in constraint-expression T f1(T x) { return x; } template<C T> // C, as a type-constraint, constrains f2(T) T f2(T x) { return x; } — end example]
A concept-definition shall inhabit a namespace scope ([basic.scope.namespace]).
A concept shall not have associated constraints.
A concept is not instantiated ([temp.spec]).
[Note 1: 
A concept-id ([temp.names]) is evaluated as an expression.
A concept cannot be explicitly instantiated ([temp.explicit]), explicitly specialized ([temp.expl.spec]), or partially specialized ([temp.spec.partial]).
— end note]
The constraint-expression of a concept-definition is an unevaluated operand ([expr.context]).
The first declared template parameter of a concept definition is its prototype parameter.
A type concept is a concept whose prototype parameter is a type template-parameter.

13.8 Name resolution [temp.res]

13.8.1 General [temp.res.general]

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 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 [temp.dep]), it is looked up for each specialization (after substitution) because the lookup depends on a template parameter.
[Note 1: 
Some dependent names are also looked up during parsing to determine that they are dependent or to interpret following < tokens.
Uses of other names might be type-dependent or value-dependent ([temp.dep.expr], [temp.dep.constexpr]).
A using-declarator is never dependent in a specialization and is therefore replaced during lookup for that specialization ([basic.lookup]).
— end note]
[Example 1: struct A { operator int(); }; template<class B, class T> struct D : B { T get() { return operator T(); } // conversion-function-id is dependent }; int f(D<A, int> d) { return d.get(); } // OK, lookup finds A​::​operator int — end example]
[Example 2: void f(char); template<class T> void g(T t) { f(1); // f(char) f(T(1)); // dependent f(t); // dependent dd++; // not dependent; error: declaration for dd not found } enum E { e }; void f(E); double dd; void h() { g(e); // will cause one call of f(char) followed by two calls of f(E) g('a'); // will cause three calls of f(char) } — end example]
[Example 3: struct A { struct B { /* ... */ }; int a; int Y; }; int a; template<class T> struct Y : T { struct B { /* ... */ }; B b; // The B defined in Y void f(int i) { a = i; } // ​::​a Y* p; // Y<T> }; Y<A> ya;
The members A​::​B, A​::​a, and A​::​Y of the template argument A do not affect the binding of names in Y<A>.
— end example]
If the validity or meaning of the program would be changed by considering a default argument or default template argument introduced in a declaration that is reachable from the point of instantiation of a specialization ([temp.point]) but is not found by lookup for the specialization, the program is ill-formed, no diagnostic required.
The component names of a typename-specifier are its identifier (if any) and those of its nested-name-specifier and simple-template-id (if any).
A typename-specifier denotes the type or class template denoted by the simple-type-specifier ([dcl.type.simple]) formed by omitting the keyword typename.
[Note 2: 
The usual qualified name lookup ([basic.lookup.qual]) applies even in the presence of typename.
— end note]
[Example 4: struct A { struct X { }; int X; }; struct B { struct X { }; }; template<class T> void f(T t) { typename T::X x; } void foo() { A a; B b; f(b); // OK, T​::​X refers to B​::​X f(a); // error: T​::​X refers to the data member A​::​X not the struct A​::​X } — end example]
A qualified or unqualified name is said to be in a type-only context if it is the terminal name of
[Example 5: template<class T> T::R f(); // OK, return type of a function declaration at global scope template<class T> void f(T::R); // ill-formed, no diagnostic required: attempt to declare // a void variable template template<class T> struct S { using Ptr = PtrTraits<T>::Ptr; // OK, in a defining-type-id T::R f(T::P p) { // OK, class scope return static_cast<T::R>(p); // OK, type-id of a static_cast } auto g() -> S<T*>::Ptr; // OK, trailing-return-type }; template<typename T> void f() { void (*pf)(T::X); // variable pf of type void* initialized with T​::​X void g(T::X); // error: T​::​X at block scope does not denote a type // (attempt to declare a void variable) } — end example]
A qualified-id whose terminal name is dependent and that is in a type-only context is considered to denote a type.
A name that refers to a using-declarator whose terminal name is dependent is interpreted as a typedef-name if the using-declarator uses the keyword typename.
[Example 6: template <class T> void f(int i) { T::x * i; // expression, not the declaration of a variable i } struct Foo { typedef int x; }; struct Bar { static int const x = 5; }; int main() { f<Bar>(1); // OK f<Foo>(1); // error: Foo​::​x is a type } — end example]
The validity of a templated entity may be checked prior to any instantiation.
[Note 3: 
Knowing which names are type names allows the syntax of every template to be checked in this way.
— end note]
The program is ill-formed, no diagnostic required, if
  • no valid specialization, ignoring static_assert-declarations that fail ([dcl.pre]), can be generated for a templated entity or a substatement of a constexpr if statement ([stmt.if]) within a templated entity and the innermost enclosing template is not instantiated, or
  • no valid specialization, ignoring static_assert-declarations that fail, can be generated for a default template-argument and the default template-argument is not used in any instantiation, or
  • no specialization of an alias template ([temp.alias]) is valid and no specialization of the alias template is named in the program, or
  • any constraint-expression in the program, introduced or otherwise, has (in its normal form) an atomic constraint A where no satisfaction check of A could be well-formed and no satisfaction check of A is performed, or
  • every valid specialization of a variadic template requires an empty template parameter pack, or
  • a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct (other than a static_assert-declaration that fails) that does not depend on a template parameter, or
  • the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the templated entity.
[Note 4: 
This can happen in situations including the following:
  • a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or
  • lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declaration was a pack expansion and the corresponding pack is empty, or
  • an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or
  • constant expression evaluation within the template instantiation uses
    • the value of a const object of integral or unscoped enumeration type or
    • the value of a constexpr object or
    • the value of a reference or
    • the definition of a constexpr function,
    and that entity was not defined when the template was defined, or
  • a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id is used by the template, and either it is instantiated from a partial specialization that was not defined when the template was defined or it names an explicit specialization that was not declared when the template was defined.
— end note]
[Note 5: 
If a template is instantiated, errors will be diagnosed according to the other rules in this document.
Exactly when these errors are diagnosed is a quality of implementation issue.
— end note]
[Example 7: int j; template<class T> class X { void f(T t, int i, char* p) { t = i; // diagnosed if X​::​f is instantiated, and the assignment to t is an error p = i; // may be diagnosed even if X​::​f is not instantiated p = j; // may be diagnosed even if X​::​f is not instantiated X<T>::g(t); // OK X<T>::h(); // may be diagnosed even if X​::​f is not instantiated } void g(T t) { +; // may be diagnosed even if X​::​g is not instantiated } }; template<class... T> struct A { void operator++(int, T... t); // error: too many parameters }; template<class... T> union X : T... { }; // error: union with base class template<class... T> struct A : T..., T... { }; // error: duplicate base class — end example]
[Note 6: 
For purposes of name lookup, default arguments and noexcept-specifiers of function templates and default arguments and noexcept-specifiers of member functions of class templates are considered definitions ([temp.decls]).
— end note]
117)117)
This includes friend function declarations.

13.8.2 Locally declared names [temp.local]

Like normal (non-template) classes, class templates have an injected-class-name ([class.pre]).
The injected-class-name can be used as a template-name or a type-name.
When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it is a template-name that refers to the class template itself.
Otherwise, it is a type-name equivalent to the template-name followed by the template argument list ([temp.decls.general], [temp.arg.general]) of the class template enclosed in <>.
When the injected-class-name of a class template specialization or partial specialization is used as a type-name, it is equivalent to the template-name followed by the template-arguments of the class template specialization or partial specialization enclosed in <>.
[Example 1: template<template<class> class T> class A { }; template<class T> class Y; template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<​::​Y> class B { template<class> friend class Y; // meaning ​::​Y }; }; — end example]
The injected-class-name of a class template or class template specialization can be used as either a template-name or a type-name wherever it is named.
[Example 2: template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived​::​Base<T> }; template<class T, template<class> class U = T::Base> struct Third { }; Third<Derived<int> > t; // OK, default argument uses injected-class-name as a template — end example]
A lookup that finds an injected-class-name ([class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class).
If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous.
[Example 3: template <class T> struct Base { }; template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; // error: ambiguous typename Derived::Base<double> d; // OK }; — end example]
When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used, it always refers to the class template itself and not a specialization of the template.
[Example 4: template<class T> class X { X* p; // meaning X<T> X<T>* p2; X<int>* p3; ::X* p4; // error: missing template argument list // ​::​X does not refer to the injected-class-name }; — end example]
The name of a template-parameter shall not be bound to any following declaration whose locus is contained by the scope to which the template-parameter belongs.
[Example 5: template<class T, int i> class Y { int T; // error: template-parameter hidden void f() { char T; // error: template-parameter hidden } friend void T(); // OK, no name bound }; template<class X> class X; // error: hidden by template-parameter — end example]
Unqualified name lookup considers the template parameter scope of a template-declaration immediately after the outermost scope associated with the template declared (even if its parent scope does not contain the template-parameter-list).
[Note 1: 
The scope of a class template, including its non-dependent base classes ([temp.dep.type], [class.member.lookup]), is searched before its template parameter scope.
— end note]
[Example 6: struct B { }; namespace N { typedef void V; template<class T> struct A : B { typedef void C; void f(); template<class U> void g(U); }; } template<class V> void N::A<V>::f() { // N​::​V not considered here V v; // V is still the template parameter, not N​::​V } template<class B> template<class C> void N::A<B>::g(C) { B b; // B is the base class, not the template parameter C c; // C is the template parameter, not A's C } — end example]

13.8.3 Dependent names [temp.dep]

13.8.3.1 General [temp.dep.general]

Inside a template, some constructs have semantics which may differ from one instantiation to another.
Such a construct depends on the template parameters.
In particular, types and expressions may depend on the type and/or value of template parameters (as determined by the template arguments) and this determines the context for name lookup for certain names.
An expression may be type-dependent (that is, its type may depend on a template parameter) or value-dependent (that is, its value when evaluated as a constant expression ([expr.const]) may depend on a template parameter) as described below.
A dependent call is an expression, possibly formed as a non-member candidate for an operator ([over.match.oper]), of the form: where the postfix-expression is an unqualified-id and
The component name of an unqualified-id ([expr.prim.id.unqual]) is dependent if
[Note 1: 
Such names are looked up only at the point of the template instantiation ([temp.point]) in both the context of the template definition and the context of the point of instantiation ([temp.dep.candidate]).
— end note]
[Example 1: template<class T> struct X : B<T> { typename T::A* pa; void f(B<T>* pb) { static int i = B<T>::i; pb->j++; } };
The base class name B<T>, the type name T​::​A, the names B<T>​::​i and pb->j explicitly depend on the template-parameter.
— end example]

13.8.3.2 Dependent types [temp.dep.type]

A name or template-id refers to the current instantiation if it is
  • in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class,
  • in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of its template-head ([temp.arg]) enclosed in <> (or an equivalent template alias specialization),
  • in the definition of a nested class of a class template, the name of the nested class referenced as a member of the current instantiation,
  • in the definition of a class template partial specialization or a member of a class template partial specialization, the name of the class template followed by a template argument list equivalent to that of the partial specialization ([temp.spec.partial]) enclosed in <> (or an equivalent template alias specialization), or
  • in the definition of a templated function, the name of a local class ([class.local]).
A template argument that is equivalent to a template parameter can be used in place of that template parameter in a reference to the current instantiation.
For a template type-parameter, a template argument is equivalent to a template parameter if it denotes the same type.
For a non-type template parameter, a template argument is equivalent to a template parameter if it is an identifier that names a variable that is equivalent to the template parameter.
A variable is equivalent to a template parameter if
  • it has the same type as the template parameter (ignoring cv-qualification) and
  • its initializer consists of a single identifier that names the template parameter or, recursively, such a variable.
[Note 1: 
Using a parenthesized variable name breaks the equivalence.
— end note]
[Example 1: template <class T> class A { A* p1; // A is the current instantiation A<T>* p2; // A<T> is the current instantiation A<T*> p3; // A<T*> is not the current instantiation ::A<T>* p4; // ​::​A<T> is the current instantiation class B { B* p1; // B is the current instantiation A<T>::B* p2; // A<T>​::​B is the current instantiation typename A<T*>::B* p3; // A<T*>​::​B is not the current instantiation }; }; template <class T> class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A<T>* p2; // A<T> is not the current instantiation }; template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; // refers to the current instantiation B<T2, T1, I>* b2; // not the current instantiation typedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; static const long my_I4 = I; static const int my_I5 = (I); B<my_T1, T2, my_I>* b3; // refers to the current instantiation B<my_T1, T2, my_I2>* b4; // not the current instantiation B<my_T1, T2, my_I3>* b5; // refers to the current instantiation B<my_T1, T2, my_I4>* b6; // not the current instantiation B<my_T1, T2, my_I5>* b7; // not the current instantiation }; — end example]
A dependent base class is a base class that is a dependent type and is not the current instantiation.
[Note 2: 
A base class can be the current instantiation in the case of a nested class naming an enclosing class as a base.
[Example 2: template<class T> struct A { typedef int M; struct B { typedef void M; struct C; }; }; template<class T> struct A<T>::B::C : A<T> { M m; // OK, A<T>​::​M }; — end example]
— end note]
A qualified ([basic.lookup.qual]) or unqualified name is a member of the current instantiation if
  • its lookup context, if it is a qualified name, is the current instantiation, and
  • lookup for it finds any member of a class that is the current instantiation
[Example 3: template <class T> class A { static const int i = 5; int n1[i]; // i refers to a member of the current instantiation int n2[A::i]; // A​::​i refers to a member of the current instantiation int n3[A<T>::i]; // A<T>​::​i refers to a member of the current instantiation int f(); }; template <class T> int A<T>::f() { return i; // i refers to a member of the current instantiation } — end example]
A qualified or unqualified name names a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member declaration (including a using-declarator whose terminal name is dependent) of a class that is the current instantiation.
A qualified name ([basic.lookup.qual]) is dependent if
[Example 4: struct A { using B = int; A f(); }; struct C : A {}; template<class T> void g(T t) { decltype(t.A::f())::B i; // error: typename needed to interpret B as a type } template void g(C); // …even though A is ​::​A here — end example]
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with a qualified name, the name is looked up in the template instantiation context.
If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous.
[Example 5: struct A { int m; }; struct B { int m; }; template<typename T> struct C : A, T { int f() { return this->m; } // finds A​::​m in the template definition context int g() { return m; } // finds A​::​m in the template definition context }; template int C<B>::f(); // error: finds both A​::​m and B​::​m template int C<B>::g(); // OK, transformation to class member access syntax // does not occur in the template definition context; see [expr.prim.id.general] — end example]
An initializer is dependent if any constituent expression ([intro.execution]) of the initializer is type-dependent.
A placeholder type ([dcl.spec.auto.general]) is dependent if it designates a type deduced from a dependent initializer.
A placeholder for a deduced class type ([dcl.type.class.deduct]) is dependent if
[Example 6: template<class T, class V> struct S { S(T); }; template<class U> struct A { template<class T> using X = S<T, U>; template<class T> using Y = S<T, int>; void f() { new X(1); // dependent new Y(1); // not dependent } }; — end example]
A type is dependent if it is
  • a template parameter,
  • denoted by a dependent (qualified) name,
  • a nested class or enumeration that is a direct member of a class that is the current instantiation,
  • a cv-qualified type where the cv-unqualified type is dependent,
  • a compound type constructed from any dependent type,
  • an array type whose element type is dependent or whose bound (if any) is value-dependent,
  • a function type whose parameters include one or more function parameter packs,
  • a function type whose exception specification is value-dependent,
  • denoted by a dependent placeholder type,
  • denoted by a dependent placeholder for a deduced class type,
  • denoted by a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion,119
  • a pack-index-specifier, or
  • denoted by decltype(expression), where expression is type-dependent.
[Note 3: 
Because typedefs do not introduce new types, but instead simply refer to other types, a name that refers to a typedef that is a member of the current instantiation is dependent only if the type referred to is dependent.
— end note]
118)118)
Every instantiation of a class template declares a different set of assignment operators.
119)119)
This includes an injected-class-name ([class.pre]) of a class template used without a template-argument-list.

13.8.3.3 Type-dependent expressions [temp.dep.expr]

Except as described below, an expression is type-dependent if any subexpression is type-dependent.
this is type-dependent if the current class ([expr.prim.this]) is dependent ([temp.dep.type]).
An id-expression is type-dependent if it is a template-id that is not a concept-id and is dependent; or if its terminal name is
  • associated by name lookup with one or more declarations declared with a dependent type,
  • associated by name lookup with a non-type template-parameter declared with a type that contains a placeholder type ([dcl.spec.auto]),
  • associated by name lookup with a variable declared with a type that contains a placeholder type ([dcl.spec.auto]) where the initializer is type-dependent,
  • associated by name lookup with one or more declarations of member functions of a class that is the current instantiation declared with a return type that contains a placeholder type,
  • associated by name lookup with a structured binding declaration ([dcl.struct.bind]) whose brace-or-equal-initializer is type-dependent,
  • associated by name lookup with a pack,
    [Example 1: struct C { }; void g(...); // #1 template <typename T> void f() { C arr[1]; auto [...e] = arr; g(e...); // calls #2 } void g(C); // #2 int main() { f<int>(); } — end example]
  • associated by name lookup with an entity captured by copy ([expr.prim.lambda.capture]) in a lambda-expression that has an explicit object parameter whose type is dependent ([dcl.fct]),
  • the identifier __func__ ([dcl.fct.def.general]), where any enclosing function is a template, a member of a class template, or a generic lambda,
  • a conversion-function-id that specifies a dependent type, or
  • dependent
or if it names a dependent member of the current instantiation that is a static data member of type “array of unknown bound of T” for some T ([temp.static]).
Expressions of the following forms are type-dependent only if the type specified by the type-id, simple-type-specifier, typename-specifier, or new-type-id is dependent, even if any subexpression is type-dependent:
Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
literal
sizeof unary-expression
sizeof ( type-id )
sizeof ... ( identifier )
alignof ( type-id )
typeid ( expression )
typeid ( type-id )
:: delete cast-expression
:: delete [ ] cast-expression
throw assignment-expression
noexcept ( expression )
requires-expression
[Note 1: 
For the standard library macro offsetof, see [support.types].
— end note]
A class member access expression is type-dependent if the terminal name of its id-expression, if any, is dependent or the expression refers to a member of the current instantiation and the type of the referenced member is dependent.
[Note 2: 
In an expression of the form x.y or xp->y the type of the expression is usually the type of the member y of the class of x (or the class pointed to by xp).
However, if x or xp refers to a dependent type that is not the current instantiation, the type of y is always dependent.
— end note]
A braced-init-list is type-dependent if any element is type-dependent or is a pack expansion.
A fold-expression is type-dependent.
A pack-index-expression is type-dependent if its id-expression is type-dependent.

13.8.3.4 Value-dependent expressions [temp.dep.constexpr]

Except as described below, an expression used in a context where a constant expression is required is value-dependent if any subexpression is value-dependent.
An id-expression is value-dependent if
  • it is a concept-id and any of its arguments are dependent,
  • it is type-dependent,
  • it is the name of a non-type template parameter,
  • it names a static data member that is a dependent member of the current instantiation and is not initialized in a member-declarator,
  • it names a static member function that is a dependent member of the current instantiation, or
  • it names a potentially-constant variable ([expr.const]) that is initialized with an expression that is value-dependent.
Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:
sizeof unary-expression
sizeof ( type-id )
typeid ( expression )
typeid ( type-id )
alignof ( type-id )
[Note 1: 
For the standard library macro offsetof, see [support.types].
— end note]
Expressions of the following form are value-dependent if either the type-id, simple-type-specifier, or typename-specifier is dependent or the expression or cast-expression is value-dependent or any expression in the expression-list is value-dependent or any assignment-expression in the braced-init-list is value-dependent:
Expressions of the following form are value-dependent:
sizeof ... ( identifier )
fold-expression
unless the identifier is a structured binding pack whose initializer is not dependent.
A noexcept-expression ([expr.unary.noexcept]) is value-dependent if its expression involves a template parameter.
An expression of the form &qualified-id where the qualified-id names a dependent member of the current instantiation is value-dependent.
An expression of the form &cast-expression is also value-dependent if evaluating cast-expression as a core constant expression succeeds and the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function.

13.8.3.5 Dependent template arguments [temp.dep.temp]

A type template-argument is dependent if the type it specifies is dependent.
A non-type template-argument is dependent if its type is dependent or the constant expression it specifies is value-dependent.
Furthermore, a non-type template-argument is dependent if the corresponding non-type template-parameter is of reference or pointer type and the template-argument designates or points to a member of the current instantiation or a member of a dependent type.
A template template-parameter is dependent if it names a template-parameter or its terminal name is dependent.

13.8.4 Dependent name resolution [temp.dep.res]

13.8.4.1 Point of instantiation [temp.point]

For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization.
Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.
For a noexcept-specifier of a function template specialization or specialization of a member function of a class template, if the noexcept-specifier is implicitly instantiated because it is needed by another template specialization and the context that requires it depends on a template parameter, the point of instantiation of the noexcept-specifier is the point of instantiation of the specialization that requires it.
Otherwise, the point of instantiation for such a noexcept-specifier immediately follows the namespace scope declaration or definition that requires the noexcept-specifier.
For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
If a virtual function is implicitly instantiated, its point of instantiation is immediately following the point of instantiation of its enclosing class template specialization.
An explicit instantiation definition is an instantiation point for the specialization or specializations specified by the explicit instantiation.
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,
A specialization for a class template has at most one point of instantiation within a translation unit.
A specialization for any template may have points of instantiation in multiple translation units.
If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

13.8.4.2 Candidate functions [temp.dep.candidate]

If a dependent call ([temp.dep]) would be ill-formed or would find a better match had the lookup for its dependent name considered all the function declarations with external linkage introduced in the associated namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts ([basic.lookup.argdep]), then the program is ill-formed, no diagnostic required.
[Example 1: 

Source file "X.h":namespace Q { struct X { }; }

Source file "G.h":namespace Q { void g_impl(X, X); }

Module interface unit of M1:module; #include "X.h" #include "G.h" export module M1; export template<typename T> void g(T t) { g_impl(t, Q::X{ }); // ADL in definition context finds Q​::​g_impl, g_impl not discarded }

Module interface unit of M2:module; #include "X.h" export module M2; import M1; void h(Q::X x) { g(x); // OK } — end example]

[Example 2: 

Module interface unit of Std:export module Std; export template<typename Iter> void indirect_swap(Iter lhs, Iter rhs) { swap(*lhs, *rhs); // swap not found by unqualified lookup, can be found only via ADL }

Module interface unit of M:export module M; import Std; struct S { /* ...*/ }; void swap(S&, S&); // #1 void f(S* p, S* q) { indirect_swap(p, q); // finds #1 via ADL in instantiation context } — end example]

[Example 3: 

Source file "X.h":struct X { /* ... */ }; X operator+(X, X);

Module interface unit of F:export module F; export template<typename T> void f(T t) { t + t; }

Module interface unit of M:module; #include "X.h" export module M; import F; void g(X x) { f(x); // OK, instantiates f from F, // operator+ is visible in instantiation context } — end example]

[Example 4: 

Module interface unit of A:export module A; export template<typename T> void f(T t) { cat(t, t); // #1 dog(t, t); // #2 }

Module interface unit of B:export module B; import A; export template<typename T, typename U> void g(T t, U u) { f(t); }

Source file "foo.h", not an importable header:struct foo { friend int cat(foo, foo); }; int dog(foo, foo);

Module interface unit of C1:module; #include "foo.h" // dog not referenced, discarded export module C1; import B; export template<typename T> void h(T t) { g(foo{ }, t); }

Translation unit:import C1; void i() { h(0); // error: dog not found at #2 }

Importable header "bar.h":struct bar { friend int cat(bar, bar); }; int dog(bar, bar);

Module interface unit of C2:module; #include "bar.h" // imports header unit "bar.h" export module C2; import B; export template<typename T> void j(T t) { g(bar{ }, t); }

Translation unit:import C2; void k() { j(0); // OK, dog found in instantiation context: // visible at end of module interface unit of C2 } — end example]

13.9 Template instantiation and specialization [temp.spec]

13.9.1 General [temp.spec.general]

The act of instantiating a function, a variable, a class, a member of a class template, or a member template is referred to as template instantiation.
A function instantiated from a function template is called an instantiated function.
A class instantiated from a class template is called an instantiated class.
A member function, a member class, a member enumeration, or a static data member of a class template instantiated from the member definition of the class template is called, respectively, an instantiated member function, member class, member enumeration, or static data member.
A member function instantiated from a member function template is called an instantiated member function.
A member class instantiated from a member class template is called an instantiated member class.
A variable instantiated from a variable template is called an instantiated variable.
A static data member instantiated from a static data member template is called an instantiated static data member.
An explicit specialization may be declared for a function template, a variable template, a class template, a member of a class template, or a member template.
An explicit specialization declaration is introduced by template<>.
In an explicit specialization declaration for a variable template, a class template, a member of a class template, or a class member template, the variable or class that is explicitly specialized shall be specified with a simple-template-id.
In the explicit specialization declaration for a function template or a member function template, the function or member function explicitly specialized may be specified using a template-id.
[Example 1: template<class T = int> struct A { static int x; }; template<class U> void g(U) { } template<> struct A<double> { }; // specialize for T == double template<> struct A<> { }; // specialize for T == int template<> void g(char) { } // specialize for U == char // U is deduced from the parameter type template<> void g<int>(int) { } // specialize for U == int template<> int A<char>::x = 0; // specialize for T == char template<class T = int> struct B { static int x; }; template<> int B<>::x = 1; // specialize for T == int — end example]
An instantiated template specialization can be either implicitly instantiated ([temp.inst]) for a given argument list or be explicitly instantiated ([temp.explicit]).
A specialization is a class, variable, function, or class member that is either instantiated ([temp.inst]) from a templated entity or is an explicit specialization ([temp.expl.spec]) of a templated entity.
For a given template and a given set of template-arguments,
  • an explicit instantiation definition shall appear at most once in a program,
  • an explicit specialization shall be defined at most once in a program, as specified in [basic.def.odr], and
  • both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit specialization is reachable from the explicit instantiation.
An implementation is not required to diagnose a violation of this rule if neither declaration is reachable from the other.
The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer.
[Note 1: 
In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) can be private types or objects that would normally not be accessible.
— end note]
Each class template specialization instantiated from a template has its own copy of any static members.
[Example 2: template<class T> class X { static T s; }; template<class T> T X<T>::s = 0; X<int> aa; X<char*> bb;
X<int> has a static member s of type int and X<char*> has a static member s of type char*.
— end example]
If a function declaration acquired its function type through a dependent type without using the syntactic form of a function declarator, the program is ill-formed.
[Example 3: template<class T> struct A { static T t; }; typedef int function(); A<function> a; // error: would declare A<function>​::​t as a static member function — end example]

13.9.2 Implicit instantiation [temp.inst]

A template specialization E is a declared specialization if there is a reachable explicit instantiation definition ([temp.explicit]) or explicit specialization declaration ([temp.expl.spec]) for E, or if there is a reachable explicit instantiation declaration for E and E is not
[Note 1: 
An implicit instantiation in an importing translation unit cannot use names with internal linkage from an imported translation unit ([basic.link]).
— end note]
Unless a class template specialization is a declared specialization, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
[Note 2: 
In particular, if the semantics of an expression depend on the member or base class lists of a class template specialization, the class template specialization is implicitly generated.
For instance, deleting a pointer to class type depends on whether or not the class declares a destructor, and a conversion between pointers to class type depends on the inheritance relationship between the two classes involved.
— end note]
[Example 1: template<class T> class B { /* ... */ }; template<class T> class D : public B<T> { /* ... */ }; void f(void*); void f(B<int>*); void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); // instantiation of D<int> required: call f(B<int>*) B<char>* q = pp; // instantiation of D<char> required: convert D<char>* to B<char>* delete ppp; // instantiation of D<double> required } — end example]
If the template selected for the specialization ([temp.spec.partial.match]) has been declared, but not defined, at the point of instantiation ([temp.point]), the instantiation yields an incomplete class type ([basic.types.general]).
[Example 2: template<class T> class X; X<char> ch; // error: incomplete type X<char> — end example]
[Note 3: 
Within a template declaration, a local class or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments, noexcept-specifiers, and non-static data member initializers, if any, but not their type-constraints or requires-clauses).
As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared.
— end note]
The implicit instantiation of a class template specialization causes
  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
  • the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.
The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions.
[Example 3: template<class T> struct C { void f() { T x; } void g() = delete; }; C<void> c; // OK, definition of C<void>​::​f is not instantiated at this point template<> void C<int>::g() { } // error: redefinition of C<int>​::​g — end example]
However, for the purpose of determining whether an instantiated redeclaration is valid according to [basic.def.odr] and [class.mem], an instantiated declaration that corresponds to a definition in the template is considered to be a definition.
[Example 4: template<class T, class U> struct Outer { template<class X, class Y> struct Inner; template<class Y> struct Inner<T, Y>; // #1a template<class Y> struct Inner<T, Y> { }; // #1b; OK, valid redeclaration of #1a template<class Y> struct Inner<U, Y> { }; // #2 }; Outer<int, int> outer; // error at #2
Outer<int, int>​::​Inner<int, Y> is redeclared at #1b.
(It is not defined but noted as being associated with a definition in Outer<T, U>.)
#2 is also a redeclaration of #1a.
It is noted as associated with a definition, so it is an invalid redeclaration of the same partial specialization.
template<typename T> struct Friendly { template<typename U> friend int f(U) { return sizeof(T); } }; Friendly<char> fc; Friendly<float> ff; // error: produces second definition of f(U) — end example]
Unless a member of a templated class is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
Unless a function template specialization is a declared specialization, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
A function whose declaration was instantiated from a friend function definition is implicitly instantiated when it is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.
[Note 4: 
An inline function that is the subject of an explicit instantiation declaration is not a declared specialization; the intent is that it still be implicitly instantiated when odr-used ([basic.def.odr]) so that the body can be considered for inlining, but that no out-of-line copy of it be generated in the translation unit.
— end note]
[Example 5: template<class T> struct Z { void f(); void g(); }; void h() { Z<int> a; // instantiation of class Z<int> required Z<char>* p; // instantiation of class Z<char> not required Z<double>* q; // instantiation of class Z<double> not required a.f(); // instantiation of Z<int>​::​f() required p->g(); // instantiation of class Z<char> required, and // instantiation of Z<char>​::​g() required }
Nothing in this example requires class Z<double>, Z<int>​::​g(), or Z<char>​::​f() to be implicitly instantiated.
— end example]
Unless a variable template specialization is a declared specialization, the variable template specialization is implicitly instantiated when it is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program.
A default template argument for a variable template is implicitly instantiated when the variable template is referenced in a context that requires the value of the default argument.
The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function is needed for constant evaluation by an expression ([expr.const]), even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition.
[Example 6: template<typename T> constexpr int f() { return T::value; } template<bool B, typename T> void g(decltype(B ? f<T>() : 0)); template<bool B, typename T> void g(...); template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0})); template<bool B, typename T> void h(...); void x() { g<false, int>(0); // OK, B ? f<T>() : 0 is not potentially constant evaluated h<false, int>(0); // error, instantiates f<int> even though B evaluates to false and // list-initialization of int from int cannot be narrowing } — end example]
If the function selected by overload resolution can be determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
[Example 7: template <class T> struct S { operator int(); }; void f(int); void f(S<int>&); void f(S<float>); void g(S<int>& sr) { f(sr); // instantiation of S<int> allowed but not required // instantiation of S<float> allowed but not required }; — end example]
If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated ([temp.over]).
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
[Note 5: 
The instantiation of a generic lambda does not require instantiation of substatements of a constexpr if statement within its compound-statement unless the call operator template is instantiated.
— end note]
It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.
The use of a template specialization in a default argument or default member initializer shall not cause the template to be implicitly instantiated except where needed to determine the correctness of the default argument or default member initializer.
The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
Similarly, the use of a default member initializer in a constructor definition or an aggregate initialization causes specializations in the default member initializer to be instantiated.
If a templated function f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point, except that the scope in which a closure type is declared ([expr.prim.lambda.closure]) — and therefore its associated namespaces — remain as determined from the context of the definition for the default argument.
This analysis is called default argument instantiation.
The instantiated default argument is then used as the argument of f.
Each default argument is instantiated independently.
[Example 8: template<class T> void f(T x, T y = ydef(T()), T z = zdef(T())); class A { }; A zdef(A); void g(A a, A b, A c) { f(a, b, c); // no default argument instantiation f(a, b); // default argument z = zdef(T()) instantiated f(a); // error: ydef is not declared } — end example]
The noexcept-specifier of a function template specialization is not instantiated along with the function declaration; it is instantiated when needed ([except.spec]).
If such a noexcept-specifier is needed but has not yet been instantiated, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the noexcept-specifier is done as if it were being done as part of instantiating the declaration of the specialization at that point.
[Note 6: 
[temp.point] defines the point of instantiation of a template specialization.
— end note]
There is an implementation-defined quantity that specifies the limit on the total depth of recursive instantiations ([implimits]), which could involve more than one template.
The result of an infinite recursion in instantiation is undefined.
[Example 9: template<class T> class X { X<T>* p; // OK X<T*> a; // implicit generation of X<T> requires // the implicit instantiation of X<T*> which requires // the implicit instantiation of X<T**> which … }; — end example]
The type-constraints and requires-clause of a template specialization or member function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in [temp.constr.decl] and [temp.constr.atomic] when determining whether the constraints are satisfied or as specified in [temp.constr.decl] when comparing declarations.
[Note 7: 
The satisfaction of constraints is determined during template argument deduction ([temp.deduct]) and overload resolution ([over.match]).
— end note]
[Example 10: template<typename T> concept C = sizeof(T) > 2; template<typename T> concept D = C<T> && sizeof(T) > 4; template<typename T> struct S { S() requires C<T> { } // #1 S() requires D<T> { } // #2 }; S<char> s1; // error: no matching constructor S<char[8]> s2; // OK, calls #2
When S<char> is instantiated, both constructors are part of the specialization.
Their constraints are not satisfied, and they suppress the implicit declaration of a default constructor for S<char> ([class.default.ctor]), so there is no viable constructor for s1.
— end example]
[Example 11: template<typename T> struct S1 { template<typename U> requires false struct Inner1; // ill-formed, no diagnostic required }; template<typename T> struct S2 { template<typename U> requires (sizeof(T[-(int)sizeof(T)]) > 1) struct Inner2; // ill-formed, no diagnostic required };
The class S1<T>​::​Inner1 is ill-formed, no diagnostic required, because it has no valid specializations.
S2 is ill-formed, no diagnostic required, since no substitution into the constraints of its Inner2 template would result in a valid expression.
— end example]

13.9.3 Explicit instantiation [temp.explicit]

A class, function, variable, or member template specialization can be explicitly instantiated from its template.
A member function, member class or static data member of a class template can be explicitly instantiated from the member definition associated with its class template.
The syntax for explicit instantiation is:
There are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration.
An explicit instantiation declaration begins with the extern keyword.
An explicit instantiation shall not use a storage-class-specifier ([dcl.stc]) other than thread_local.
An explicit instantiation of a function template, member function of a class template, or variable template shall not use the inline, constexpr, or consteval specifiers.
No attribute-specifier-seq ([dcl.attr.grammar]) shall appertain to an explicit instantiation.
If the explicit instantiation is for a class or member class, the elaborated-type-specifier in the declaration shall include a simple-template-id; otherwise, the declaration shall be a simple-declaration whose init-declarator-list comprises a single init-declarator that does not have an initializer.
If the explicit instantiation is for a variable template specialization, the unqualified-id in the declarator shall be a simple-template-id.
[Example 1: template<class T> class Array { void mf(); }; template class Array<char>; template void Array<int>::mf(); template<class T> void sort(Array<T>& v) { /* ... */ } template void sort(Array<char>&); // argument is deduced here ([temp.arg.explicit]) namespace N { template<class T> void f(T&) { } } template void N::f<int>(int&); — end example]
An explicit instantiation does not introduce a name ([basic.scope.scope]).
A declaration of a function template, a variable template, a member function or static data member of a class template, or a member function template of a class or class template shall be reachable from any explicit instantiation of that entity.
A definition of a class template, a member class of a class template, or a member class template of a class or class template shall be reachable from any explicit instantiation of that entity unless an explicit specialization of the entity with the same template arguments is reachable therefrom.
If the declaration of the explicit instantiation names an implicitly-declared special member function ([special]), the program is ill-formed.
The declaration in an explicit-instantiation and the declaration produced by the corresponding substitution into the templated function, variable, or class are two declarations of the same entity.
[Note 1: 
These declarations need to have matching types as specified in [basic.link], except as specified in [except.spec].
[Example 2: template<typename T> T var = {}; template float var<float>; // OK, instantiated variable has type float template int var<int[16]>[]; // OK, absence of major array bound is permitted template int *var<int>; // error: instantiated variable has type int template<typename T> auto av = T(); template int av<int>; // OK, variable with type int can be redeclared with type auto template<typename T> auto f() {} template void f<int>(); // error: function with deduced return type // redeclared with non-deduced return type ([dcl.spec.auto]) — end example]
— end note]
Despite its syntactic form, the declaration in an explicit-instantiation for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable.
For a given set of template arguments, if an explicit instantiation of a template appears after a declaration of an explicit specialization for that template, the explicit instantiation has no effect.
Otherwise, for an explicit instantiation definition, the definition of a function template, a variable template, a member function template, or a member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
[Note 2: 
An explicit instantiation of a constrained template needs to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit instantiation in which all template arguments are specified ([temp.names]), or, for explicit instantiations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— end note]
An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each of its direct non-template members that has not been previously explicitly specialized in 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 ([temp.constr.decl], [temp.constr.constr]), except as described below.
[Note 3: 
In addition, it will typically be an explicit instantiation of certain implementation-dependent data about the class.
— end note]
An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.
An explicit instantiation of a prospective destructor ([class.dtor]) shall correspond to the selected destructor of the class.
If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration.
An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required.
[Note 4: 
This rule does apply to inline functions even though an explicit instantiation declaration of such an entity has no other normative effect.
This is needed to ensure that if the address of an inline function is taken in a translation unit in which the implementation chose to suppress the out-of-line body, another translation unit will supply the body.
— end note]
An explicit instantiation declaration shall not name a specialization of a template with internal linkage.
An explicit instantiation does not constitute a use of a default argument, so default argument instantiation is not done.
[Example 3: char* p = 0; template<class T> T g(T x = &p) { return x; } template int g<int>(int); // OK even though &p isn't an int. — end example]

13.9.4 Explicit specialization [temp.expl.spec]

An explicit specialization of any of the following:
  • function template
  • class template
  • variable template
  • member function of a class template
  • static data member of a class template
  • member class of a class template
  • member enumeration of a class template
  • member class template of a class or class template
  • member function template of a class or class template
can be declared by a declaration introduced by template<>; that is:
[Example 1: template<class T> class stream; template<> class stream<char> { /* ... */ }; // #1 template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } template<> void sort<int>(Array<int>&); // #2 template<> void sort(Array<char*>&); // #3 template argument is deduced ([temp.arg.explicit])
Given these declarations, #1 will be used as the definition of streams of chars; other streams will be handled by class template specializations instantiated from the class template.
Similarly, #2 will be used as the sort function for arguments of type Array<int> and #3 will be used for arguments of type Array<char*>; other Array types will be sorted by functions generated from the function template.
— end example]
An explicit specialization shall not use a storage-class-specifier ([dcl.stc]) other than thread_local.
An explicit specialization may be declared in any scope in which the corresponding primary template may be defined ([dcl.meaning], [class.mem], [temp.mem]).
An explicit specialization does not introduce a name ([basic.scope.scope]).
A declaration of a function template, class template, or variable template being explicitly specialized shall be reachable from the declaration of the explicit specialization.
[Note 1: 
A declaration, but not a definition of the template is needed.
— end note]
The definition of a class or class template shall be reachable from the declaration of an explicit specialization for a member template of the class or class template.
[Example 2: template<> class X<int> { /* ... */ }; // error: X not a template template<class T> class X; template<> class X<char*> { /* ... */ }; // OK, X is a template — end example]
A member function, a member function template, a member class, a member enumeration, a member class template, a static data member, or a static data member template of a class template may be explicitly specialized for a class specialization that is implicitly instantiated; in this case, the definition of the class template shall be reachable from the explicit specialization for the member of the class template.
If such an explicit specialization for the member of a class template names an implicitly-declared special member function ([special]), the program is ill-formed.
A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required.
The definition of the class template explicit specialization shall be reachable from the definition of any member of it.
The definition of an explicitly specialized class is unrelated to the definition of a generated specialization.
That is, its members need not have the same names, types, etc. as the members of a generated specialization.
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
The same is true when defining a member of an explicitly specialized member class.
However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.
[Example 3: template<class T> struct A { struct B { }; template<class U> struct C { }; }; template<> struct A<int> { void f(int); }; void h() { A<int> a; a.f(16); // A<int>​::​f must be defined somewhere } // template<> not used for a member of an explicitly specialized class template void A<int>::f(int) { /* ... */ } template<> struct A<char>::B { void f(); }; // template<> also not used when defining a member of an explicitly specialized member class void A<char>::B::f() { /* ... */ } template<> template<class U> struct A<char>::C { void f(); }; // template<> is used when defining a member of an explicitly specialized member class template // specialized as a class template template<> template<class U> void A<char>::C<U>::f() { /* ... */ } template<> struct A<short>::B { void f(); }; template<> void A<short>::B::f() { /* ... */ } // error: template<> not permitted template<> template<class U> struct A<short>::C { void f(); }; template<class U> void A<short>::C<U>::f() { /* ... */ } // error: template<> required — end example]
If a template, a member template or a member of a class template is explicitly specialized, a declaration of that specialization shall be reachable from every use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required.
An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
[Example 4: class String { }; template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } void f(Array<String>& v) { sort(v); // use primary template sort(Array<T>&), T is String } template<> void sort<String>(Array<String>& v); // error: specialization after use of primary template template<> void sort<>(Array<char*>& v); // OK, sort<char*> not yet used template<class T> struct A { enum E : T; enum class S : T; }; template<> enum A<int>::E : int { eint }; // OK template<> enum class A<int>::S : int { sint }; // OK template<class T> enum A<T>::E : T { eT }; template<class T> enum class A<T>::S : T { sT }; template<> enum A<char>::E : char { echar }; // error: A<char>​::​E was instantiated // when A<char> was instantiated template<> enum class A<char>::S : char { schar }; // OK — end example]
The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below.
When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
A simple-template-id that names a class template explicit specialization that has been declared but not defined can be used exactly like the names of other incompletely-defined classes ([basic.types]).
[Example 5: template<class T> class X; // X is a class template template<> class X<int>; X<int>* p; // OK, pointer to declared class X<int> X<int> x; // error: object of incomplete class X<int> — end example]
[Note 2: 
An explicit specialization of a constrained template needs to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit specialization in which all template arguments are specified ([temp.names]), or, for explicit specializations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— end note]
A function with the same name as a template and a type that exactly matches that of a template specialization is not an explicit specialization ([temp.fct]).
Whether an explicit specialization of a function or variable template is inline, constexpr, constinit, or consteval is determined by the explicit specialization and is independent of those properties of the template.
Similarly, attributes appearing in the declaration of a template have no effect on an explicit specialization of that template.
[Example 6: template<class T> void f(T) { /* ... */ } template<class T> inline T g(T) { /* ... */ } template<> inline void f<>(int) { /* ... */ } // OK, inline template<> int g<>(int) { /* ... */ } // OK, not inline template<typename> [[noreturn]] void h([[maybe_unused]] int i); template<> void h<int>(int i) { // Implementations are expected not to warn that the function returns // but can warn about the unused parameter. } — end example]
An explicit specialization of a static data member of a template or an explicit specialization of a static data member template is a definition if the declaration includes an initializer; otherwise, it is a declaration.
[Note 3: 
The definition of a static data member of a template for which default-initialization is desired can use functional cast notation ([expr.type.conv]): template<> X Q<int>::x; // declaration template<> X Q<int>::x (); // error: declares a function template<> X Q<int>::x = X(); // definition
— end note]
A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition.
An explicit specialization of a member or member template is specified using the syntax for explicit specialization.
[Example 7: template<class T> struct A { void f(T); template<class X1> void g1(T, X1); template<class X2> void g2(T, X2); void h(T) { } }; // specialization template<> void A<int>::f(int); // out of class member template definition template<class T> template<class X1> void A<T>::g1(T, X1) { } // member template specialization template<> template<class X1> void A<int>::g1(int, X1); // member template specialization template<> template<> void A<int>::g1(int, char); // X1 deduced as char template<> template<> void A<int>::g2<char>(int, char); // X2 specified as char // member specialization even if defined in class definition template<> void A<int>::h(int) { } — end example]
A member or a member template may be nested within many enclosing class templates.
In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized.
[Example 8: template<class T1> class A { template<class T2> class B { void mf(); }; }; template<> template<> class A<int>::B<double>; template<> template<> void A<char>::B<char>::mf(); — end example]
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
In such an explicit specialization declaration, the keyword template followed by a template-parameter-list shall be provided instead of the template<> preceding the explicit specialization declaration of the member.
The types of the template-parameters in the template-parameter-list shall be the same as those specified in the primary template definition.
[Example 9: template <class T1> class A { template<class T2> class B { template<class T3> void mf1(T3); void mf2(); }; }; template <> template <class X> class A<int>::B { template <class T> void mf1(T); }; template <> template <> template<class T> void A<int>::B<double>::mf1(T t) { } template <class Y> template <> void A<Y>::B<double>::mf2() { } // error: B<double> is specialized but // its enclosing class template A is not — end example]
A specialization of a member function template, member class template, or static data member template of a non-specialized class template is itself a template.
An explicit specialization declaration shall not be a friend declaration.
Default function arguments shall not be specified in a declaration or a definition for one of the following explicit specializations:
  • the explicit specialization of a function template;
  • the explicit specialization of a member function template;
  • the explicit specialization of a member function of a class template where the class template specialization to which the member function specialization belongs is implicitly instantiated.
    [Note 4: 
    Default function arguments can be specified in the declaration or definition of a member function of a class template specialization that is explicitly specialized.
    — end note]

13.10 Function template specializations [temp.fct.spec]

13.10.1 General [temp.fct.spec.general]

A function instantiated from a function template is called a function template specialization; so is an explicit specialization of a function template.
Template arguments can be explicitly specified when naming the function template specialization, deduced from the context (e.g., deduced from the function arguments in a call to the function template specialization, see [temp.deduct]), or obtained from default template arguments.
Each function template specialization instantiated from a template has its own copy of any static variable.
[Example 1: template<class T> void f(T* p) { static T s; }; void g(int a, char* b) { f(&a); // calls f<int>(int*) f(&b); // calls f<char*>(char**) }
Here f<int>(int*) has a static variable s of type int and f<char*>(char**) has a static variable s of type char*.
— end example]

13.10.2 Explicit template argument specification [temp.arg.explicit]

Template arguments can be specified when referring to a function template specialization that is not a specialization of a constructor template by qualifying the function template name with the list of template-arguments in the same way as template-arguments are specified in uses of a class template specialization.
[Example 1: 
template<class T> void sort(Array<T>& v); void f(Array<dcomplex>& cv, Array<int>& ci) { sort<dcomplex>(cv); // sort(Array<dcomplex>&) sort<int>(ci); // sort(Array<int>&) } and template<class U, class V> U convert(V v); void g(double d) { int i = convert<int,double>(d); // int convert(double) char c = convert<char,double>(d); // char convert(double) }
— end example]
Template arguments shall not be specified when referring to a specialization of a constructor template ([class.ctor], [class.qual]).
A template argument list may be specified when referring to a specialization of a function template
  • when a function is called,
  • when the address of a function is taken, when a function initializes a reference to function, or when a pointer to member function is formed,
  • in an explicit specialization,
  • in an explicit instantiation, or
  • in a friend declaration.
Trailing template arguments that can be deduced ([temp.deduct]) or obtained from default template-arguments may be omitted from the list of explicit template-arguments.
[Note 1: 
A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments.
— end note]
If all of the template arguments can be deduced or obtained from default template-arguments, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.
[Example 2: template<class X, class Y> X f(Y); template<class X, class Y, class ... Z> X g(Y); void h() { int i = f<int>(5.6); // Y deduced as double int j = f(5.6); // error: X cannot be deduced f<void>(f<int, bool>); // Y for outer f deduced as int (*)(bool) f<void>(f<int>); // error: f<int> does not denote a single function template specialization int k = g<int>(5.6); // Y deduced as double; Z deduced as an empty sequence f<void>(g<int, bool>); // Y for outer f deduced as int (*)(bool), // Z deduced as an empty sequence } — end example]
[Note 2: 
An empty template argument list can be used to indicate that a given use refers to a specialization of a function template even when a non-template function ([dcl.fct]) is visible that would otherwise be used.
For example: template <class T> int f(T); // #1 int f(int); // #2 int k = f(1); // uses #2 int l = f<>(1); // uses #1
— end note]
Template arguments that are present shall be specified in the declaration order of their corresponding template-parameters.
The template argument list shall not specify more template-arguments than there are corresponding template-parameters unless one of the template-parameters is a template parameter pack.
[Example 3: template<class X, class Y, class Z> X f(Y,Z); template<class ... Args> void f2(); void g() { f<int,const char*,double>("aa",3.0); f<int,const char*>("aa",3.0); // Z deduced as double f<int>("aa",3.0); // Y deduced as const char*; Z deduced as double f("aa",3.0); // error: X cannot be deduced f2<char, short, int, long>(); // OK } — end example]
Implicit conversions ([conv]) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction.
[Note 3: 
Template parameters do not participate in template argument deduction if they are explicitly specified.
For example,
template<class T> void f(T); class Complex { Complex(double); }; void g() { f<Complex>(1); // OK, means f<Complex>(Complex(1)) } — end note]
[Note 4: 
Because the explicit template argument list follows the function template name, and because constructor templates ([class.ctor]) are named without using a function name ([class.qual]), there is no way to provide an explicit template argument list for these function templates.
— end note]
Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments.
[Example 4: template<class ... Types> void f(Types ... values); void g() { f<int*, float*>(0, 0, 0); // Types deduced as the sequence int*, float*, int } — end example]

13.10.3 Template argument deduction [temp.deduct]

13.10.3.1 General [temp.deduct.general]

When a function template specialization is referenced, all of the template arguments shall have values.
The values can be explicitly specified or, in some cases, be deduced from the use or obtained from default template-arguments.
[Example 1: 
void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); // calls sort(Array<dcomplex>&) sort(ci); // calls sort(Array<int>&) } and void g(double d) { int i = convert<int>(d); // calls convert<int,double>(double) int c = convert<char>(d); // calls convert<char,double>(double) }
— end example]
When an explicit template argument list is specified, if the given template-id is not valid ([temp.names]), type deduction fails.
Otherwise, the specified template argument values are substituted for the corresponding template parameters as specified below.
After this substitution is performed, the function parameter type adjustments described in [dcl.fct] are performed.
[Example 2: 
A parameter type of “void (const int, int[5])” becomes “void(*)(int,int*).
— end example]
[Note 1: 
A top-level qualifier in a function parameter declaration does not affect the function type but still affects the type of the function parameter variable within the function.
— end note]
[Example 3: template <class T> void f(T t); template <class X> void g(const X x); template <class Z> void h(Z, Z*); int main() { // #1: function type is f(int), t is non const f<int>(1); // #2: function type is f(int), t is const f<const int>(1); // #3: function type is g(int), x is const g<int>(1); // #4: function type is g(int), x is const g<const int>(1); // #5: function type is h(int, const int*) h<const int>(1,0); } — end example]
[Note 2: 
f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type.
— end note]
The resulting substituted and adjusted function type is used as the type of the function template for template argument deduction.
If a template argument has not been deduced and its corresponding template parameter has a default argument, the template argument is determined by substituting the template arguments determined for preceding template parameters into the default argument.
If the substitution results in an invalid type, as described above, type deduction fails.
[Example 4: template <class T, class U = double> void f(T t = 0, U u = 0); void g() { f(1, 'c'); // f<int,char>(1,'c') f(1); // f<int,double>(1,0) f(); // error: T cannot be deduced f<int>(); // f<int,double>(0,0) f<int,char>(); // f<int,char>(0,0) } — end example]
When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template are replaced with the corresponding deduced or default argument values.
If the substitution results in an invalid type, as described above, type deduction fails.
If the function template has associated constraints ([temp.constr.decl]), those constraints are checked for satisfaction ([temp.constr.constr]).
If the constraints are not satisfied, type deduction fails.
In the context of a function call, if type deduction has not yet failed, then for those function parameters for which the function call has arguments, each function parameter with a type that was non-dependent before substitution of any explicitly-specified template arguments is checked against its corresponding argument; if the corresponding argument cannot be implicitly converted to the parameter type, type deduction fails.
[Note 3: 
Overload resolution will check the other parameters, including parameters with dependent types in which no template parameters participate in template argument deduction and parameters that became non-dependent due to substitution of explicitly-specified template arguments.
— end note]
If type deduction has not yet failed, then all uses of template parameters in the function type are replaced with the corresponding deduced or default argument values.
If the substitution results in an invalid type, as described above, type deduction fails.
[Example 5: template <class T> struct Z { typedef typename T::x xx; }; template <class T> concept C = requires { typename T::A; }; template <C T> typename Z<T>::xx f(void *, T); // #1 template <class T> void f(int, T); // #2 struct A {} a; struct ZZ { template <class T, class = typename Z<T>::xx> operator T *(); operator int(); }; int main() { ZZ zz; f(1, a); // OK, deduction fails for #1 because there is no conversion from int to void* f(zz, 42); // OK, deduction fails for #1 because C<int> is not satisfied } — end example]
At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments.
This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
The deduction substitution loci are
The substitution occurs in all types and expressions that are used in the deduction substitution loci.
The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions.
The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered.
If substitution into different declarations of the same function template would cause template instantiations to occur in a different order or not at all, the program is ill-formed; no diagnostic required.
[Note 4: 
The equivalent substitution in exception specifications is done only when the noexcept-specifier is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression.
— end note]
[Example 6: template <class T> struct A { using X = typename T::X; }; template <class T> typename T::X f(typename A<T>::X); template <class T> void f(...) { } template <class T> auto g(typename A<T>::X) -> typename T::X; template <class T> void g(...) { } template <class T> typename T::X h(typename A<T>::X); template <class T> auto h(typename A<T>::X) -> typename T::X; // redeclaration template <class T> void h(...) { } void x() { f<int>(0); // OK, substituting return type causes deduction to fail g<int>(0); // error, substituting parameter type instantiates A<int> h<int>(0); // ill-formed, no diagnostic required } — end example]
If a substitution results in an invalid type or expression, type deduction fails.
An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written in the same context using the substituted arguments.
[Note 5: 
If no diagnostic is required, the program is still ill-formed.
Access checking is done as part of the substitution process.
— end note]
Invalid types and expressions can result in a deduction failure only in the immediate context of the deduction substitution loci.
[Note 6: 
The substitution into types and expressions can result in effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc.
Such effects are not in the “immediate context” and can result in the program being ill-formed.
— end note]
When substituting into a lambda-expression, substitution into its body is not in the immediate context.
[Note 7: 
The intent is to avoid requiring implementations to deal with substitution failure involving arbitrary statements.
[Example 7: template <class T> auto f(T) -> decltype([]() { T::invalid; } ()); void f(...); f(0); // error: invalid expression not part of the immediate context template <class T, std::size_t = sizeof([]() { T::invalid; })> void g(T); void g(...); g(0); // error: invalid expression not part of the immediate context template <class T> auto h(T) -> decltype([x = T::invalid]() { }); void h(...); h(0); // error: invalid expression not part of the immediate context template <class T> auto i(T) -> decltype([]() -> typename T::invalid { }); void i(...); i(0); // error: invalid expression not part of the immediate context template <class T> auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1 void j(...); // #2 j(0); // deduction fails on #1, calls #2 — end example]
— end note]
[Example 8: struct X { }; struct Y { Y(X) {} }; template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1 X f(Y, Y); // #2 X x1, x2; X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2 — end example]
[Note 8: 
Type deduction can fail for the following reasons:
  • Attempting to instantiate a pack expansion containing multiple packs of differing lengths.
  • Attempting to create an array with an element type that is void, a function type, or a reference type, or attempting to create an array with a size that is zero or negative.
    [Example 9: template <class T> int f(T[5]); int I = f<int>(0); int j = f<void>(0); // invalid array — end example]
  • Attempting to use a type that is not a class or enumeration type in a qualified name.
    [Example 10: template <class T> int f(typename T::B*); int i = f<int>(0); — end example]
  • Attempting to use a type in a nested-name-specifier of a qualified-id when that type does not contain the specified member, or
    • the specified member is not a type where a type is required, or
    • the specified member is not a template where a template is required, or
    • the specified member is not a non-type where a non-type is required.
    [Example 11: template <int I> struct X { }; template <template <class T> class> struct Z { }; template <class T> void f(typename T::Y*) {} template <class T> void g(X<T::N>*) {} template <class T> void h(Z<T::TT>*) {} struct A {}; struct B { int Y; }; struct C { typedef int N; }; struct D { typedef int TT; }; int main() { // Deduction fails in each of these cases: f<A>(0); // A does not contain a member Y f<B>(0); // The Y member of B is not a type g<C>(0); // The N member of C is not a non-type h<D>(0); // The TT member of D is not a template } — end example]
  • Attempting to create a pointer to reference type.
  • Attempting to create a reference to void.
  • Attempting to create “pointer to member of T” when T is not a class type.
    [Example 12: template <class T> int f(int T::*); int i = f<int>(0); — end example]
  • Attempting to give an invalid type to a non-type template parameter.
    [Example 13: template <class T, T> struct S {}; template <class T> int f(S<T, T{}>*); // #1 class X { int m; }; int i0 = f<X>(0); // #1 uses a value of non-structural type X as a non-type template argument — end example]
  • Attempting to perform an invalid conversion in either a template argument expression, or an expression used in the function declaration.
    [Example 14: template <class T, T*> int f(int); int i2 = f<int,1>(0); // can't convert 1 to int* — end example]
  • Attempting to create a function type in which a parameter has a type of void, or in which the return type is a function type or array type.
  • Attempting to give to an explicit object parameter of a lambda's function call operator a type not permitted for such ([expr.prim.lambda.closure]).
— end note]
[Example 15: 
In the following example, assuming a signed char cannot represent the value 1000, a narrowing conversion would be required to convert the template-argument of type int to signed char, therefore substitution fails for the second template ([temp.arg.nontype]).
template <int> int f(int); template <signed char> int f(int); int i1 = f<1000>(0); // OK int i2 = f<1>(0); // ambiguous; not narrowing — end example]

13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]

Template argument deduction is done by comparing each function template parameter type (call it P) that contains template-parameters that participate in template argument deduction with the type of the corresponding argument of the call (call it A) as described below.
If removing references and cv-qualifiers from P gives or for some and N and the argument is a non-empty initializer list ([dcl.init.list]), then deduction is performed instead for each element of the initializer list independently, taking as separate function template parameter types and the initializer element as the corresponding argument.
In the case, if N is a non-type template parameter, N is deduced from the length of the initializer list.
Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context ([temp.deduct.type]).
[Example 1: template<class T> void f(std::initializer_list<T>); f({1,2,3}); // T deduced as int f({1,"asdf"}); // error: T deduced as both int and const char* template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T template<class T, int N> void h(T const(&)[N]); h({1,2,3}); // T deduced as int; N deduced as 3 template<class T> void j(T const(&)[3]); j({42}); // T deduced as int; array bound not considered struct Aggr { int i; int j; }; template<int N> void k(Aggr const(&)[N]); k({1,2,3}); // error: deduction fails, no conversion from int to Aggr k({{1},{2},{3}}); // OK, N deduced as 3 template<int M, int N> void m(int const(&)[M][N]); m({{1,2},{3,4}}); // M and N both deduced as 2 template<class T, int N> void n(T const(&)[N], T); n({{1},{2},{3}},Aggr()); // OK, T is Aggr, N is 3 template<typename T, int N> void o(T (* const (&)[N])(T)) { } int f1(int); int f4(int); char f4(char); o({ &f1, &f4 }); // OK, T deduced as int from first element, nothing // deduced from second element, N deduced as 2 o({ &f1, static_cast<char(*)(char)>(&f4) }); // error: conflicting deductions for T — end example]
For a function parameter pack that occurs at the end of the parameter-declaration-list, deduction is performed for each remaining argument of the call, taking the type P of the declarator-id of the function parameter pack as the corresponding function template parameter type.
Each deduction deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced.
[Example 2: template<class ... Types> void f(Types& ...); template<class T1, class ... Types> void g(T1, Types ...); template<class T1, class ... Types> void g1(Types ..., T1); void h(int x, float& y) { const int z = x; f(x, y, z); // Types deduced as int, float, const int g(x, y, z); // T1 deduced as int; Types deduced as float, int g1(x, y, z); // error: Types is not deduced g1<int, int, int>(x, y, z); // OK, no deduction occurs } — end example]
If P is not a reference type:
If P is a cv-qualified type, the top-level cv-qualifiers of P's type are ignored for type deduction.
If P is a reference type, the type referred to by P is used for type deduction.
[Example 3: template<class T> int f(const T&); int n1 = f(5); // calls f<int>(const int&) const int i = 0; int n2 = f(i); // calls f<int>(const int&) template <class T> int g(volatile T&); int n3 = g(i); // calls g<const int>(const volatile int&) — end example]
A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])).
If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.
[Example 4: template <class T> int f(T&& heisenreference); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which // would bind an rvalue reference to an lvalue template <class T> struct A { template <class U> A(T&&, U&&, int*); // #1: T&& is not a forwarding reference. // U&& is a forwarding reference. A(T&&, int*); // #2 }; template <class T> A(T&&, int*) -> A<T>; // #3: T&& is a forwarding reference. int *ip; A a{i, 0, ip}; // error: cannot deduce from #1 A a0{0, 0, ip}; // uses #1 to deduce A<int> and #1 to initialize A a2{i, ip}; // uses #3 to deduce A<int&> and #2 to initialize — end example]
In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above).
However, there are three cases that allow a difference:
  • If the original P is a reference type, the deduced A (i.e., the type referred to by the reference) can be more cv-qualified than the transformed A.
  • The transformed A can be another pointer or pointer-to-member type that can be converted to the deduced A via a function pointer conversion and/or qualification conversion.
  • If P is a class and P has the form simple-template-id, then the transformed A can be a derived class D of the deduced A.
    Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class D pointed to by the deduced A.
    However, if there is a class C that is a (direct or indirect) base class of D and derived (directly or indirectly) from a class B and that would be a valid deduced A, the deduced A cannot be B or pointer to B, respectively.
    [Example 5: template <typename... T> struct X; template <> struct X<> {}; template <typename T, typename... Ts> struct X<T, Ts...> : X<Ts...> {}; struct D : X<int> {}; struct E : X<>, X<int> {}; template <typename... T> int f(const X<T...>&); int x = f(D()); // calls f<int>, not f<> // B is X<>, C is X<int> int z = f(E()); // calls f<int>, not f<> — end example]
These alternatives are considered only if type deduction would otherwise fail.
If they yield more than one possible deduced A, the type deduction fails.
[Note 1: 
If a template-parameter is not used in any of the function parameters of a function template, or is used only in a non-deduced context, its corresponding template-argument cannot be deduced from a function call and the template-argument must be explicitly specified.
— end note]
When P is a function type, function pointer type, or pointer-to-member-function type:
  • If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.
  • If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set whose associated constraints ([temp.constr.constr]) are satisfied.
    If all successful deductions yield the same deduced A, that deduced A is the result of deduction; otherwise, the parameter is treated as a non-deduced context.
[Example 6: // Only one function of an overload set matches the call so the function parameter is a deduced context. template <class T> int f(T (*p)(T)); int g(int); int g(char); int i = f(g); // calls f(int (*)(int)) — end example]
[Example 7: // Ambiguous deduction causes the second function parameter to be a non-deduced context. template <class T> int f(T, T (*p)(T)); int g(int); char g(char); int i = f(1, g); // calls f(int, int (*)(int)) — end example]
[Example 8: // The overload set contains a template, causing the second function parameter to be a non-deduced context. template <class T> int f(T, T (*p)(T)); char g(char); template <class T> T g(T); int i = f(1, g); // calls f(int, int (*)(int)) — end example]
[Example 9: // All arguments for placeholder type deduction ([dcl.type.auto.deduct]) yield the same deduced type. template<bool B> struct X { static void f(short) requires B; // #1 static void f(short); // #2 }; void test() { auto x = &X<true>::f; // OK, deduces void(*)(short), selects #1 auto y = &X<false>::f; // OK, deduces void(*)(short), selects #2 } — end example]

13.10.3.3 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]

Template arguments can be deduced from the type specified when taking the address of an overload set.
If there is a target, the function template's function type and the target type are used as the types of P and A, and the deduction is done as described in [temp.deduct.type].
Otherwise, deduction is performed with empty sets of types P and A.
A placeholder type ([dcl.spec.auto]) in the return type of a function template is a non-deduced context.
If template argument deduction succeeds for such a function, the return type is determined from instantiation of the function body.

13.10.3.4 Deducing conversion function template arguments [temp.deduct.conv]

Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type specified by the conversion-type-id of the conversion-function-id being looked up (call it A) as described in [temp.deduct.type].
If the conversion-function-id is constructed during overload resolution ([over.match.funcs]), the rules in the remainder of this subclause apply.
If P is a reference type, the type referred to by P is used in place of P for type deduction and for any further references to or transformations of P in the remainder of this subclause.
If A is not a reference type:
If A is a cv-qualified type, the top-level cv-qualifiers of A's type are ignored for type deduction.
If A is a reference type, the type referred to by A is used for type deduction.
In general, the deduction process attempts to find template argument values that will make the deduced A identical to A.
However, certain attributes of A may be ignored:
  • If the original A is a reference type, any cv-qualifiers of A (i.e., the type referred to by the reference).
  • If the original A is a function pointer or pointer-to-member-function type with a potentially-throwing exception specification ([except.spec]), the exception specification.
  • Any cv-qualifiers in A that can be restored by a qualification conversion.
These attributes are ignored only if type deduction would otherwise fail.
If ignoring them allows more than one possible deduced A, the type deduction fails.

13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]

Template argument deduction is done by comparing certain types associated with the two function templates being compared.
Two sets of types are used to determine the partial ordering.
For each of the templates involved there is the original function type and the transformed function type.
[Note 1: 
The creation of the transformed type is described in [temp.func.order].
— end note]
The deduction process uses the transformed type as the argument template and the original type of the other template as the parameter template.
This process is done twice for each type involved in the partial ordering comparison: once using the transformed template-1 as the argument template and template-2 as the parameter template and again using the transformed template-2 as the argument template and template-1 as the parameter template.
The types used to determine the ordering depend on the context in which the partial ordering is done:
  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.120
  • In the context of a call to a conversion function, the return types of the conversion function templates are used.
  • In other contexts the function template's function type is used.
Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A.
Before the partial ordering is done, certain transformations are performed on the types used for partial ordering:
  • If P is a reference type, P is replaced by the type referred to.
  • If A is a reference type, A is replaced by the type referred to.
If both P and A were reference types (before being replaced with the type referred to above), determine which of the two types (if any) is more cv-qualified than the other; otherwise the types are considered to be equally cv-qualified for partial ordering purposes.
The result of this determination will be used below.
Remove any top-level cv-qualifiers:
  • If P is a cv-qualified type, P is replaced by the cv-unqualified version of P.
  • If A is a cv-qualified type, A is replaced by the cv-unqualified version of A.
Using the resulting types P and A, the deduction is then done as described in [temp.deduct.type].
If P is a function parameter pack, the type A of each remaining parameter type of the argument template is compared with the type P of the declarator-id of the function parameter pack.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
Similarly, if A was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.
If deduction succeeds for a given type, the type from the argument template is considered to be at least as specialized as the type from the parameter template.
[Example 1: template<class... Args> void f(Args... args); // #1 template<class T1, class... Args> void f(T1 a1, Args... args); // #2 template<class T1, class T2> void f(T1 a1, T2 a2); // #3 f(); // calls #1 f(1, 2, 3); // calls #2 f(1, 2); // calls #3; non-variadic template #3 is more specialized // than the variadic templates #1 and #2 — end example]
If, for a given type, the types are identical after the transformations above and both P and A were reference types (before being replaced with the type referred to above):
  • if the type from the argument template was an lvalue reference and the type from the parameter template was not, the parameter type is not considered to be at least as specialized as the argument type; otherwise,
  • if the type from the argument template is more cv-qualified than the type from the parameter template (as described above), the parameter type is not considered to be at least as specialized as the argument type.
Function template F is at least as specialized as function template G if, for each pair of types used to determine the ordering, the type from F is at least as specialized as the type from G.
F is more specialized than G if F is at least as specialized as G and G is not at least as specialized as F.
If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and if G has a trailing function parameter pack for which F does not have a corresponding parameter, and if F does not have a trailing function parameter pack, then F is more specialized than G.
In most cases, deduction fails if not all template parameters have values, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering.
[Note 2: 
A template parameter used in a non-deduced context is considered used.
— end note]
[Example 2: template <class T> T f(int); // #1 template <class T, class U> T f(U); // #2 void g() { f<int>(1); // calls #1 } — end example]
[Note 3: 
Partial ordering of function templates containing template parameter packs is independent of the number of deduced arguments for those template parameter packs.
— end note]
[Example 3: template<class ...> struct Tuple { }; template<class ... Types> void g(Tuple<Types ...>); // #1 template<class T1, class ... Types> void g(Tuple<T1, Types ...>); // #2 template<class T1, class ... Types> void g(Tuple<T1, Types& ...>); // #3 g(Tuple<>()); // calls #1 g(Tuple<int, float>()); // calls #2 g(Tuple<int, float&>()); // calls #3 g(Tuple<int>()); // calls #3 — end example]
120)120)
Default arguments are not considered to be arguments in this context; they only become arguments after a function has been selected.

13.10.3.6 Deducing template arguments from a type [temp.deduct.type]

Template arguments can be deduced in several different contexts, but in each case a type that is specified in terms of template parameters (call it P) is compared with an actual type (call it A), and an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.
In some cases, the deduction is done using a single set of types P and A, in other cases, there will be a set of corresponding types P and A.
Type deduction is done independently for each P/A pair, and the deduced template argument values are then combined.
If type deduction cannot be done for any P/A pair, or if for any pair the deduction leads to more than one possible set of deduced values, or if different pairs yield different deduced values, or if any template argument remains neither deduced nor explicitly specified, template argument deduction fails.
The type of a type parameter is only deduced from an array bound if it is not otherwise deduced.
A given type P can be composed from a number of other types, templates, and non-type values:
  • A function type includes the types of each of the function parameters, the return type, and its exception specification.
  • A pointer-to-member type includes the type of the class object pointed to and the type of the member pointed to.
  • A type that is a specialization of a class template (e.g., A<int>) includes the types, templates, and non-type values referenced by the template argument list of the specialization.
  • An array type includes the array element type and the value of the array bound.
In most cases, the types, templates, and non-type values that are used to compose P participate in template argument deduction.
That is, they may be used to determine the value of a template argument, and template argument deduction fails if the value so determined is not consistent with the values determined elsewhere.
In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified.
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
[Note 1: 
Under [temp.deduct.call], if P contains no template-parameters that appear in deduced contexts, no deduction is done, so P and A need not have the same form.
— end note]
The non-deduced contexts are:
  • The nested-name-specifier of a type that was specified using a qualified-id.
  • A non-type template argument or an array bound in which a subexpression references a template parameter.
  • A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
  • A function parameter for which the associated argument is an overload set such that one or more of the following apply:
    • functions whose associated constraints are satisfied and that do not all have the same function type match the function parameter type (resulting in an ambiguous deduction), or
    • no function whose associated constraints are satisfied matches the function parameter type, or
    • the overload set supplied as an argument contains one or more function templates.
    [Note 2: 
    A particular function from the overload set is selected ([over.over]) after template argument deduction has succeeded ([temp.over]).
    — end note]
  • A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have a type for which deduction from an initializer list is specified ([temp.deduct.call]).
    [Example 1: template<class T> void g(T); g({1,2,3}); // error: no argument deduced for T — end example]
  • A function parameter pack that does not occur at the end of the parameter-declaration-list.
When a type name is specified in a way that includes a non-deduced context, all of the types that comprise that type name are also non-deduced.
However, a compound type can include both deduced and non-deduced types.
[Example 2: 
If a type is specified as A<T>​::​B<T2>, both T and T2 are non-deduced.
Likewise, if a type is specified as A<I+J>​::​X<T>, I, J, and T are non-deduced.
If a type is specified as void f(typename A<T>​::​B, A<T>), the T in A<T>​::​B is non-deduced but the T in A<T> is deduced.
— end example]
[Example 3: 
Here is an example in which different parameter/argument pairs produce inconsistent template argument deductions: template<class T> void f(T x, T y) { /* ... */ } struct A { /* ... */ }; struct B : A { /* ... */ }; void g(A a, B b) { f(a,b); // error: T deduced as both A and B f(b,a); // error: T deduced as both A and B f(a,a); // OK, T is A f(b,b); // OK, T is B }
Here is an example where two template arguments are deduced from a single function parameter/argument pair.
This can lead to conflicts that cause type deduction to fail: template <class T, class U> void f(T (*)(T, U, U)); int g1(int, float, float); char g2(int, float, float); int g3(int, char, float); void r() { f(g1); // OK, T is int and U is float f(g2); // error: T deduced as both char and int f(g3); // error: U deduced as both char and float }
Here is an example where the exception specification of a function type is deduced: template<bool E> void f1(void (*)() noexcept(E)); template<bool> struct A { }; template<bool B> void f2(void (*)(A<B>) noexcept(B)); void g1(); void g2() noexcept; void g3(A<true>); void h() { f1(g1); // OK, E is false f1(g2); // OK, E is true f2(g3); // error: B deduced as both true and false }
Here is an example where a qualification conversion applies between the argument type on the function call and the deduced template argument type: template<class T> void f(const T*) { } int* p; void s() { f(p); // f(const int*) }
Here is an example where the template argument is used to instantiate a derived class type of the corresponding function parameter type: template <class T> struct B { }; template <class T> struct D : public B<T> {}; struct D2 : public B<int> {}; template <class T> void f(B<T>&) {} void t() { D<int> d; D2 d2; f(d); // calls f(B<int>&) f(d2); // calls f(B<int>&) }
— end example]
A template type argument T, a template template argument TT, or a template non-type argument i can be deduced if P and A have one of the following forms: cv T T* T& T&& T[i] T(T) noexcept(i) T T::* TT<T> TT<i> TT<TT> TT<> where
  • T represents a type or parameter-type-list that either satisfies these rules recursively, is a non-deduced context in P or A, or is the same non-dependent type in P and A,
  • TT represents either a class template or a template template parameter,
  • i represents an expression that either is an i, is value-dependent in P or A, or has the same constant value in P and A, and
  • noexcept(i) represents an exception specification ([except.spec]) in which the (possibly-implicit, see [dcl.fct]) noexcept-specifier's operand satisfies the rules for an i above.
[Note 3: 
If a type matches such a form but contains no Ts, is, or TTs, deduction is not possible.
— end note]
Similarly, <T> represents template argument lists where at least one argument contains a T, <i> represents template argument lists where at least one argument contains an i and <> represents template argument lists where no argument contains a T or an i.
If P has a form that contains <T> or <i>, then each argument of the respective template argument list of P is compared with the corresponding argument of the corresponding template argument list of A.
If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context.
If is a pack expansion, then the pattern of is compared with each remaining argument in the template argument list of A.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by .
During partial ordering, if was originally a pack expansion:
  • if P does not contain a template argument corresponding to then is ignored;
  • otherwise, if is not a pack expansion, template argument deduction fails.
[Example 4: template<class T1, class... Z> class S; // #1 template<class T1, class... Z> class S<T1, const Z&...> { }; // #2 template<class T1, class T2> class S<T1, const T2&> { }; // #3 S<int, const int&> s; // both #2 and #3 match; #3 is more specialized template<class T, class... U> struct A { }; // #1 template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; // #2 template<class T1, class T2> struct A<T1, T2> { }; // #3 template struct A<int, int*>; // selects #2 — end example]
Similarly, if P has a form that contains (T), then each parameter type of the respective parameter-type-list ([dcl.fct]) of P is compared with the corresponding parameter type of the corresponding parameter-type-list of A.
If P and A are function types that originated from deduction when taking the address of a function template ([temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and and are parameters of the top-level parameter-type-list of P and A, respectively, is adjusted if it is a forwarding reference ([temp.deduct.call]) and is an lvalue reference, in which case the type of is changed to be the template parameter type (i.e., T&& is changed to simply T).
[Note 4: 
As a result, when is T&& and is X&, the adjusted will be T, causing T to be deduced as X&.
— end note]
[Example 5: template <class T> void f(T&&); template <> void f(int&) { } // #1 template <> void f(int&&) { } // #2 void g(int i) { f(i); // calls f<int&>(int&), i.e., #1 f(0); // calls f<int>(int&&), i.e., #2 } — end example]
If the parameter-declaration corresponding to is a function parameter pack, then the type of its declarator-id is compared with each remaining parameter type in the parameter-type-list of A.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
During partial ordering, if was originally a function parameter pack:
  • if P does not contain a function parameter type corresponding to then is ignored;
  • otherwise, if is not a function parameter pack, template argument deduction fails.
[Example 6: template<class T, class... U> void f(T*, U...) { } // #1 template<class T> void f(T) { } // #2 template void f(int*); // selects #1 — end example]
These forms can be used in the same way as T is for further composition of types.
[Example 7: 
X<int> (*)(char[6]) is of the form template-name<T> (*)(type[i]) which is a variant of type (*)(T) where type is X<int> and T is char[6].
— end example]
Template arguments cannot be deduced from function arguments involving constructs other than the ones specified above.
When the value of the argument corresponding to a non-type template parameter P that is declared with a dependent type is deduced from an expression, the template parameters in the type of P are deduced from the type of the value.
[Example 8: template<long n> struct A { }; template<typename T> struct C; template<typename T, T n> struct C<A<n>> { using Q = T; }; using R = long; using R = C<A<2>>::Q; // OK; T was deduced as long from the // template argument value in the type A<2> — end example]
The type of N in the type T[N] is std​::​size_t.
[Example 9: template<typename T> struct S; template<typename T, T n> struct S<int[n]> { using Q = T; }; using V = decltype(sizeof 0); using V = S<int[42]>::Q; // OK; T was deduced as std​::​size_t from the type int[42] — end example]
The type of B in the noexcept-specifier noexcept(B) of a function type is bool.
[Example 10: template<bool> struct A { }; template<auto> struct B; template<auto X, void (*F)() noexcept(X)> struct B<F> { A<X> ax; }; void f_nothrow() noexcept; B<f_nothrow> bn; // OK, type of X deduced as bool — end example]
[Example 11: template<class T, T i> void f(int (&a)[i]); int v[10]; void g() { f(v); // OK, T is std​::​size_t } — end example]
[Note 5: 
Except for reference and pointer types, a major array bound is not part of a function parameter type and cannot be deduced from an argument: template<int i> void f1(int a[10][i]); template<int i> void f2(int a[i][20]); template<int i> void f3(int (&a)[i][20]); void g() { int v[10][20]; f1(v); // OK, i deduced as 20 f1<20>(v); // OK f2(v); // error: cannot deduce template-argument i f2<10>(v); // OK f3(v); // OK, i deduced as 10 }
— end note]
[Note 6: 
If, in the declaration of a function template with a non-type template parameter, the non-type template parameter is used in a subexpression in the function parameter list, the expression is a non-deduced context as specified above.
[Example 12: template <int i> class A { /* ... */ }; template <int i> void g(A<i+1>); template <int i> void f(A<i>, A<i+1>); void k() { A<1> a1; A<2> a2; g(a1); // error: deduction fails for expression i+1 g<0>(a1); // OK f(a1, a2); // OK } — end example]
— end note]
[Note 7: 
Template parameters do not participate in template argument deduction if they are used only in non-deduced contexts.
For example,
template<int i, typename T> T deduce(typename A<T>::X x, // T is not deduced here T t, // but T is deduced here typename B<i>::Y y); // i is not deduced here A<int> a; B<77> b; int x = deduce<77>(a.xm, 62, b.ym); // T deduced as int; a.xm must be convertible to A<int>​::​X // i is explicitly specified to be 77; b.ym must be convertible to B<77>​::​Y — end note]
If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails.
If P has a form that contains [i], and if the type of i is not an integral type, deduction fails.121
If P has a form that includes noexcept(i) and the type of i is not bool, deduction fails.
[Example 13: template<int i> class A { /* ... */ }; template<short s> void f(A<s>); void k1() { A<1> a; f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK } template<const short cs> class B { }; template<short s> void g(B<s>); void k2() { B<1> b; g(b); // OK, cv-qualifiers are ignored on template parameter types } — end example]
A template-argument can be deduced from a function, pointer to function, or pointer-to-member-function type.
[Example 14: template<class T> void f(void(*)(T,int)); template<class T> void foo(T,int); void g(int,int); void g(char,int); void h(int,int,int); void h(char,int); int m() { f(&g); // error: ambiguous f(&h); // OK, void h(char,int) is a unique match f(&foo); // error: type deduction fails because foo is a template } — end example]
A template type-parameter cannot be deduced from the type of a function default argument.
[Example 15: template <class T> void f(T = 5, T = 7); void g() { f(1); // OK, calls f<int>(1,7) f(); // error: cannot deduce T f<int>(); // OK, calls f<int>(5,7) } — end example]
The template-argument corresponding to a template template-parameter is deduced from the type of the template-argument of a class template specialization used in the argument list of a function call.
[Example 16: template <template <class T> class X> struct A { }; template <template <class T> class X> void f(A<X>) { } template<class T> struct B { }; A<B> ab; f(ab); // calls f(A<B>) — end example]
[Note 8: 
Template argument deduction involving parameter packs ([temp.variadic]) can deduce zero or more arguments for each parameter pack.
— end note]
[Example 17: template<class> struct X { }; template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { }; template<class ... Types> struct Y { }; template<class T, class ... Types> struct Y<T, Types& ...> { }; template<class ... Types> int f(void (*)(Types ...)); void g(int, float); X<int> x1; // uses primary template X<int(int, float, double)> x2; // uses partial specialization; ArgTypes contains float, double X<int(float, int)> x3; // uses primary template Y<> y1; // uses primary template; Types is empty Y<int&, float&, double&> y2; // uses partial specialization; T is int&, Types contains float, double Y<int, float, double> y3; // uses primary template; Types contains int, float, double int fv = f(g); // OK; Types contains int, float — end example]
121)121)
Although the template-argument corresponding to a template-parameter of type bool can be deduced from an array bound, the resulting value will always be true because the array bound will be nonzero.

13.10.3.7 Deducing template arguments from a function declaration [temp.deduct.decl]

In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers.
Specifically, this is done for explicit instantiations, explicit specializations, and certain friend declarations.
This is also done to determine whether a deallocation function template specialization matches a placement operator new ([basic.stc.dynamic.deallocation], [expr.new]).
In all these cases, P is the type of the function template being considered as a potential match and A is either the function type from the declaration or the type of the deallocation function that would match the placement operator new as described in [expr.new].
The deduction is done as described in [temp.deduct.type].
If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered ([temp.func.order]), deduction fails and, in the declaration cases, the program is ill-formed.

13.10.4 Overload resolution [temp.over]

When a call of a function or function template is written (explicitly, or implicitly using the operator notation), template argument deduction ([temp.deduct]) and checking of any explicit template arguments ([temp.arg]) are performed for each function template to find the template argument values (if any) that can be used with that function template to instantiate a function template specialization that can be invoked with the call arguments or, for conversion function templates, that can convert to the required type.
For each function template:
  • If the argument deduction and checking succeeds, the template-arguments (deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution.
  • If the argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the set of candidate functions for that template.
The complete set of candidate functions includes all the synthesized declarations and all of the non-template functions found by name lookup.
The synthesized declarations are treated like any other functions in the remainder of overload resolution, except as explicitly noted in [over.match.best].122
[Example 1: template<class T> T max(T a, T b) { return a>b?a:b; } void f(int a, int b, char c, char d) { int m1 = max(a,b); // max(int a, int b) char m2 = max(c,d); // max(char a, char b) int m3 = max(a,c); // error: cannot generate max(int,char) }
Adding the non-template function int max(int,int); to the example above would resolve the third call, by providing a function that can be called for max(a,c) after using the standard conversion of char to int for c.
— end example]
[Example 2: 
Here is an example involving conversions on a function argument involved in template-argument deduction: template<class T> struct B { /* ... */ }; template<class T> struct D : public B<T> { /* ... */ }; template<class T> void f(B<T>&); void g(B<int>& bi, D<int>& di) { f(bi); // f(bi) f(di); // f((B<int>&)di) }
— end example]
[Example 3: 
Here is an example involving conversions on a function argument not involved in template-parameter deduction: template<class T> void f(T*,int); // #1 template<class T> void f(T,char); // #2 void h(int* pi, int i, char c) { f(pi,i); // #1: f<int>(pi,i) f(pi,c); // #2: f<int*>(pi,c) f(i,c); // #2: f<int>(i,c); f(i,i); // #2: f<int>(i,char(i)) }
— end example]
Only the signature of a function template specialization is needed to enter the specialization in a set of candidate functions.
Therefore only the function template declaration is needed to resolve a call for which a template specialization is a candidate.
[Example 4: template<class T> void f(T); // declaration void g() { f("Annemarie"); // calls f<const char*> }
The call to f is well-formed even if the template f is only declared and not defined at the point of the call.
The program will be ill-formed unless a specialization for f<const char*> is explicitly instantiated in some translation unit ([temp.pre]).
— end example]
122)122)
The parameters of function template specializations contain no template parameter types.
The set of conversions allowed on deduced arguments is limited, because the argument deduction process produces function templates with parameters that either match the call arguments exactly or differ only in ways that can be bridged by the allowed limited conversions.
Non-deduced arguments allow the full range of conversions.
Note also that [over.match.best] specifies that a non-template function will be given preference over a template specialization if the two functions are otherwise equally good candidates for an overload match.

14 Exception handling [except]

14.1 Preamble [except.pre]

Exception handling provides a way of transferring control and information from a point in the execution of a thread to an exception handler associated with a point previously passed by the execution.
A handler will be invoked only by throwing an exception in code executed in the handler's try block or in functions called from the handler's try block.
The optional attribute-specifier-seq in an exception-declaration appertains to the parameter of the catch clause ([except.handle]).
[Note 1: 
Within this Clause “try block” is taken to mean both try-block and function-try-block.
— end note]
The compound-statement of a try block or of a handler is a control-flow-limited statement ([stmt.label]).
[Example 1: void f() { goto l1; // error goto l2; // error try { goto l1; // OK goto l2; // error l1: ; } catch (...) { l2: ; goto l1; // error goto l2; // OK } } — end example]
A goto, break, return, or continue statement can be used to transfer control out of a try block or handler.
When this happens, each variable declared in the try block will be destroyed in the context that directly contains its declaration.
[Example 2: lab: try { T1 t1; try { T2 t2; if (condition) goto lab; } catch(...) { /* handler 2 */ } } catch(...) { /* handler 1 */ }
Here, executing goto lab; will destroy first t2, then t1, assuming the condition does not declare a variable.
Any exception thrown while destroying t2 will result in executing handler 2; any exception thrown while destroying t1 will result in executing handler 1.
— end example]
A function-try-block associates a handler-seq with the ctor-initializer, if present, and the compound-statement.
An exception thrown during the execution of the compound-statement or, for constructors and destructors, during the initialization or destruction, respectively, of the class's subobjects, transfers control to a handler in a function-try-block in the same way as an exception thrown during the execution of a try-block transfers control to other handlers.
[Example 3: int f(int); class C { int i; double d; public: C(int, double); }; C::C(int ii, double id) try : i(f(ii)), d(id) { // constructor statements } catch (...) { // handles exceptions thrown from the ctor-initializer and from the constructor statements } — end example]
In this Clause, “before” and “after” refer to the “sequenced before” relation.

14.2 Throwing an exception [except.throw]

Throwing an exception transfers control to a handler.
[Note 1: 
An exception can be thrown from one of the following contexts: throw-expressions ([expr.throw]), allocation functions ([basic.stc.dynamic.allocation]), dynamic_cast ([expr.dynamic.cast]), typeid ([expr.typeid]), new-expressions ([expr.new]), and standard library functions ([structure.specifications]).
— end note]
An object is passed and the type of that object determines which handlers can catch it.
[Example 1: 
throw "Help!"; can be caught by a handler of const char* type: try { // ... } catch(const char* p) { // handle character string exceptions here } and class Overflow { public: Overflow(char,double,double); }; void f(double x) { throw Overflow('+',x,3.45e107); } can be caught by a handler for exceptions of type Overflow: try { f(1.2); } catch(Overflow& oo) { // handle exceptions of type Overflow here }
— end example]
When an exception is thrown, control is transferred to the nearest handler with a matching type ([except.handle]); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.
Throwing an exception initializes an object with dynamic storage duration, called the exception object.
If the type of the exception object would be an incomplete type ([basic.types.general]), an abstract class type ([class.abstract]), or a pointer to an incomplete type other than cv void ([basic.compound]), the program is ill-formed.
The memory for the exception object is allocated in an unspecified way, except as noted in [basic.stc.dynamic.allocation].
If a handler exits by rethrowing, control is passed to another handler for the same exception object.
The points of potential destruction for the exception object are:
  • when an active handler for the exception exits by any means other than rethrowing, immediately after the destruction of the object (if any) declared in the exception-declaration in the handler;
  • when an object of type std​::​exception_ptr that refers to the exception object is destroyed, before the destructor of std​::​exception_ptr returns.
Among all points of potential destruction for the exception object, there is an unspecified last one where the exception object is destroyed.
All other points happen before that last one.
[Note 2: 
No other thread synchronization is implied in exception handling.
— end note]
The implementation may then deallocate the memory for the exception object; any such deallocation is done in an unspecified way.
[Note 3: 
A thrown exception does not propagate to other threads unless caught, stored, and rethrown using appropriate library functions; see [propagation] and [futures].
— end note]
Let T denote the type of the exception object.
Copy-initialization of an object of type T from an lvalue of type const T in a context unrelated to T shall be well-formed.
If T is a class type, the selected constructor is odr-used ([basic.def.odr]) and the destructor of T is potentially invoked ([class.dtor]).
An exception is considered caught when a handler for that exception becomes active.
[Note 4: 
An exception can have active handlers and still be considered uncaught if it is rethrown.
— end note]
If the exception handling mechanism handling an uncaught exception directly invokes a function that exits via an exception, the function std​::​terminate is invoked.
[Example 2: struct C { C() { } C(const C&) { if (std::uncaught_exceptions()) { throw 0; // throw during copy to handler's exception-declaration object ([except.handle]) } } }; int main() { try { throw C(); // calls std​::​terminate if construction of the handler's // exception-declaration object is not elided ([class.copy.elision]) } catch(C) { } } — end example]
[Note 5: 
If a destructor directly invoked by stack unwinding exits via an exception, std​::​terminate is invoked.
— end note]

14.3 Stack unwinding [except.ctor]

As control passes from the point where an exception is thrown to a handler, objects are destroyed by a process, specified in this subclause, called stack unwinding.
Each object with automatic storage duration is destroyed if it has been constructed, but not yet destroyed, since the try block was entered.
If an exception is thrown during the destruction of temporaries or local variables for a return statement ([stmt.return]), the destructor for the returned object (if any) is also invoked.
The objects are destroyed in the reverse order of the completion of their construction.
[Example 1: struct A { }; struct Y { ~Y() noexcept(false) { throw 0; } }; A f() { try { A a; Y y; A b; return {}; // #1 } catch (...) { } return {}; // #2 }
At #1, the returned object of type A is constructed.
Then, the local variable b is destroyed ([stmt.jump]).
Next, the local variable y is destroyed, causing stack unwinding, resulting in the destruction of the returned object, followed by the destruction of the local variable a.
Finally, the returned object is constructed again at #2.
— end example]
If the initialization of an object other than by delegating constructor is terminated by an exception, the destructor is invoked for each of the object's subobjects that were known to be initialized by the object's initialization and whose initialization has completed ([dcl.init]).
[Note 1: 
If such an object has a reference member that extends the lifetime of a temporary object, this ends the lifetime of the reference member, so the lifetime of the temporary object is effectively not extended.
— end note]
A subobject is known to be initialized if it is not an anonymous union member and its initialization is specified
[Note 2: 
This includes virtual base class subobjects if the initialization is for a complete object, and can include variant members that were nominated explicitly by a mem-initializer or designated-initializer-clause or that have a default member initializer.
— end note]
If the destructor of an object is terminated by an exception, each destructor invocation that would be performed after executing the body of the destructor ([class.dtor]) and that has not yet begun execution is performed.
[Note 3: 
This includes virtual base class subobjects if the destructor was invoked for a complete object.
— end note]
The subobjects are destroyed in the reverse order of the completion of their construction.
Such destruction is sequenced before entering a handler of the function-try-block of the constructor or destructor, if any.
If the compound-statement of the function-body of a delegating constructor for an object exits via an exception, the object's destructor is invoked.
Such destruction is sequenced before entering a handler of the function-try-block of a delegating constructor for that object, if any.
[Note 4: 
If the object was allocated by a new-expression ([expr.new]), the matching deallocation function, if any, is called to free the storage occupied by the object.
— end note]

14.4 Handling an exception [except.handle]

The exception-declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered.
The exception-declaration shall not denote an incomplete type, an abstract class type, or an rvalue reference type.
The exception-declaration shall not denote a pointer or reference to an incomplete type, other than “pointer to cv void.
A handler of type “array of T” or function type T is adjusted to be of type “pointer to T.
A handler is a match for an exception object of type E if
[Note 1: 
A throw-expression whose operand is an integer literal with value zero does not match a handler of pointer or pointer-to-member type.
A handler of reference to array or function type is never a match for any exception object ([expr.throw]).
— end note]
[Example 1: class Matherr { /* ... */ virtual void vf(); }; class Overflow: public Matherr { /* ... */ }; class Underflow: public Matherr { /* ... */ }; class Zerodivide: public Matherr { /* ... */ }; void f() { try { g(); } catch (Overflow oo) { // ... } catch (Matherr mm) { // ... } }
Here, the Overflow handler will catch exceptions of type Overflow and the Matherr handler will catch exceptions of type Matherr and of all types publicly derived from Matherr including exceptions of type Underflow and Zerodivide.
— end example]
The handlers for a try block are tried in order of appearance.
[Note 2: 
This makes it possible to write handlers that can never be executed, for example by placing a handler for a final derived class after a handler for a corresponding unambiguous public base class.
— end note]
A ... in a handler's exception-declaration specifies a match for any exception.
If present, a ... handler shall be the last handler for its try block.
If no match is found among the handlers for a try block, the search for a matching handler continues in a dynamically surrounding try block of the same thread.
If the search for a handler encounters the outermost block of a function with a non-throwing exception specification, the function std​::​terminate ([except.terminate]) is invoked.
[Note 3: 
An implementation is not permitted to reject an expression merely because, when executed, it throws or might throw an exception from a function with a non-throwing exception specification.
— end note]
[Example 2: extern void f(); // potentially-throwing void g() noexcept { f(); // valid, even if f throws throw 42; // valid, effectively a call to std​::​terminate }
The call to f is well-formed despite the possibility for it to throw an exception.
— end example]
If no matching handler is found, the function std​::​terminate is invoked; whether or not the stack is unwound before this invocation of std​::​terminate is implementation-defined ([except.terminate]).
A handler is considered active when initialization is complete for the parameter (if any) of the catch clause.
[Note 4: 
The stack will have been unwound at that point.
— end note]
Also, an implicit handler is considered active when the function std​::​terminate is entered due to a throw.
A handler is no longer considered active when the catch clause exits.
The exception with the most recently activated handler that is still active is called the currently handled exception.
Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior.
Exceptions thrown in destructors of objects with static storage duration or in constructors of objects associated with non-block variables with static storage duration are not caught by a function-try-block on the main function.
Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a function-try-block on the initial function of the thread.
If a return statement ([stmt.return]) appears in a handler of the function-try-block of a constructor, the program is ill-formed.
The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.
Otherwise, flowing off the end of the compound-statement of a handler of a function-try-block is equivalent to flowing off the end of the compound-statement of that function (see [stmt.return]).
The variable declared by the exception-declaration, of type cv T or cv T&, is initialized from the exception object, of type E, as follows:
  • if T is a base class of E, the variable is copy-initialized ([dcl.init]) from an lvalue of type T designating the corresponding base class subobject of the exception object;
  • otherwise, the variable is copy-initialized ([dcl.init]) from an lvalue of type E designating the exception object.
The lifetime of the variable ends when the handler exits, after the destruction of any objects with automatic storage duration initialized within the handler.
When the handler declares an object, any changes to that object will not affect the exception object.
When the handler declares a reference to an object, any changes to the referenced object are changes to the exception object and will have effect should that object be rethrown.

14.5 Exception specifications [except.spec]

The predicate indicating whether a function cannot exit via an exception is called the exception specification of the function.
If the predicate is false, the function has a potentially-throwing exception specification, otherwise it has a non-throwing exception specification.
The exception specification is either defined implicitly, or defined explicitly by using a noexcept-specifier as a suffix of a function declarator.
In a noexcept-specifier, the constant-expression, if supplied, shall be a contextually converted constant expression of type bool ([expr.const]); that constant expression is the exception specification of the function type in which the noexcept-specifier appears.
A ( token that follows noexcept is part of the noexcept-specifier and does not commence an initializer ([dcl.init]).
The noexcept-specifier noexcept without a constant-expression is equivalent to the noexcept-specifier noexcept(true).
[Example 1: void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type bool void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type bool is non-narrowing — end example]
If a declaration of a function does not have a noexcept-specifier, the declaration has a potentially throwing exception specification unless it is a destructor or a deallocation function or is defaulted on its first declaration, in which cases the exception specification is as specified below and no other declaration for that function shall have a noexcept-specifier.
In an explicit instantiation a noexcept-specifier may be specified, but is not required.
If a noexcept-specifier is specified in an explicit instantiation, the exception specification shall be the same as the exception specification of all other declarations of that function.
A diagnostic is required only if the exception specifications are not the same within a single translation unit.
If a virtual function has a non-throwing exception specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall have a non-throwing exception specification, unless the overriding function is defined as deleted.
[Example 2: struct B { virtual void f() noexcept; virtual void g(); virtual void h() noexcept = delete; }; struct D: B { void f(); // error void g() noexcept; // OK void h() = delete; // OK };
The declaration of D​::​f is ill-formed because it has a potentially-throwing exception specification, whereas B​::​f has a non-throwing exception specification.
— end example]
An expression E is potentially-throwing if
An implicitly-declared constructor for a class X, or a constructor without a noexcept-specifier that is defaulted on its first declaration, has a potentially-throwing exception specification if and only if any of the following constructs is potentially-throwing:
  • the invocation of a constructor selected by overload resolution in the implicit definition of the constructor for class X to initialize a potentially constructed subobject, or
  • a subexpression of such an initialization, such as a default argument expression, or,
  • for a default constructor, a default member initializer.
[Note 1: 
Even though destructors for fully-constructed subobjects are invoked when an exception is thrown during the execution of a constructor ([except.ctor]), their exception specifications do not contribute to the exception specification of the constructor, because an exception thrown from such a destructor would call the function std​::​terminate rather than escape the constructor ([except.throw], [except.terminate]).
— end note]
The exception specification for an implicitly-declared destructor, or a destructor without a noexcept-specifier, is potentially-throwing if and only if any of the destructors for any of its potentially constructed subobjects has a potentially-throwing exception specification or the destructor is virtual and the destructor of any virtual base class has a potentially-throwing exception specification.
The exception specification for an implicitly-declared assignment operator, or an assignment-operator without a noexcept-specifier that is defaulted on its first declaration, is potentially-throwing if and only if the invocation of any assignment operator in the implicit definition is potentially-throwing.
A deallocation function with no explicit noexcept-specifier has a non-throwing exception specification.
The exception specification for a comparison operator function ([over.binary]) without a noexcept-specifier that is defaulted on its first declaration is potentially-throwing if and only if any expression in the implicit definition is potentially-throwing.
[Example 3: struct A { A(int = (A(5), 0)) noexcept; A(const A&) noexcept; A(A&&) noexcept; ~A(); }; struct B { B() noexcept; B(const B&) = default; // implicit exception specification is noexcept(true) B(B&&, int = (throw 42, 0)) noexcept; ~B() noexcept(false); }; int n = 7; struct D : public A, public B { int * p = new int[n]; // D​::​D() potentially-throwing, as the new operator may throw bad_alloc or bad_array_new_length // D​::​D(const D&) non-throwing // D​::​D(D&&) potentially-throwing, as the default argument for B's constructor may throw // D​::​~D() potentially-throwing };
Furthermore, if A​::​~A() were virtual, the program would be ill-formed since a function that overrides a virtual function from a base class shall not have a potentially-throwing exception specification if the base class function has a non-throwing exception specification.
— end example]
An exception specification is considered to be needed when:
  • in an expression, the function is selected by overload resolution ([over.match], [over.over]);
  • the function is odr-used ([basic.def.odr]) or, if it appears in an unevaluated operand, would be odr-used if the expression were potentially-evaluated;
  • the exception specification is compared to that of another declaration (e.g., an explicit specialization or an overriding virtual function);
  • the function is defined; or
  • the exception specification is needed for a defaulted function that calls the function.
    [Note 2: 
    A defaulted declaration does not require the exception specification of a base member function to be evaluated until the implicit exception specification of the derived function is needed, but an explicit noexcept-specifier needs the implicit exception specification to compare against.
    — end note]
The exception specification of a defaulted function is evaluated as described above only when needed; similarly, the noexcept-specifier of a specialization of a function template or member function of a class template is instantiated only when needed.

14.6 Special functions [except.special]

14.6.1 General [except.special.general]

The function std​::​terminate ([except.terminate]) is used by the exception handling mechanism for coping with errors related to the exception handling mechanism itself.
The function std​::​current_exception() and the class std​::​nested_exception can be used by a program to capture the currently handled exception.

14.6.2 The std​::​terminate function [except.terminate]

Some errors in a program cannot be recovered from, such as when an exception is not handled or a std​::​thread object is destroyed while its thread function is still executing.
In such cases, the function std​::​terminate ([exception.terminate]) is invoked.
[Note 1: 
These situations are:
— end note]
In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std​::​terminate is invoked.
In the situation where the search for a handler ([except.handle]) encounters the outermost block of a function with a non-throwing exception specification ([except.spec]), it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before the function std​::​terminate is invoked.
In all other situations, the stack shall not be unwound before the function std​::​terminate is invoked.
An implementation is not permitted to finish stack unwinding prematurely based on a determination that the unwind process will eventually cause an invocation of the function std​::​terminate.

14.6.3 The std​::​uncaught_exceptions function [except.uncaught]

An exception is considered uncaught after completing the initialization of the exception object until completing the activation of a handler for the exception ([except.handle]).
[Note 1: 
As a consequence, an exception is considered uncaught during any stack unwinding resulting from it being thrown.
— end note]
If an exception is rethrown ([expr.throw], [propagation]), it is considered uncaught from the point of rethrow until the rethrown exception is caught.
The function std​::​uncaught_exceptions ([uncaught.exceptions]) returns the number of uncaught exceptions in the current thread.

15 Preprocessing directives [cpp]

15.1 Preamble [cpp.pre]

lparen:
a ( character not immediately preceded by whitespace
new-line:
the new-line character
A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: At the start of translation phase 4, the first preprocessing token in the sequence, referred to as a directive-introducing token, begins with the first character in the source file (optionally after whitespace containing no new-line characters) or follows whitespace containing at least one new-line character, and is
  • a # preprocessing token, or
  • an import preprocessing token immediately followed on the same logical source line by a header-name, <, identifier, string-literal, or : preprocessing token, or
  • a module preprocessing token immediately followed on the same logical source line by an identifier, :, or ; preprocessing token, or
  • an export preprocessing token immediately followed on the same logical source line by one of the two preceding forms.
The last preprocessing token in the sequence is the first preprocessing token within the sequence that is immediately followed by whitespace containing a new-line character.123
[Note 1: 
A new-line character ends the preprocessing directive even if it occurs within what would otherwise be an invocation of a function-like macro.
— end note]
[Example 1: # // preprocessing directive module ; // preprocessing directive export module leftpad; // preprocessing directive import <string>; // preprocessing directive export import "squee"; // preprocessing directive import rightpad; // preprocessing directive import :part; // preprocessing directive module // not a preprocessing directive ; // not a preprocessing directive export // not a preprocessing directive import // not a preprocessing directive foo; // not a preprocessing directive export // not a preprocessing directive import foo; // preprocessing directive (ill-formed at phase 7) import :: // not a preprocessing directive import -> // not a preprocessing directive — end example]
A sequence of preprocessing tokens is only a text-line if it does not begin with a directive-introducing token.
[Example 2: using module = int; module i; // not a text-line and not a control-line int foo() { return i; }
The example is not a valid preprocessing-file.
— end example]
A sequence of preprocessing tokens is only a conditionally-supported-directive if it does not begin with any of the directive names appearing after a # in the syntax.
A conditionally-supported-directive is conditionally-supported with implementation-defined semantics.
At the start of phase 4 of translation, the group of a pp-global-module-fragment shall contain neither a text-line nor a pp-import.
When in a group that is skipped ([cpp.cond]), the directive syntax is relaxed to allow any sequence of preprocessing tokens to occur between the directive name and the following new-line character.
The only whitespace characters that shall appear between preprocessing tokens within a preprocessing directive (from just after the directive-introducing token through just before the terminating new-line character) are space and horizontal-tab (including spaces that have replaced comments or possibly other whitespace characters in translation phase 3).
The implementation can process and skip sections of source files conditionally, include other source files, import macros from header units, and replace macros.
These capabilities are called preprocessing, because conceptually they occur before translation of the resulting translation unit.
The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.
[Example 3: 
In: #define EMPTY EMPTY # include <file.h> the sequence of preprocessing tokens on the second line is not a preprocessing directive, because it does not begin with a # at the start of translation phase 4, even though it will do so after the macro EMPTY has been replaced.
— end example]
123)123)
Thus, preprocessing directives are commonly called “lines”.
These “lines” have no other syntactic significance, as all whitespace is equivalent except in certain situations during preprocessing (see the # character string literal creation operator in [cpp.stringize], for example).

15.2 Conditional inclusion [cpp.cond]

has-include-expression:
__has_include ( header-name )
__has_include ( header-name-tokens )
has-attribute-expression:
__has_cpp_attribute ( pp-tokens )
The expression that controls conditional inclusion shall be an integral constant expression except that identifiers (including those lexically identical to keywords) are interpreted as described below124 and it may contain zero or more defined-macro-expressions and/or has-include-expressions and/or has-attribute-expressions as unary operator expressions.
A defined-macro-expression evaluates to 1 if the identifier is currently defined as a macro name (that is, if it is predefined or if it has one or more active macro definitions ([cpp.import]), for example because it has been the subject of a #define preprocessing directive without an intervening #undef directive with the same subject identifier), 0 if it is not.
The second form of has-include-expression is considered only if the first form does not match, in which case the preprocessing tokens are processed just as in normal text.
The header or source file identified by the parenthesized preprocessing token sequence in each contained has-include-expression is searched for as if that preprocessing token sequence were the pp-tokens in a #include directive, except that no further macro expansion is performed.
If such a directive would not satisfy the syntactic requirements of a #include directive, the program is ill-formed.
The has-include-expression evaluates to 1 if the search for the source file succeeds, and to 0 if the search fails.
Each has-attribute-expression is replaced by a non-zero pp-number matching the form of an integer-literal if the implementation supports an attribute with the name specified by interpreting the pp-tokens, after macro expansion, as an attribute-token, and by 0 otherwise.
The program is ill-formed if the pp-tokens do not match the form of an attribute-token.
For an attribute specified in this document, it is implementation-defined whether the value of the has-attribute-expression is 0 or is given by Table 21.
For other attributes recognized by the implementation, the value is implementation-defined.
[Note 1: 
It is expected that the availability of an attribute can be detected by any non-zero result.
— end note]
Table 21__has_cpp_attribute values [tab:cpp.cond.ha]
Attribute
Value
assume
202207L
carries_dependency
200809L
deprecated
201309L
fallthrough
201603L
likely
201803L
maybe_unused
201603L
no_unique_address
201803L
nodiscard
201907L
noreturn
200809L
unlikely
201803L
The #ifdef, #ifndef, #elifdef, and #elifndef directives, and the defined conditional inclusion operator, shall treat __has_include and __has_cpp_attribute as if they were the names of defined macros.
The identifiers __has_include and __has_cpp_attribute shall not appear in any context not mentioned in this subclause.
Each preprocessing token that remains (in the list of preprocessing tokens that will become the controlling expression) after all macro replacements have occurred shall be in the lexical form of a token.
Preprocessing directives of the forms check whether the controlling constant expression evaluates to nonzero.
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text.
If the preprocessing token defined is generated as a result of this replacement process or use of the defined unary operator does not match one of the two specified forms prior to macro replacement, the behavior is undefined.
After all replacements due to macro expansion and evaluations of defined-macro-expressions, has-include-expressions, and has-attribute-expressions have been performed, all remaining identifiers and keywords, except for true and false, are replaced with the pp-number 0, and then each preprocessing token is converted into a token.
[Note 2: 
An alternative token is not an identifier, even when its spelling consists entirely of letters and underscores.
Therefore it is not subject to this replacement.
— end note]
The resulting tokens comprise the controlling constant expression which is evaluated according to the rules of [expr.const] using arithmetic that has at least the ranges specified in [support.limits].
For the purposes of this token conversion and evaluation all signed and unsigned integer types act as if they have the same representation as, respectively, intmax_t or uintmax_t ([cstdint.syn]).
[Note 3: 
Thus on an implementation where std​::​numeric_limits<int>​::​max() is 0x7FFF and std​::​numeric_limits<unsigned int>​::​max() is 0xFFFF, the integer literal 0x8000 is signed and positive within a #if expression even though it is unsigned in translation phase 7.
— end note]
This includes interpreting character-literals according to the rules in [lex.ccon].
[Note 4: 
The associated character encodings of literals are the same in #if and #elif directives and in any expression.
— end note]
Each subexpression with type bool is subjected to integral promotion before processing continues.
Preprocessing directives of the forms check whether the identifier is or is not currently defined as a macro name.
Their conditions are equivalent to #if defined identifier, #if !defined identifier, #elif defined identifier, and #elif !defined identifier, respectively.
Each directive's condition is checked in order.
If it evaluates to false (zero), the group that it controls is skipped: directives are processed only through the name that determines the directive in order to keep track of the level of nested conditionals; the rest of the directives' preprocessing tokens are ignored, as are the other preprocessing tokens in the group.
Only the first group whose control condition evaluates to true (nonzero) is processed; any following groups are skipped and their controlling directives are processed as if they were in a group that is skipped.
If none of the conditions evaluates to true, and there is a #else directive, the group controlled by the #else is processed; lacking a #else directive, all the groups until the #endif are skipped.125
[Example 1: 
This demonstrates a way to include a library optional facility only if it is available: #if __has_include(<optional>) # include <optional> # if __cpp_lib_optional >= 201603 # define have_optional 1 # endif #elif __has_include(<experimental/optional>) # include <experimental/optional> # if __cpp_lib_experimental_optional >= 201411 # define have_optional 1 # define experimental_optional 1 # endif #endif #ifndef have_optional # define have_optional 0 #endif
— end example]
[Example 2: 
This demonstrates a way to use the attribute [[acme​::​deprecated]] only if it is available.
#if __has_cpp_attribute(acme::deprecated) # define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] #else # define ATTR_DEPRECATED(msg) [[deprecated(msg)]] #endif ATTR_DEPRECATED("This function is deprecated") void anvil(); — end example]
124)124)
Because the controlling constant expression is evaluated during translation phase 4, all identifiers either are or are not macro names — there simply are no keywords, enumeration constants, etc.
125)125)
As indicated by the syntax, a preprocessing token cannot follow a #else or #endif directive before the terminating new-line character.
However, comments can appear anywhere in a source file, including within a preprocessing directive.

15.3 Source file inclusion [cpp.include]

A #include directive shall identify a header or source file that can be processed by the implementation.
A preprocessing directive of the form
# include < h-char-sequence > new-line
searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header.
How the places are specified or the header identified is implementation-defined.
A preprocessing directive of the form
# include " q-char-sequence " new-line
causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters.
The named source file is searched for in an implementation-defined manner.
If this search is not supported, or if the search fails, the directive is reprocessed as if it read
# include < h-char-sequence > new-line
with the identical contained sequence (including > characters, if any) from the original directive.
A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is permitted.
The preprocessing tokens after include in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).
If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined.126
The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.
The implementation shall provide unique mappings for sequences consisting of one or more nondigits or digits ([lex.name]) followed by a period (.) and a single nondigit.
The first character shall not be a digit.
The implementation may ignore distinctions of alphabetical case.
A #include preprocessing directive may appear in a source file that has been read because of a #include directive in another file, up to an implementation-defined nesting limit.
If the header identified by the header-name denotes an importable header ([module.import]), it is implementation-defined whether the #include preprocessing directive is instead replaced by an import directive ([cpp.import]) of the form
[Note 1: 
An implementation can provide a mechanism for making arbitrary source files available to the < > search.
However, using the < > form for headers provided with the implementation and the " " form for sources outside the control of the implementation achieves wider portability.
For instance: #include <stdio.h> #include <unistd.h> #include "usefullib.h" #include "myprog.h"
— end note]
[Example 1: 
This illustrates macro-replaced #include directives: #if VERSION == 1 #define INCFILE "vers1.h" #elif VERSION == 2 #define INCFILE "vers2.h" // and so on #else #define INCFILE "versN.h" #endif #include INCFILE
— end example]
126)126)
Note that adjacent string-literals are not concatenated into a single string-literal (see the translation phases in [lex.phases]); thus, an expansion that results in two string-literals is an invalid directive.

15.4 Module directive [cpp.module]

pp-module:
export module pp-tokens ; new-line
A pp-module shall not appear in a context where module or (if it is the first preprocessing token of the pp-module) export is an identifier defined as an object-like macro.
The pp-tokens, if any, of a pp-module shall be of the form: where the pp-tokens (if any) shall not begin with a ( preprocessing token and the grammar non-terminals are defined as: No identifier in the pp-module-name or pp-module-partition shall currently be defined as an object-like macro.
Any preprocessing tokens after the module preprocessing token in the module directive are processed just as in normal text.
[Note 1: 
Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.
— end note]
The module and export (if it exists) preprocessing tokens are replaced by the module-keyword and export-keyword preprocessing tokens respectively.
[Note 2: 
This makes the line no longer a directive so it is not removed at the end of phase 4.
— end note]

15.5 Header unit importation [cpp.import]

pp-import:
export import header-name pp-tokens ; new-line
export import header-name-tokens pp-tokens ; new-line
export import pp-tokens ; new-line
A pp-import shall not appear in a context where import or (if it is the first preprocessing token of the pp-import) export is an identifier defined as an object-like macro.
The preprocessing tokens after the import preprocessing token in the import control-line are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).
[Note 1: 
An import directive matching the first two forms of a pp-import instructs the preprocessor to import macros from the header unit ([module.import]) denoted by the header-name, as described below.
— end note]
The point of macro import for the first two forms of pp-import is immediately after the new-line terminating the pp-import.
The last form of pp-import is only considered if the first two forms did not match, and does not have a point of macro import.
If a pp-import is produced by source file inclusion (including by the rewrite produced when a #include directive names an importable header) while processing the group of a module-file, the program is ill-formed.
In all three forms of pp-import, the import and export (if it exists) preprocessing tokens are replaced by the import-keyword and export-keyword preprocessing tokens respectively.
[Note 2: 
This makes the line no longer a directive so it is not removed at the end of phase 4.
— end note]
Additionally, in the second form of pp-import, a header-name token is formed as if the header-name-tokens were the pp-tokens of a #include directive.
The header-name-tokens are replaced by the header-name token.
[Note 3: 
This ensures that imports are treated consistently by the preprocessor and later phases of translation.
— end note]
Each #define directive encountered when preprocessing each translation unit in a program results in a distinct macro definition.
[Note 4: 
A predefined macro name ([cpp.predefined]) is not introduced by a #define directive.
Implementations providing mechanisms to predefine additional macros are encouraged to not treat them as being introduced by a #define directive.
— end note]
Each macro definition has at most one point of definition in each translation unit and at most one point of undefinition, as follows:
  • The point of definition of a macro definition within a translation unit T is
    • if the #define directive of the macro definition occurs within T, the point at which that directive occurs, or otherwise,
    • if the macro name is not lexically identical to a keyword ([lex.key]) or to the identifiers module or import, the first point of macro import in T of a header unit containing a point of definition for the macro definition, if any.
    In the latter case, the macro is said to be imported from the header unit.
  • The point of undefinition of a macro definition within a translation unit is the first point at which a #undef directive naming the macro occurs after its point of definition, or the first point of macro import of a header unit containing a point of undefinition for the macro definition, whichever (if any) occurs first.
A macro definition is active at a source location if it has a point of definition in that translation unit preceding the location, and does not have a point of undefinition in that translation unit preceding the location.
If a macro would be replaced or redefined, and multiple macro definitions are active for that macro name, the active macro definitions shall all be valid redefinitions of the same macro ([cpp.replace]).
[Note 5: 
The relative order of pp-imports has no bearing on whether a particular macro definition is active.
— end note]
[Example 1: 

Importable header "a.h":#define X 123 // #1 #define Y 45 // #2 #define Z a // #3 #undef X // point of undefinition of #1 in "a.h"

Importable header "b.h":import "a.h"; // point of definition of #1, #2, and #3, point of undefinition of #1 in "b.h" #define X 456 // OK, #1 is not active #define Y 6 // error: #2 is active

Importable header "c.h":#define Y 45 // #4 #define Z c // #5

Importable header "d.h":import "c.h"; // point of definition of #4 and #5 in "d.h"

Importable header "e.h":import "a.h"; // point of definition of #1, #2, and #3, point of undefinition of #1 in "e.h" import "d.h"; // point of definition of #4 and #5 in "e.h" int a = Y; // OK, active macro definitions #2 and #4 are valid redefinitions int c = Z; // error: active macro definitions #3 and #5 are not valid redefinitions of Z

Module unit f:export module f; export import "a.h"; int a = Y; // OK

Translation unit #1:import f; int x = Y; // error: Y is neither a defined macro nor a declared name — end example]

15.6 Macro replacement [cpp.replace]

15.6.1 General [cpp.replace.general]

Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, ordering, spelling, and whitespace separation, where all whitespace separations are considered identical.
An identifier currently defined as an object-like macro (see below) may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two replacement lists are identical, otherwise the program is ill-formed.
Likewise, an identifier currently defined as a function-like macro (see below) may be redefined by another #define preprocessing directive provided that the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical, otherwise the program is ill-formed.
[Example 1: 
The following sequence is valid: #define OBJ_LIKE (1-1) #define OBJ_LIKE /* whitespace */ (1-1) /* other */ #define FUNC_LIKE(a) ( a ) #define FUNC_LIKE( a )( /* note the whitespace */ \ a /* other stuff on this line */ )
But the following redefinitions are invalid: #define OBJ_LIKE (0) // different token sequence #define OBJ_LIKE (1 - 1) // different whitespace #define FUNC_LIKE(b) ( a ) // different parameter usage #define FUNC_LIKE(b) ( b ) // different parameter spelling
— end example]
There shall be whitespace between the identifier and the replacement list in the definition of an object-like macro.
If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments (including those arguments consisting of no preprocessing tokens) in an invocation of a function-like macro shall equal the number of parameters in the macro definition.
Otherwise, there shall be at least as many arguments in the invocation as there are parameters in the macro definition (excluding the ...).
There shall exist a ) preprocessing token that terminates the invocation.
The identifiers __VA_ARGS__ and __VA_OPT__ shall occur only in the replacement-list of a function-like macro that uses the ellipsis notation in the parameters.
A parameter identifier in a function-like macro shall be uniquely declared within its scope.
The identifier immediately following the define is called the macro name.
There is one name space for macro names.
Any whitespace characters preceding or following the replacement list of preprocessing tokens are not considered part of the replacement list for either form of macro.
If a # preprocessing token, followed by an identifier, occurs lexically at the point at which a preprocessing directive can begin, the identifier is not subject to macro replacement.
A preprocessing directive of the form defines an object-like macro that causes each subsequent instance of the macro name127 to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive.128
The replacement list is then rescanned for more macro names as specified below.
[Example 2: 
The simplest use of this facility is to define a “manifest constant”, as in #define TABSIZE 100 int table[TABSIZE];
— end example]
A preprocessing directive of the form defines a function-like macro with parameters, whose use is similar syntactically to a function call.
The parameters are specified by the optional list of identifiers.
Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing token introduces the sequence of preprocessing tokens that is replaced by the replacement list in the definition (an invocation of the macro).
The replaced sequence of preprocessing tokens is terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and right parenthesis preprocessing tokens.
Within the sequence of preprocessing tokens making up an invocation of a function-like macro, new-line is considered a normal whitespace character.
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro.
The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments.
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives,129 the behavior is undefined.
[Example 3: 
The following defines a function-like macro whose value is the maximum of its arguments.
It has the disadvantages of evaluating one or the other of its arguments a second time (including side effects) and generating more code than a function if invoked several times.
It also cannot have its address taken, as it has none.
#define max(a, b) ((a) > (b) ? (a) : (b))
The parentheses ensure that the arguments and the resulting expression are bound properly.
— end example]
If there is a ... immediately preceding the ) in the function-like macro definition, then the trailing arguments (if any), including any separating comma preprocessing tokens, are merged to form a single item: the variable arguments.
The number of arguments so combined is such that, following merger, the number of arguments is either equal to or one more than the number of parameters in the macro definition (excluding the ...).
127)127)
Since, by macro-replacement time, all character-literals and string-literals are preprocessing tokens, not sequences possibly containing identifier-like subsequences (see [lex.phases], translation phases), they are never scanned for macro names or parameters.
128)128)
An alternative token ([lex.digraph]) is not an identifier, even when its spelling consists entirely of letters and underscores.
Therefore it is not possible to define a macro whose name is the same as that of an alternative token.
129)129)
A conditionally-supported-directive is a preprocessing directive regardless of whether the implementation supports it.

15.6.2 Argument substitution [cpp.subst]

va-opt-replacement:
__VA_OPT__ ( pp-tokens )
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place.
For each parameter in the replacement list that is neither preceded by a # or ## preprocessing token nor followed by a ## preprocessing token, the preprocessing tokens naming the parameter are replaced by a preprocessing token sequence determined as follows:
  • If the parameter is of the form va-opt-replacement, the replacement preprocessing tokens are the preprocessing token sequence for the corresponding argument, as specified below.
  • Otherwise, the replacement preprocessing tokens are the preprocessing tokens of corresponding argument after all macros contained therein have been expanded.
    The argument's preprocessing tokens are completely macro replaced before being substituted as if they formed the rest of the preprocessing translation unit with no other preprocessing tokens being available.
[Example 1: #define LPAREN() ( #define G(Q) 42 #define F(R, X, ...) __VA_OPT__(G R X) ) int x = F(LPAREN(), 0, <:-); // replaced by int x = 42; — end example]
An identifier __VA_ARGS__ that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it.
[Example 2: 
#define debug(...) fprintf(stderr, __VA_ARGS__) #define showlist(...) puts(#__VA_ARGS__) #define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__)) debug("Flag"); debug("X = %d\n", x); showlist(The first, second, and third items.); report(x>y, "x is %d but y is %d", x, y); results in fprintf(stderr, "Flag"); fprintf(stderr, "X = %d\n", x); puts("The first, second, and third items."); ((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));
— end example]
The identifier __VA_OPT__ shall always occur as part of the preprocessing token sequence va-opt-replacement; its closing ) is determined by skipping intervening pairs of matching left and right parentheses in its pp-tokens.
The pp-tokens of a va-opt-replacement shall not contain __VA_OPT__.
If the pp-tokens would be ill-formed as the replacement list of the current function-like macro, the program is ill-formed.
A va-opt-replacement is treated as if it were a parameter, and the preprocessing token sequence for the corresponding argument is defined as follows.
If the substitution of __VA_ARGS__ as neither an operand of # nor ## consists of no preprocessing tokens, the argument consists of a single placemarker preprocessing token ([cpp.concat], [cpp.rescan]).
Otherwise, the argument consists of the results of the expansion of the contained pp-tokens as the replacement list of the current function-like macro before removal of placemarker tokens, rescanning, and further replacement.
[Note 1: 
The placemarker tokens are removed before stringization ([cpp.stringize]), and can be removed by rescanning and further replacement ([cpp.rescan]).
— end note]
[Example 3: #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) #define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) #define EMP F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) F(EMP) // replaced by f(0) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 }; #define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: ## may not appear at // the beginning of a replacement list ([cpp.concat]) #define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ H2(a, b, c, d) // replaced by ab, c, d #define H3(X, ...) #__VA_OPT__(X##X X##X) H3(, 0) // replaced by "" #define H4(X, ...) __VA_OPT__(a X ## X) ## b H4(, 1) // replaced by a b #define H5A(...) __VA_OPT__()/**/__VA_OPT__() #define H5B(X) a ## X ## b #define H5C(X) H5B(X) H5C(H5A()) // replaced by ab — end example]

15.6.3 The # operator [cpp.stringize]

Each # preprocessing token in the replacement list for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list.
If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument (excluding placemarker tokens).
Let the stringizing argument be the preprocessing token sequence for the corresponding argument with placemarker tokens removed.
Each occurrence of whitespace between the stringizing argument's preprocessing tokens becomes a single space character in the character string literal.
Whitespace before the first preprocessing token and after the last preprocessing token comprising the stringizing argument is deleted.
Otherwise, the original spelling of each preprocessing token in the stringizing argument is retained in the character string literal, except for special handling for producing the spelling of string-literals and character-literals: a \ character is inserted before each " and \ character of a character-literal or string-literal (including the delimiting " characters).
If the replacement that results is not a valid character string literal, the behavior is undefined.
The character string literal corresponding to an empty stringizing argument is "".
The order of evaluation of # and ## operators is unspecified.

15.6.4 The ## operator [cpp.concat]

A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.
If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.130
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
Placemarker preprocessing tokens are handled specially: concatenation of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
[Note 1: 
Concatenation can form a universal-character-name ([lex.charset]).
— end note]
If the result is not a valid preprocessing token, the behavior is undefined.
The resulting preprocessing token is available for further macro replacement.
The order of evaluation of ## operators is unspecified.
[Example 1: 
The sequence #define str(s) # s #define xstr(s) str(s) #define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ x ## s, x ## t) #define INCFILE(n) vers ## n #define glue(a, b) a ## b #define xglue(a, b) glue(a, b) #define HIGHLOW "hello" #define LOW LOW ", world" debug(1, 2); fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away == 0) str(: @\n), s); #include xstr(INCFILE(2).h) glue(HIGH, LOW); xglue(HIGH, LOW) results in printf("x" "1" "= %d, x" "2" "= %s", x1, x2); fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s); #include "vers2.h" (after macro replacement, before file access) "hello"; "hello" ", world" or, after concatenation of the character string literals, printf("x1= %d, x2= %s", x1, x2); fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s); #include "vers2.h" (after macro replacement, before file access) "hello"; "hello, world"
Space around the # and ## preprocessing tokens in the macro definition is optional.
— end example]
[Example 2: 
In the following fragment: #define hash_hash # ## # #define mkstr(a) # a #define in_between(a) mkstr(a) #define join(c, d) in_between(c hash_hash d) char p[] = join(x, y); // equivalent to char p[] = "x ## y";
The expansion produces, at various stages: join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y) "x ## y"
In other words, expanding hash_hash produces a new preprocessing token, consisting of two adjacent sharp signs, but this new preprocessing token is not the ## operator.
— end example]
[Example 3: 
To illustrate the rules for placemarker preprocessing tokens, the sequence #define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) }; results in int j[] = { 123, 45, 67, 89, 10, 11, 12, };
— end example]
130)130)
Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.

15.6.5 Rescanning and further replacement [cpp.rescan]

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed.
Then the resulting preprocessing token sequence is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.
[Example 1: 
The sequence #define x 3 #define f(a) f(x * (a)) #undef x #define x 2 #define g f #define z z[0] #define h g(~ #define m(a) a(w) #define w 0,1 #define t(a) a #define p() int #define q(x) x #define r(x,y) x ## y #define str(x) # x f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); g(x+(3,4)-w) | h 5) & m (f)^m(m); p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; char c[2][6] = { str(hello), str() }; results in f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); int i[] = { 1, 23, 4, 5, }; char c[2][6] = { "hello", "" };
— end example]
If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file's preprocessing tokens), it is not replaced.
Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced.
These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one, but all pragma unary operator expressions within it are then processed as specified in [cpp.pragma.op] below.

15.6.6 Scope of macro definitions [cpp.scope]

A macro definition lasts (independent of block structure) until a corresponding #undef directive is encountered or (if none is encountered) until the end of the translation unit.
Macro definitions have no significance after translation phase 4.
A preprocessing directive of the form causes the specified identifier no longer to be defined as a macro name.
It is ignored if the specified identifier is not currently defined as a macro name.

15.7 Line control [cpp.line]

The string-literal of a #line directive, if present, shall be a character string literal.
The line number of the current source line is the line number of the current physical source line, i.e., it is one greater than the number of new-line characters read or introduced in translation phase 1 while processing the source file to the current preprocessing token.
A preprocessing directive of the form causes the implementation to behave as if the following sequence of source lines begins with a source line that has a line number as specified by the digit sequence (interpreted as a decimal integer).
If the digit sequence specifies zero or a number greater than 2147483647, the behavior is undefined.
A preprocessing directive of the form sets the presumed line number similarly and changes the presumed name of the source file to be the contents of the character string literal.
A preprocessing directive of the form (that does not match one of the two previous forms) is permitted.
The preprocessing tokens after line on the directive are processed just as in normal text (each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).
If the directive resulting after all replacements does not match one of the two previous forms, the behavior is undefined; otherwise, the result is processed as appropriate.

15.8 Diagnostic directives [cpp.error]

A preprocessing directive of the form
# error pp-tokens new-line
renders the program ill-formed.
A preprocessing directive of the form
# warning pp-tokens new-line
requires the implementation to produce at least one diagnostic message for the preprocessing translation unit ([intro.compliance.general]).
Recommended practice: Any diagnostic message caused by either of these directives should include the specified sequence of preprocessing tokens.

15.9 Pragma directive [cpp.pragma]

A preprocessing directive of the form
# pragma pp-tokens new-line
causes the implementation to behave in an implementation-defined manner.
The behavior may cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner.
Any pragma that is not recognized by the implementation is ignored.

15.10 Null directive [cpp.null]

A preprocessing directive of the form has no effect.

15.11 Predefined macro names [cpp.predefined]

The following macro names shall be defined by the implementation:
  • __cplusplus
    The integer literal 202302L.
    [Note 1: 
    Future revisions of this document will replace the value of this macro with a greater value.
    — end note]
  • The names listed in Table 22.

    The macros defined in Table 22 shall be defined to the corresponding integer literal.
    [Note 2: 
    Future revisions of this document might replace the values of these macros with greater values.
    — end note]
  • __DATE__
    The date of translation of the source file: a character string literal of the form "Mmm dd yyyy", where the names of the months are the same as those generated by the asctime function, and the first character of dd is a space character if the value is less than 10.
    If the date of translation is not available, an implementation-defined valid date shall be supplied.
  • __FILE__
    The presumed name of the current source file (a character string literal).131
  • __LINE__
    The presumed line number (within the current source file) of the current source line (an integer literal).132
  • __STDC_HOSTED__
    The integer literal 1 if the implementation is a hosted implementation or the integer literal 0 if it is a freestanding implementation ([intro.compliance]).
  • __STDCPP_DEFAULT_NEW_ALIGNMENT__
    An integer literal of type std​::​size_t whose value is the alignment guaranteed by a call to operator new(std​::​size_t) or operator new[](std​::​size_t).
    [Note 3: 
    Larger alignments will be passed to operator new(std​::​size_t, std​::​align_val_t), etc.
    — end note]
  • __STDCPP_FLOAT16_T__
    Defined as the integer literal 1 if and only if the implementation supports the ISO/IEC 60559 floating-point interchange format binary16 as an extended floating-point type ([basic.extended.fp]).
  • __STDCPP_FLOAT32_T__
    Defined as the integer literal 1 if and only if the implementation supports the ISO/IEC 60559 floating-point interchange format binary32 as an extended floating-point type.
  • __STDCPP_FLOAT64_T__
    Defined as the integer literal 1 if and only if the implementation supports the ISO/IEC 60559 floating-point interchange format binary64 as an extended floating-point type.
  • __STDCPP_FLOAT128_T__
    Defined as the integer literal 1 if and only if the implementation supports the ISO/IEC 60559 floating-point interchange format binary128 as an extended floating-point type.
  • __STDCPP_BFLOAT16_T__
    Defined as the integer literal 1 if and only if the implementation supports an extended floating-point type with the properties of the typedef-name std​::​bfloat16_t as described in [basic.extended.fp].
  • __TIME__
    The time of translation of the source file: a character string literal of the form "hh:mm:ss" as in the time generated by the asctime function.
    If the time of translation is not available, an implementation-defined valid time shall be supplied.
Table 22 — Feature-test macros [tab:cpp.predefined.ft]
Macro name
Value
__cpp_aggregate_bases
201603L
__cpp_aggregate_nsdmi
201304L
__cpp_aggregate_paren_init
201902L
__cpp_alias_templates
200704L
__cpp_aligned_new
201606L
__cpp_attributes
200809L
__cpp_auto_cast
202110L
__cpp_binary_literals
201304L
__cpp_capture_star_this
201603L
__cpp_char8_t
202207L
__cpp_concepts
202002L
__cpp_conditional_explicit
201806L
__cpp_constexpr
202406L
__cpp_constexpr_dynamic_alloc
201907L
__cpp_constexpr_exceptions
202411L
__cpp_constexpr_in_decltype
201711L
__cpp_consteval
202211L
__cpp_constinit
201907L
__cpp_decltype
200707L
__cpp_decltype_auto
201304L
__cpp_deduction_guides
201907L
__cpp_delegating_constructors
200604L
__cpp_deleted_function
202403L
__cpp_designated_initializers
201707L
__cpp_enumerator_attributes
201411L
__cpp_explicit_this_parameter
202110L
__cpp_fold_expressions
201603L
__cpp_generic_lambdas
201707L
__cpp_guaranteed_copy_elision
201606L
__cpp_hex_float
201603L
__cpp_if_consteval
202106L
__cpp_if_constexpr
201606L
__cpp_impl_coroutine
201902L
__cpp_impl_destroying_delete
201806L
__cpp_impl_three_way_comparison
201907L
__cpp_implicit_move
202207L
__cpp_inheriting_constructors
201511L
__cpp_init_captures
201803L
__cpp_initializer_lists
200806L
__cpp_inline_variables
201606L
__cpp_lambdas
200907L
__cpp_modules
201907L
__cpp_multidimensional_subscript
202211L
__cpp_named_character_escapes
202207L
__cpp_namespace_attributes
201411L
__cpp_noexcept_function_type
201510L
__cpp_nontype_template_args
201911L
__cpp_nontype_template_parameter_auto
201606L
__cpp_nsdmi
200809L
__cpp_pack_indexing
202311L
__cpp_placeholder_variables
202306L
__cpp_range_based_for
202211L
__cpp_raw_strings
200710L
__cpp_ref_qualifiers
200710L
__cpp_return_type_deduction
201304L
__cpp_rvalue_references
200610L
__cpp_size_t_suffix
202011L
__cpp_sized_deallocation
201309L
__cpp_static_assert
202306L
__cpp_static_call_operator
202207L
__cpp_structured_bindings
202411L
__cpp_template_template_args
201611L
__cpp_threadsafe_static_init
200806L
__cpp_unicode_characters
200704L
__cpp_unicode_literals
200710L
__cpp_user_defined_literals
200809L
__cpp_using_enum
201907L
__cpp_variable_templates
201304L
__cpp_variadic_friend
202403L
__cpp_variadic_templates
200704L
__cpp_variadic_using
201611L
The following macro names are conditionally defined by the implementation:
  • __STDC__
    Whether __STDC__ is predefined and if so, what its value is, are implementation-defined.
  • __STDC_MB_MIGHT_NEQ_WC__
    The integer literal 1, intended to indicate that, in the encoding for wchar_t, a member of the basic character set need not have a code value equal to its value when used as the lone character in an ordinary character literal.
  • __STDC_VERSION__
    Whether __STDC_VERSION__ is predefined and if so, what its value is, are implementation-defined.
  • __STDC_ISO_10646__
    An integer literal of the form yyyymmL (for example, 199712L).
    Whether __STDC_ISO_10646__ is predefined and if so, what its value is, are implementation-defined.
  • __STDCPP_THREADS__
    Defined, and has the value integer literal 1, if and only if a program can have more than one thread of execution.
The values of the predefined macros (except for __FILE__ and __LINE__) remain constant throughout the translation unit.
If any of the pre-defined macro names in this subclause, or the identifier defined, is the subject of a #define or a #undef preprocessing directive, the behavior is undefined.
Any other predefined macro names shall begin with a leading underscore followed by an uppercase letter or a second underscore.
131)131)
The presumed source file name can be changed by the #line directive.
132)132)
The presumed line number can be changed by the #line directive.

15.12 Pragma operator [cpp.pragma.op]

A unary operator expression of the form:
_Pragma ( string-literal )
is processed as follows: The string-literal is destringized by deleting the L prefix, if present, deleting the leading and trailing double-quotes, replacing each escape sequence \" by a double-quote, and replacing each escape sequence \\ by a single backslash.
The resulting sequence of characters is processed through translation phase 3 to produce preprocessing tokens that are executed as if they were the pp-tokens in a pragma directive.
The original four preprocessing tokens in the unary operator expression are removed.
[Example 1: 
#pragma listing on "..\listing.dir" can also be expressed as: _Pragma ( "listing on \"..\\listing.dir\"" )
The latter form is processed in the same way whether it appears literally as shown, or results from macro replacement, as in: #define LISTING(x) PRAGMA(listing on #x) #define PRAGMA(x) _Pragma(#x) LISTING( ..\listing.dir )
— end example]

16 Library introduction [library]

16.1 General [library.general]

This Clause describes the contents of the C++ standard library, how a well-formed C++ program makes use of the library, and how a conforming implementation may provide the entities in the library.
The following subclauses describe the method of description ([description]) and organization ([organization]) of the library.
[requirements], [support] through [exec], and [depr] specify the contents of the library, as well as library requirements and constraints on both well-formed C++ programs and conforming implementations.
Detailed specifications for each of the components in the library are in [support][exec], as shown in Table 23.
Table 23 — Library categories [tab:library.categories]
Clause
Category
Language support library
Concepts library
Diagnostics library
Memory management library
Metaprogramming library
General utilities library
Containers library
Iterators library
Ranges library
Algorithms library
Strings library
Text processing library
Numerics library
Time library
Input/output library
Concurrency support library
Execution control library
The operating system interface described in ISO/IEC/IEEE 9945:2009 is hereinafter called POSIX.
The language support library ([support]) provides components that are required by certain parts of the C++ language, such as memory allocation ([expr.new], [expr.delete]) and exception processing ([except]).
The concepts library ([concepts]) describes library components that C++ programs may use to perform compile-time validation of template arguments and perform function dispatch based on properties of types.
The diagnostics library ([diagnostics]) provides a consistent framework for reporting errors in a C++ program, including predefined exception classes.
The memory management library ([mem]) provides components for memory management, including smart pointers and scoped allocators.
The metaprogramming library ([meta]) describes facilities for use in templates and during constant evaluation, including type traits, integer sequences, and rational arithmetic.
The general utilities library ([utilities]) includes components used by other library elements, such as a predefined storage allocator for dynamic storage management ([basic.stc.dynamic]), and components used as infrastructure in C++ programs, such as tuples and function wrappers.
The containers ([containers]), iterators ([iterators]), ranges ([ranges]), and algorithms ([algorithms]) libraries provide a C++ program with access to a subset of the most widely used algorithms and data structures.
The strings library ([strings]) provides support for manipulating sequences of type char, sequences of type char8_t, sequences of type char16_t, sequences of type char32_t, sequences of type wchar_t, and sequences of any other character-like type.
The text processing library ([text]) provides support for text processing, including formatting, internationalization support and regular expression matching and searching.
The numerics library provides numeric algorithms and complex number components that extend support for numeric processing.
The valarray component provides support for n-at-a-time processing, potentially implemented as parallel operations on platforms that support such processing.
The random number component provides facilities for generating pseudo-random numbers.
The time library ([time]) provides generally useful time utilities.
The input/output library ([input.output]) provides the iostream components that are the primary mechanism for C++ program input and output.
They can be used with other elements of the library, particularly strings, locales, and iterators.
The concurrency support library ([thread]) provides components to create and manage threads, including atomic operations, mutual exclusion, and interthread communication.
The execution control library ([exec]) provides components supporting execution of function objects.

16.2 The C standard library [library.c]

The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety.
The descriptions of many library functions rely on the C standard library for the semantics of those functions.
In some cases, the signatures specified in this document may be different from the signatures in the C standard library, and additional overloads may be declared in this document, but the behavior and the preconditions (including any preconditions implied by the use of a C restrict qualifier) are the same unless otherwise stated.
A call to a C standard library function is a non-constant library call ([defns.nonconst.libcall]) if it raises a floating-point exception other than FE_INEXACT.
The semantics of a call to a C standard library function evaluated as a core constant expression are those specified in ISO/IEC 9899:2018, Annex F133 to the extent applicable to the floating-point types ([basic.fundamental]) that are parameter types of the called function.
[Note 1: 
ISO/IEC 9899:2018, 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]
[Note 2: 
Equivalently, a call to a C standard library function is a non-constant library call if errno is set when math_errhandling & MATH_ERRNO is true.
— end note]
133)133)
See also ISO/IEC 9899:2018, 7.6.

16.3 Method of description [description]

16.3.1 General [description.general]

Subclause [description] describes the conventions used to specify the C++ standard library.
[structure] describes the structure of [support] through [exec] and [depr].
[conventions] describes other editorial conventions.

16.3.2 Structure of each clause [structure]

16.3.2.1 Elements [structure.elements]

Each library clause contains the following elements, as applicable:134
134)134)
To save space, items that do not apply to a Clause are omitted.
For example, if a Clause does not specify any requirements, there will be no “Requirements” subclause.

16.3.2.2 Summary [structure.summary]

The Summary provides a synopsis of the category, and introduces the first-level subclauses.
Each subclause also provides a summary, listing the headers specified in the subclause and the library entities provided in each header.
The contents of the summary and the detailed specifications include:

16.3.2.3 Requirements [structure.requirements]

Requirements describe constraints that shall be met by a C++ program that extends the standard library.
Such extensions are generally one of the following:
  • Template arguments
  • Derived classes
  • Containers, iterators, and algorithms that meet an interface convention or model a concept
The string and iostream components use an explicit representation of operations required of template arguments.
They use a class template char_traits to define these constraints.
Interface convention requirements are stated as generally as possible.
Instead of stating “class X has to define a member function operator++()”, the interface requires “for any object x of class X, ++x is defined”.
That is, whether the operator is a member is unspecified.
Requirements are stated in terms of well-defined expressions that define valid terms of the types that meet the requirements.
For every set of well-defined expression requirements there is either a named concept or a table that specifies an initial set of the valid expressions and their semantics.
Any generic algorithm ([algorithms]) that uses the well-defined expression requirements is described in terms of the valid expressions for its template type parameters.
The library specification uses a typographical convention for naming requirements.
Names in italic type that begin with the prefix Cpp17 refer to sets of well-defined expression requirements typically presented in tabular form, possibly with additional prose semantic requirements.
For example, Cpp17Destructible (Table 35) is such a named requirement.
Names in constant width type refer to library concepts which are presented as a concept definition ([temp]), possibly with additional prose semantic requirements.
For example, destructible ([concept.destructible]) is such a named requirement.
Template argument requirements are sometimes referenced by name.
In some cases the semantic requirements are presented as C++ code.
Such code is intended as a specification of equivalence of a construct to another construct, not necessarily as the way the construct must be implemented.135
Required operations of any concept defined in this document need not be total functions; that is, some arguments to a required operation may result in the required semantics failing to be met.
[Example 1: 
The required < operator of the totally_ordered concept ([concept.totallyordered]) does not meet the semantic requirements of that concept when operating on NaNs.
— end example]
This does not affect whether a type models the concept.
A declaration may explicitly impose requirements through its associated constraints ([temp.constr.decl]).
When the associated constraints refer to a concept ([temp.concept]), the semantic constraints specified for that concept are additionally imposed on the use of the declaration.
135)135)
Although in some cases the code given is unambiguously the optimum implementation.

16.3.2.4 Detailed specifications [structure.specifications]

The detailed specifications each contain the following elements:
  • name and brief description
  • synopsis (class definition or function declaration, as appropriate)
  • restrictions on template arguments, if any
  • description of class invariants
  • description of function semantics
Descriptions of class member functions follow the order (as appropriate):136
  • constructor(s) and destructor
  • copying, moving & assignment functions
  • comparison operator functions
  • modifier functions
  • observer functions
  • operators and other non-member functions
Descriptions of function semantics contain the following elements (as appropriate):137
  • Constraints: the conditions for the function's participation in overload resolution ([over.match]).
    [Note 1: 
    Failure to meet such a condition results in the function's silent non-viability.
    — end note]
    [Example 1: 
    An implementation can express such a condition via a constraint-expression ([temp.constr.decl]).
    — end example]
  • Mandates: the conditions that, if not met, render the program ill-formed.
    [Example 2: 
    An implementation can express such a condition via the constant-expression in a static_assert-declaration ([dcl.pre]).
    If the diagnostic is to be emitted only after the function has been selected by overload resolution, an implementation can express such a condition via a constraint-expression ([temp.constr.decl]) and also define the function as deleted.
    — end example]
  • Preconditions: the conditions that the function assumes to hold whenever it is called; violation of any preconditions results in undefined behavior.
  • Effects: the actions performed by the function.
  • Synchronization: the synchronization operations ([intro.multithread]) applicable to the function.
  • Postconditions: the conditions (sometimes termed observable results) established by the function.
  • Result: for a typename-specifier, a description of the named type; for an expression, a description of the type and value category of the expression; the expression is an lvalue if the type is an lvalue reference type, an xvalue if the type is an rvalue reference type, and a prvalue otherwise.
  • Returns: a description of the value(s) returned by the function.
  • Throws: any exceptions thrown by the function, and the conditions that would cause the exception.
  • Complexity: the time and/or space complexity of the function.
  • Remarks: additional semantic constraints on the function.
  • Error conditions: the error conditions for error codes reported by the function.
Whenever the Effects element specifies that the semantics of some function F are Equivalent to some code sequence, then the various elements are interpreted as follows.
If F's semantics specifies any Constraints or Mandates elements, then those requirements are logically imposed prior to the equivalent-to semantics.
Next, the semantics of the code sequence are determined by the Constraints, Mandates, Preconditions, Effects, Synchronization, Postconditions, Returns, Throws, Complexity, Remarks, and Error conditions specified for the function invocations contained in the code sequence.
The value returned from F is specified by F's Returns element, or if F has no Returns element, a non-void return from F is specified by the return statements ([stmt.return]) in the code sequence.
If F's semantics contains a Throws, Postconditions, or Complexity element, then that supersedes any occurrences of that element in the code sequence.
For non-reserved replacement and handler functions, [support] specifies two behaviors for the functions in question: their required and default behavior.
The default behavior describes a function definition provided by the implementation.
The required behavior describes the semantics of a function definition provided by either the implementation or a C++ program.
Where no distinction is explicitly made in the description, the behavior described is the required behavior.
If the formulation of a complexity requirement calls for a negative number of operations, the actual requirement is zero operations.138
Complexity requirements specified in the library clauses are upper bounds, and implementations that provide better complexity guarantees meet the requirements.
Error conditions specify conditions where a function may fail.
The conditions are listed, together with a suitable explanation, as the enum class errc constants ([syserr]).
136)136)
To save space, items that do not apply to a class are omitted.
For example, if a class does not specify any comparison operator functions, there will be no “Comparison operator functions” subclause.
137)137)
To save space, elements that do not apply to a function are omitted.
For example, if a function specifies no preconditions, there will be no Preconditions: element.
138)138)
This simplifies the presentation of complexity requirements in some cases.

16.3.2.5 C library [structure.see.also]

Paragraphs labeled “See also” contain cross-references to the relevant portions of other standards ([intro.refs]).

16.3.3 Other conventions [conventions]

16.3.3.1 General [conventions.general]

Subclause [conventions] describes several editorial conventions used to describe the contents of the C++ standard library.
These conventions are for describing implementation-defined types, and member functions.

16.3.3.2 Exposition-only entities, etc. [expos.only.entity]

Several entities and typedef-names defined in [support] through [exec] and [depr] are only defined for the purpose of exposition.
The declaration of such an entity or typedef-name is followed by a comment ending in exposition only.
The following are defined for exposition only to aid in the specification of the library: namespace std { template<class T> requires convertible_to<T, decay_t<T>> constexpr decay_t<T> decay-copy(T&& v) // exposition only noexcept(is_nothrow_convertible_v<T, decay_t<T>>) { return std::forward<T>(v); } constexpr auto synth-three-way = // exposition only []<class T, class U>(const T& t, const U& u) requires requires { { t < u } -> boolean-testable; { u < t } -> boolean-testable; } { if constexpr (three_way_comparable_with<T, U>) { return t <=> u; } else { if (t < u) return weak_ordering::less; if (u < t) return weak_ordering::greater; return weak_ordering::equivalent; } }; template<class T, class U=T> using synth-three-way-result = // exposition only decltype(synth-three-way(declval<T&>(), declval<U&>())); }
An object dst is said to be decay-copied from a subexpression src if the type of dst is decay_t<decltype((src))>

16.3.3.3 Type descriptions [type.descriptions]

16.3.3.3.1 General [type.descriptions.general]

The Requirements subclauses may describe names that are used to specify constraints on template arguments.139
These names are used in library Clauses to describe the types that may be supplied as arguments by a C++ program when instantiating template components from the library.
Certain types defined in [input.output] are used to describe implementation-defined types.
They are based on other types, but with added constraints.
139)139)
Examples from [utility.requirements] include: Cpp17EqualityComparable, Cpp17LessThanComparable, Cpp17CopyConstructible.
Examples from [iterator.requirements] include: Cpp17InputIterator, Cpp17ForwardIterator.

16.3.3.3.2 Enumerated types [enumerated.types]

Several types defined in [input.output] are enumerated types.
Each enumerated type may be implemented as an enumeration or as a synonym for an enumeration.140
The enumerated type enumerated can be written: enum enumerated { , , , , }; inline const (); inline const (); inline const (); inline const (); ⋮
Here, the names , , etc. represent enumerated elements for this particular enumerated type.
All such elements have distinct values.
140)140)
Such as an integer type, with constant integer values ([basic.fundamental]).

16.3.3.3.3 Bitmask types [bitmask.types]

Several types defined in [support] through [exec] and [depr] are bitmask types.
Each bitmask type can be implemented as an enumerated type that overloads certain operators, as an integer type, or as a bitset.
The bitmask type bitmask can be written: // For exposition only. // int_type is an integral type capable of representing all values of the bitmask type. enum bitmask : int_type { = 1 << 0, = 1 << 1, = 1 << 2, = 1 << 3, }; inline constexpr (); inline constexpr (); inline constexpr (); inline constexpr (); ⋮ constexpr bitmask operator&(bitmask X, bitmask Y) { return static_cast<bitmask>( static_cast<int_type>(X) & static_cast<int_type>(Y)); } constexpr bitmask operator|(bitmask X, bitmask Y) { return static_cast<bitmask>( static_cast<int_type>(X) | static_cast<int_type>(Y)); } constexpr bitmask operator^(bitmask X, bitmask Y) { return static_cast<bitmask>( static_cast<int_type>(X) ^ static_cast<int_type>(Y)); } constexpr bitmask operator~(bitmask X) { return static_cast<bitmask>(~static_cast<int_type>(X)); } bitmask& operator&=(bitmask& X, bitmask Y) { X = X & Y; return X; } bitmask& operator|=(bitmask& X, bitmask Y) { X = X | Y; return X; } bitmask& operator^=(bitmask& X, bitmask Y) { X = X ^ Y; return X; }
Here, the names , , etc. represent bitmask elements for this particular bitmask type.
All such elements have distinct, nonzero values such that, for any pair and where i  ≠ j, & is nonzero and & is zero.
Additionally, the value 0 is used to represent an empty bitmask, in which no bitmask elements are set.
The following terms apply to objects and values of bitmask types:
  • To set a value Y in an object X is to evaluate the expression X |= Y.
  • To clear a value Y in an object X is to evaluate the expression X &= ~Y.
  • The value Y is set in the object X if the expression X & Y is nonzero.

16.3.3.3.4 Character sequences [character.seq]

16.3.3.3.4.1 General [character.seq.general]

The C standard library makes widespread use of characters and character sequences that follow a few uniform conventions:
  • Properties specified as locale-specific may change during program execution by a call to setlocale(int, const char*) ([clocale.syn]), or by a change to a locale object, as described in [locales] and [input.output].
  • The execution character set and the execution wide-character set are supersets of the basic literal character set ([lex.charset]).
    The encodings of the execution character sets and the sets of additional elements (if any) are locale-specific.
    Each element of the execution wide-character set is encoded as a single code unit representable by a value of type wchar_t.
    [Note 1: 
    The encodings of the execution character sets can be unrelated to any literal encoding.
    — end note]
  • A letter is any of the 26 lowercase or 26 uppercase letters in the basic character set.
  • The decimal-point character is the locale-specific (single-byte) character used by functions that convert between a (single-byte) character sequence and a value of one of the floating-point types.
    It is used in the character sequence to denote the beginning of a fractional part.
    It is represented in [support] through [exec] and [depr] by a period, '.', which is also its value in the "C" locale.
  • A character sequence is an array object A that can be declared as T A[N], where T is any of the types char, unsigned char, or signed char ([basic.fundamental]), optionally qualified by any combination of const or volatile.
    The initial elements of the array have defined contents up to and including an element determined by some predicate.
    A character sequence can be designated by a pointer value S that points to its first element.

16.3.3.3.4.2 Byte strings [byte.strings]

A null-terminated byte string, or ntbs, is a character sequence whose highest-addressed element with defined content has the value zero (the terminating null character); no other element in the sequence has the value zero.141
The length of an ntbs is the number of elements that precede the terminating null character.
An empty ntbs has a length of zero.
The value of an ntbs is the sequence of values of the elements up to and including the terminating null character.
A static ntbs is an ntbs with static storage duration.142
141)141)
Many of the objects manipulated by function signatures declared in <cstring> are character sequences or ntbss.
The size of some of these character sequences is limited by a length value, maintained separately from the character sequence.
142)142)
A string-literal, such as "abc", is a static ntbs.

16.3.3.3.4.3 Multibyte strings [multibyte.strings]

A multibyte character is a sequence of one or more bytes representing the code unit sequence for an encoded character of the execution character set.
A null-terminated multibyte string, or ntmbs, is an ntbs that constitutes a sequence of valid multibyte characters, beginning and ending in the initial shift state.143
A static ntmbs is an ntmbs with static storage duration.
143)143)
An ntbs that contains characters only from the basic literal character set is also an ntmbs.
Each multibyte character then consists of a single byte.

16.3.3.3.5 Customization Point Object types [customization.point.object]

A customization point object is a function object ([function.objects]) with a literal class type that interacts with program-defined types while enforcing semantic requirements on that interaction.
The type of a customization point object, ignoring cv-qualifiers, shall model semiregular ([concepts.object]).
All instances of a specific customization point object type shall be equal ([concepts.equality]).
The effects of invoking different instances of a specific customization point object type on the same arguments are equivalent.
The type T of a customization point object, ignoring cv-qualifiers, shall model invocable<T&, Args...>, invocable<const T&, Args...>, invocable<T, Args...>, and invocable<const T, Args...> ([concept.invocable]) when the types in Args... meet the requirements specified in that customization point object's definition.
When the types of Args... do not meet the customization point object's requirements, T shall not have a function call operator that participates in overload resolution.
For a given customization point object o, let p be a variable initialized as if by auto p = o;.
Then for any sequence of arguments args..., the following expressions have effects equivalent to o(args...):
  • p(args...)
  • as_const(p)(args...)
  • std​::​move(p)(args...)
  • std​::​move(as_const(p))(args...)

16.3.3.4 Algorithm function objects [alg.func.obj]

An algorithm function object is a customization point object ([customization.point.object]) that is specified as one or more overloaded function templates.
The name of these function templates designates the corresponding algorithm function object.
For an algorithm function object o, let S be the corresponding set of function templates.
Then for any sequence of arguments args, o(args) is expression-equivalent to s(args), where the result of name lookup for s is the overload set S.
[Note 1: 
Algorithm function objects are not found by argument-dependent name lookup ([basic.lookup.argdep]).
When found by unqualified name lookup ([basic.lookup.unqual]) for the postfix-expression in a function call ([expr.call]), they inhibit argument-dependent name lookup.
[Example 1: void foo() { using namespace std::ranges; std::vector<int> vec{1,2,3}; find(begin(vec), end(vec), 2); // #1 }
The function call expression at #1 invokes std​::​ranges​::​find, not std​::​find.
— end example]
— end note]

16.3.3.5 Functions within classes [functions.within.classes]

For the sake of exposition, [support] through [exec] and [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 ([class.copy.ctor], [class.copy.assign], [class.dtor]).
It is unspecified whether the implementation provides explicit definitions for such member function signatures, or for virtual destructors that can be generated by default.

16.3.3.6 Private members [objects.within.classes]

[support] through [exec] and [depr] do not specify the representation of classes, and intentionally omit specification of class members.
An implementation may define static or non-static class members, or both, as needed to implement the semantics of the member functions specified in [support] through [exec] and [depr].
For the sake of exposition, some subclauses provide representative declarations, and semantic requirements, for private members of classes that meet the external specifications of the classes.
The declarations for such members are followed by a comment that ends with exposition only, as in: streambuf* sb; // exposition only
An implementation may use any technique that provides equivalent observable behavior.

16.3.3.7 Freestanding items [freestanding.item]

A freestanding item is a declaration, entity, typedef-name, or macro that is required to be present in a freestanding implementation and a hosted implementation.
Unless otherwise specified, the requirements on freestanding items for a freestanding implementation are the same as the corresponding requirements for a hosted implementation, except that not all of the members of those items are required to be present.
Function declarations and function template declarations followed by a comment that include freestanding-deleted are freestanding deleted functions.
On freestanding implementations, it is implementation-defined whether each entity introduced by a freestanding deleted function is a deleted function ([dcl.fct.def.delete]) or whether the requirements are the same as the corresponding requirements for a hosted implementation.
[Note 1: 
Deleted definitions reduce the chance of overload resolution silently changing when migrating from a freestanding implementation to a hosted implementation.
— end note]
[Example 1: double abs(double j); // freestanding-deleted — end example]
A declaration in a synopsis is a freestanding item if
  • it is followed by a comment that includes freestanding,
  • it is followed by a comment that includes freestanding-deleted, or
  • the header synopsis begins with a comment that includes freestanding and the declaration is not followed by a comment that includes hosted.
    [Note 2: 
    Declarations followed by hosted in freestanding headers are not freestanding items.
    As a result, looking up the name of such functions can vary between hosted and freestanding implementations.
    — end note]
[Example 2: // all freestanding namespace std { — end example]
An entity, deduction guide, or typedef-name is a freestanding item if it is:
  • introduced by a declaration that is a freestanding item,
  • a member of a freestanding item other than a namespace,
  • an enumerator of a freestanding item,
  • a deduction guide of a freestanding item,
  • an enclosing namespace of a freestanding item,
  • a friend of a freestanding item,
  • denoted by a typedef-name that is a freestanding item, or
  • denoted by an alias template that is a freestanding item.
A macro is a freestanding item if it is defined in a header synopsis and
  • the definition is followed by a comment that includes freestanding, or
  • the header synopsis begins with a comment that includes freestanding and the definition is not followed by a comment that includes hosted.
[Example 3: #define NULL see below // freestanding — end example]
[Note 3: 
Freestanding annotations follow some additional exposition conventions that do not impose any additional normative requirements.
Header synopses that begin with a comment containing "all freestanding" contain no hosted items and no freestanding deleted functions.
Header synopses that begin with a comment containing "mostly freestanding" contain at least one hosted item or freestanding deleted function.
Classes and class templates followed by a comment containing "partially freestanding" contain at least one hosted item or freestanding deleted function.
— end note]
[Example 4: template<class T, size_t N> struct array; // partially freestanding template<class T, size_t N> struct array { constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); // freestanding-deleted constexpr const_reference at(size_type n) const; // freestanding-deleted }; — end example]

16.4 Library-wide requirements [requirements]

16.4.1 General [requirements.general]

Subclause [requirements] specifies requirements that apply to the entire C++ standard library.
[support] through [exec] and [depr] specify the requirements of individual entities within the library.
Requirements specified in terms of interactions between threads do not apply to programs having only a single thread of execution.
[organization] describes the library's contents and organization, [using] describes how well-formed C++ programs gain access to library entities, [utility.requirements] describes constraints on types and functions used with the C++ standard library, [constraints] describes constraints on well-formed C++ programs, and [conforming] describes constraints on conforming implementations.

16.4.2 Library contents and organization [organization]

16.4.2.1 General [organization.general]

[contents] describes the entities and macros defined in the C++ standard library.
[headers] lists the standard library headers and some constraints on those headers.
[compliance] lists requirements for a freestanding implementation of the C++ standard library.

16.4.2.2 Library contents [contents]

The C++ standard library provides definitions for the entities and macros described in the synopses of the C++ standard library headers ([headers]), unless otherwise specified.
All library entities except operator new and operator delete are defined within the namespace std or namespaces nested within namespace std.144
It is unspecified whether names declared in a specific namespace are declared directly in that namespace or in an inline namespace inside that namespace.145
Whenever an unqualified name other than swap, make_error_code, make_error_condition, or submdspan_mapping is used in the specification of a declaration D in [support] through [exec] or [depr], its meaning is established as-if by performing unqualified name lookup ([basic.lookup.unqual]) in the context of D.
[Note 1: 
Argument-dependent lookup is not performed.
— end note]
Similarly, the meaning of a qualified-id is established as-if by performing qualified name lookup ([basic.lookup.qual]) in the context of D.
[Example 1: 
The reference to is_array_v in the specification of std​::​to_array ([array.creation]) refers to ​::​std​::​is_array_v.
— end example]
[Note 2: 
Operators in expressions ([over.match.oper]) are not so constrained; see [global.functions].
— end note]
The meaning of the unqualified name swap is established in an overload resolution context for swappable values ([swappable.requirements]).
The meanings of the unqualified names make_error_code, make_error_condition, and submdspan_mapping are established as-if by performing argument-dependent lookup ([basic.lookup.argdep]).
144)144)
The C standard library headers ([support.c.headers]) also define names within the global namespace, while the C++ headers for C library facilities ([headers]) can also define names within the global namespace.
145)145)
This gives implementers freedom to use inline namespaces to support multiple configurations of the library.

16.4.2.3 Headers [headers]

Each element of the C++ standard library is declared or defined (as appropriate) in a header.146
The C++ standard library provides the C++ library headers, shown in Table 24.
Table 24 — C++ library headers [tab:headers.cpp]
<algorithm>
<forward_list>
<mutex>
<stacktrace>
<any>
<fstream>
<new>
<stdexcept>
<array>
<functional>
<numbers>
<stdfloat>
<atomic>
<future>
<numeric>
<stop_token>
<barrier>
<generator>
<optional>
<streambuf>
<bit>
<hazard_pointer>
<ostream>
<string>
<bitset>
<initializer_list>
<print>
<string_view>
<charconv>
<inplace_vector>
<queue>
<syncstream>
<chrono>
<iomanip>
<random>
<system_error>
<compare>
<ios>
<ranges>
<text_encoding>
<complex>
<iosfwd>
<ratio>
<thread>
<concepts>
<iostream>
<rcu>
<tuple>
<condition_variable>
<istream>
<regex>
<type_traits>
<coroutine>
<iterator>
<scoped_allocator>
<typeindex>
<debugging>
<latch>
<semaphore>
<typeinfo>
<deque>
<limits>
<set>
<unordered_map>
<exception>
<linalg>
<shared_mutex>
<unordered_set>
<execution>
<list>
<simd>
<utility>
<expected>
<locale>
<source_location>
<valarray>
<filesystem>
<map>
<span>
<variant>
<flat_map>
<mdspan>
<spanstream>
<vector>
<flat_set>
<memory>
<sstream>
<version>
<format>
<memory_resource>
<stack>
The facilities of the C standard library are provided in the additional headers shown in Table 25.147
Table 25 — C++ headers for C library facilities [tab:headers.cpp.c]
<cassert>
<cfenv>
<climits>
<csetjmp>
<cstddef>
<cstdlib>
<cuchar>
<cctype>
<cfloat>
<clocale>
<csignal>
<cstdint>
<cstring>
<cwchar>
<cerrno>
<cinttypes>
<cmath>
<cstdarg>
<cstdio>
<ctime>
<cwctype>
The headers listed in Table 24, or, for a freestanding implementation, the subset of such headers that are provided by the implementation, are collectively known as the importable C++ library headers.
[Note 1: 
Importable C++ library headers can be imported ([module.import]).
— end note]
[Example 1: import <vector>; // imports the <vector> header unit std::vector<int> vi; // OK — end example]
Except as noted in [library] through [exec] and [depr], the contents of each header cname is the same as that of the corresponding header name.h as specified in the C standard library.
In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope of the namespace std.
It is unspecified whether these names (including any overloads added in [support] through [exec] and [depr]) are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations ([namespace.udecl]).
Names which are defined as macros in C shall be defined as macros in the C++ standard library, even if C grants license for implementation as functions.
[Note 2: 
The names defined as macros in C include the following: assert, offsetof, setjmp, va_arg, va_end, and va_start.
— end note]
Names that are defined as functions in C shall be defined as functions in the C++ standard library.148
Identifiers that are keywords or operators in C++ shall not be defined as macros in C++ standard library headers.149
Subclause [support.c.headers] describes the effects of using the name.h (C header) form in a C++ program.150
ISO/IEC 9899:2018, Annex K describes a large number of functions, with associated types and macros, which “promote safer, more secure programming” than many of the traditional C library functions.
The names of the functions have a suffix of _s; most of them provide the same service as the C library function with the unsuffixed name, but generally take an additional argument whose value is the size of the result array.
If any C++ header is included, it is implementation-defined whether any of these names is declared in the global namespace.
(None of them is declared in namespace std.)
Table 26 lists the Annex K names that may be declared in some header.
These names are also subject to the restrictions of [macro.names].
Table 26 — Names from ISO/IEC 9899:2018, Annex K [tab:c.annex.k.names]
abort_handler_s
mbstowcs_s
strncat_s
vswscanf_s
asctime_s
memcpy_s
strncpy_s
vwprintf_s
bsearch_s
memmove_s
strtok_s
vwscanf_s
constraint_handler_t
memset_s
swprintf_s
wcrtomb_s
ctime_s
printf_s
swscanf_s
wcscat_s
errno_t
qsort_s
tmpfile_s
wcscpy_s
fopen_s
RSIZE_MAX
TMP_MAX_S
wcsncat_s
fprintf_s
rsize_t
tmpnam_s
wcsncpy_s
freopen_s
scanf_s
vfprintf_s
wcsnlen_s
fscanf_s
set_constraint_handler_s
vfscanf_s
wcsrtombs_s
fwprintf_s
snprintf_s
vfwprintf_s
wcstok_s
fwscanf_s
snwprintf_s
vfwscanf_s
wcstombs_s
getenv_s
sprintf_s
vprintf_s
wctomb_s
gets_s
sscanf_s
vscanf_s
wmemcpy_s
gmtime_s
strcat_s
vsnprintf_s
wmemmove_s
ignore_handler_s
strcpy_s
vsnwprintf_s
wprintf_s
localtime_s
strerrorlen_s
vsprintf_s
wscanf_s
L_tmpnam_s
strerror_s
vsscanf_s
mbsrtowcs_s
strlen_s
vswprintf_s
146)146)
A header is not necessarily a source file, nor are the sequences delimited by < and > in header names necessarily valid source file names ([cpp.include]).
147)147)
It is intentional that there is no C++ header for any of these C headers: <stdnoreturn.h>, <threads.h>.
148)148)
This disallows the practice, allowed in C, of providing a masking macro in addition to the function prototype.
The only way to achieve equivalent inline behavior in C++ is to provide a definition as an extern inline function.
149)149)
In particular, including the standard header <iso646.h> has no effect.
150)150)
The ".h" headers dump all their names into the global namespace, whereas the newer forms keep their names in namespace std.
Therefore, the newer forms are the preferred forms for all uses except for C++ programs which are intended to be strictly compatible with C.

16.4.2.4 Modules [std.modules]

The C++ standard library provides the following C++ library modules.
The named module std exports declarations in namespace std that are provided by the importable C++ library headers (Table 24 or the subset provided by a freestanding implementation) and the C++ headers for C library facilities (Table 25).
It additionally exports declarations in the global namespace for the storage allocation and deallocation functions that are provided by <new>.
The named module std.compat exports the same declarations as the named module std, and additionally exports
  • declarations in the global namespace corresponding to the declarations in namespace std that are provided by the C++ headers for C library facilities (Table 25), except the explicitly excluded declarations described in [support.c.headers.other] and
  • declarations provided by the headers <stdbit.h> and <stdckdint.h>.
It is unspecified to which module a declaration in the standard library is attached.
[Note 1: 
Conforming implementations ensure that mixing #include and import does not result in conflicting attachments ([basic.link]).
— end note]
Recommended practice: Implementations should ensure such attachments do not preclude further evolution or decomposition of the standard library modules.
A declaration in the standard library denotes the same entity regardless of whether it was made reachable through including a header, importing a header unit, or importing a C++ library module.
Recommended practice: Implementations should avoid exporting any other declarations from the C++ library modules.
[Note 2: 
Like all named modules, the C++ library modules do not make macros visible ([module.import]), such as assert ([cassert.syn]), errno ([cerrno.syn]), offsetof ([cstddef.syn]), and va_arg ([cstdarg.syn]).
— end note]

16.4.2.5 Freestanding implementations [compliance]

Two kinds of implementations are defined: hosted and freestanding ([intro.compliance]); the kind of the implementation is implementation-defined.
For a hosted implementation, this document describes the set of available headers.
A freestanding implementation has an implementation-defined set of headers.
This set shall include at least the headers shown in Table 27.
Table 27 — C++ headers for freestanding implementations [tab:headers.cpp.fs]
Subclause
Header
Common definitions
<cstddef>
C standard library
<cstdlib>
Implementation properties
<cfloat>, <climits>, <limits>,
<version>
Integer types
<cstdint>
Dynamic memory management
<new>
Type identification
<typeinfo>
Source location
<source_location>
Exception handling
<exception>
Initializer lists
<initializer_list>
Comparisons
<compare>
Coroutines support
<coroutine>
Other runtime support
<cstdarg>
Concepts library
<concepts>
Error numbers
<cerrno>
System error support
<system_error>
Debugging
<debugging>
Memory
<memory>
Type traits
<type_traits>
Compile-time rational arithmetic
<ratio>
Utility components
<utility>
Tuples
<tuple>
Optional objects
<optional>
Variants
<variant>
Expected objects
<expected>
Function objects
<functional>
Bit manipulation
<bit>
Class template array
<array>
Class template inplace_vector
<inplace_vector>
Contiguous access
<span>
Multidimensional access
<mdspan>
Iterators library
<iterator>
Ranges library
<ranges>
Algorithms library
<algorithm>, <numeric>
String view classes
<string_view>
String classes
<string>
Null-terminated sequence utilities
<cstring>, <cwchar>
Primitive numeric conversions
<charconv>
Mathematical functions for floating-point types
<cmath>
Atomics
<atomic>
For each of the headers listed in Table 27, a freestanding implementation provides at least the freestanding items ([freestanding.item]) declared in the header.
The hosted library facilities are the set of facilities described in this document that are required for hosted implementations, but not required for freestanding implementations.
A freestanding implementation provides a (possibly empty) implementation-defined subset of the hosted library facilities.
Unless otherwise specified, the requirements on each declaration, entity, typedef-name, and macro provided in this way are the same as the corresponding requirements for a hosted implementation, except that not all of the members of the namespaces are required to be present.
A freestanding implementation provides deleted definitions ([dcl.fct.def.delete]) for a (possibly empty) implementation-defined subset of the namespace-scope functions and function templates from the hosted library facilities.
[Note 1: 
An implementation can provide a deleted definition so that the result of overload resolution does not silently change when migrating a program from a freestanding implementation to a hosted implementation.
— end note]

16.4.3 Using the library [using]

16.4.3.1 Overview [using.overview]

Subclause [using] describes how a C++ program gains access to the facilities of the C++ standard library.
[using.headers] describes effects during translation phase 4, while [using.linkage] describes effects during phase 8.

16.4.3.2 Headers [using.headers]

The entities in the C++ standard library are defined in headers, whose contents are made available to a translation unit when it contains the appropriate #include preprocessing directive ([cpp.include]) or the appropriate import declaration ([module.import]).
A translation unit may include library headers in any order ([lex.separate]).
Each may be included more than once, with no effect different from being included exactly once, except that the effect of including either <cassert> or <assert.h> depends each time on the lexically current definition of NDEBUG.151
A translation unit shall include a header only outside of any declaration or definition and, in the case of a module unit, only in its global-module-fragment, and shall include the header or import the corresponding header unit lexically before the first reference in that translation unit to any of the entities declared in that header.
No diagnostic is required.
151)151)
This is the same as the C standard library.

16.4.3.3 Linkage [using.linkage]

Entities in the C++ standard library have external linkage.
Unless otherwise specified, objects and functions have the default extern "C++" linkage ([dcl.link]).
Whether a name from the C standard library declared with external linkage has extern "C" or extern "C++" linkage is implementation-defined.
It is recommended that an implementation use extern "C++" linkage for this purpose.152
Objects and functions defined in the library and required by a C++ program are included in the program prior to program startup.
152)152)
The only reliable way to declare an object or function signature from the C standard library is by including the header that declares it, notwithstanding the latitude granted in ISO/IEC 9899:2018, 7.1.4.

16.4.4 Requirements on types and expressions [utility.requirements]

16.4.4.1 General [utility.requirements.general]

[utility.arg.requirements] describes requirements on types and expressions used to instantiate templates defined in the C++ standard library.
[swappable.requirements] describes the requirements on swappable types and swappable expressions.
[nullablepointer.requirements] describes the requirements on pointer-like types that support null values.
[hash.requirements] describes the requirements on hash function objects.
[allocator.requirements] describes the requirements on storage allocators.

16.4.4.2 Template argument requirements [utility.arg.requirements]

The template definitions in the C++ standard library refer to various named requirements whose details are set out in Tables 2835.
In these tables,
  • T denotes an object or reference type to be supplied by a C++ program instantiating a template,
  • a, b, and c denote values of type (possibly const) T,
  • s and t denote modifiable lvalues of type T,
  • u denotes an identifier,
  • rv denotes an rvalue of type T, and
  • v denotes an lvalue of type (possibly const) T or an rvalue of type const T.
In general, a default constructor is not required.
Certain container class member function signatures specify T() as a default argument.
T() shall be a well-defined expression ([dcl.init]) if one of those signatures is called using the default argument.
Table 28Cpp17EqualityComparable requirements [tab:cpp17.equalitycomparable]
Expression
Return type
Requirement
a == b
decltype(a == b) models boolean-testable
== is an equivalence relation, that is, it has the following properties:
  • For all a, a == a.
  • If a == b, then b == a.
  • If a == b and b == c, then a == c.
Table 29Cpp17LessThanComparable requirements [tab:cpp17.lessthancomparable]
Expression
Return type
Requirement
a < b
decltype(a < b) models boolean-testable
< is a strict weak ordering relation ([alg.sorting])
Table 30Cpp17DefaultConstructible requirements [tab:cpp17.defaultconstructible]
Expression
Post-condition
T t;
object t is default-initialized
T u{};
object u is value-initialized or aggregate-initialized
T()
T{}
an object of type T is value-initialized or aggregate-initialized
Table 31Cpp17MoveConstructible requirements [tab:cpp17.moveconstructible]
Expression
Post-condition
T u = rv;
u is equivalent to the value of rv before the construction
T(rv)
T(rv) is equivalent to the value of rv before the construction
rv's state is unspecified
[Note 1: 
rv must still meet the requirements of the library component that is using it.
The operations listed in those requirements must work as specified whether rv has been moved from or not.
— end note]
Table 32Cpp17CopyConstructible requirements (in addition to Cpp17MoveConstructible) [tab:cpp17.copyconstructible]
Expression
Post-condition
T u = v;
the value of v is unchanged and is equivalent to u
T(v)
the value of v is unchanged and is equivalent to T(v)
Table 33Cpp17MoveAssignable requirements [tab:cpp17.moveassignable]
Expression
Return type
Return value
Post-condition
t = rv
T&
t
If t and rv do not refer to the same object, t is equivalent to the value of rv before the assignment
rv's state is unspecified.
[Note 2: 
rv must still meet the requirements of the library component that is using it, whether or not t and rv refer to the same object.
The operations listed in those requirements must work as specified whether rv has been moved from or not.
— end note]
Table 34Cpp17CopyAssignable requirements (in addition to Cpp17MoveAssignable) [tab:cpp17.copyassignable]
Expression
Return type
Return value
Post-condition
t = v
T&
t
t is equivalent to v, the value of v is unchanged
Table 35Cpp17Destructible requirements [tab:cpp17.destructible]
Expression
Post-condition
u.~T()
All resources owned by u are reclaimed, no exception is propagated.
[Note 3: 
Array types and non-object types are not Cpp17Destructible.
— end note]

16.4.4.3 Swappable requirements [swappable.requirements]

This subclause provides definitions for swappable types and expressions.
In these definitions, let t denote an expression of type T, and let u denote an expression of type U.
An object t is swappable with an object u if and only if
  • the expressions swap(t, u) and swap(u, t) are valid when evaluated in the context described below, and
  • these expressions have the following effects:
    • the object referred to by t has the value originally held by u and
    • the object referred to by u has the value originally held by t.
The context in which swap(t, u) and swap(u, t) are evaluated shall ensure that a binary non-member function named “swap” is selected via overload resolution on a candidate set that includes:
[Note 1: 
If T and U are both fundamental types or arrays of fundamental types and the declarations from the header <utility> are in scope, the overall lookup set described above is equivalent to that of the qualified name lookup applied to the expression std​::​swap(t, u) or std​::​swap(u, t) as appropriate.
— end note]
[Note 2: 
It is unspecified whether a library component that has a swappable requirement includes the header <utility> to ensure an appropriate evaluation context.
— end note]
An rvalue or lvalue t is swappable if and only if t is swappable with any rvalue or lvalue, respectively, of type T.
A type X meets the Cpp17Swappable requirements if lvalues of type X are swappable.
A type X meeting any of the iterator requirements ([iterator.requirements]) meets the Cpp17ValueSwappable requirements if, for any dereferenceable object x of type X, *x is swappable.
[Example 1: 
User code can ensure that the evaluation of swap calls is performed in an appropriate context under the various conditions as follows: #include <cassert> #include <utility> // Preconditions: std​::​forward<T>(t) is swappable with std​::​forward<U>(u). template<class T, class U> void value_swap(T&& t, U&& u) { using std::swap; swap(std::forward<T>(t), std::forward<U>(u)); // OK, uses “swappable with'' conditions // for rvalues and lvalues } // Preconditions: T meets the Cpp17Swappable requirements. template<class T> void lv_swap(T& t1, T& t2) { using std::swap; swap(t1, t2); // OK, uses swappable conditions for lvalues of type T } namespace N { struct A { int m; }; struct Proxy { A* a; }; 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 // conditions for fundamental types } void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint } int main() { int i = 1, j = 2; lv_swap(i, j); assert(i == 2 && j == 1); N::A a1 = { 5 }, a2 = { -5 }; value_swap(a1, proxy(a2)); assert(a1.m == -5 && a2.m == 5); }
— end example]

16.4.4.4 Cpp17NullablePointer requirements [nullablepointer.requirements]

A Cpp17NullablePointer type is a pointer-like type that supports null values.
A type P meets the Cpp17NullablePointer requirements if
A value-initialized object of type P produces the null value of the type.
The null value shall be equivalent only to itself.
A default-initialized object of type P may have an indeterminate or erroneous value.
[Note 1: 
Operations involving indeterminate values can cause undefined behavior, and operations involving erroneous values can cause erroneous behavior ([basic.indet]).
— end note]
An object p of type P can be contextually converted to bool.
The effect shall be as if p != nullptr had been evaluated in place of p.
No operation which is part of the Cpp17NullablePointer requirements shall exit via an exception.
In Table 36, u denotes an identifier, t denotes a non-const lvalue of type P, a and b denote values of type (possibly const) P, and np denotes a value of type (possibly const) std​::​nullptr_t.
Table 36Cpp17NullablePointer requirements [tab:cpp17.nullablepointer]
Expression
Return type
Operational semantics
P u(np);
Postconditions: u == nullptr
P u = np;
P(np)
Postconditions: P(np) == nullptr
t = np
P&
Postconditions: t == nullptr
a != b
decltype(a != b) models boolean-testable
!(a == b)
a == np
decltype(a == np) and decltype(np == a) each model boolean-testable
a == P()
np == a
a != np
decltype(a != np) and decltype(np != a) each model boolean-testable
!(a == np)
np != a

16.4.4.5 Cpp17Hash requirements [hash.requirements]

A type H meets the Cpp17Hash requirements if
Given Key is an argument type for function objects of type H, in Table 37 h is a value of type (possibly const) H, u is an lvalue of type Key, and k is a value of a type convertible to (possibly const) Key.
Table 37Cpp17Hash requirements [tab:cpp17.hash]
Expression
Return type
Requirement
h(k)
size_t
The value returned shall depend only on the argument k for the duration of the program.
[Note 1: 
Thus all evaluations of the expression h(k) with the same value for k yield the same result for a given execution of the program.
— end note]
For two different values t1 and t2, the probability that h(t1) and h(t2) compare equal should be very small, approaching 1.0 / numeric_limits<size_t>​::​max().
h(u)
size_t
Shall not modify u.

16.4.4.6 Cpp17Allocator requirements [allocator.requirements]

16.4.4.6.1 General [allocator.requirements.general]

The library describes a standard set of requirements for allocators, which are class-type objects that encapsulate the information about an allocation model.
This information includes the knowledge of pointer types, the type of their difference, the type of the size of objects in this allocation model, as well as the memory allocation and deallocation primitives for it.
All of the string types ([strings]), containers ([containers]) (except array and inplace_vector), string buffers and string streams ([input.output]), and match_results are parameterized in terms of allocators.
In [allocator.requirements],
  • T, U, C denote any cv-unqualified object type ([basic.types.general]),
  • X denotes an allocator class for type T,
  • Y denotes the corresponding allocator class for type U,
  • XX denotes the type allocator_traits<X>,
  • YY denotes the type allocator_traits<Y>,
  • a, a1, a2 denote lvalues of type X,
  • u denotes the name of a variable being declared,
  • b denotes a value of type Y,
  • c denotes a pointer of type C* through which indirection is valid,
  • p denotes a value of type XX​::​pointer obtained by calling a1.allocate, where a1 == a,
  • q denotes a value of type XX​::​const_pointer obtained by conversion from a value p,
  • r denotes a value of type T& obtained by the expression *p,
  • w denotes a value of type XX​::​void_pointer obtained by conversion from a value p,
  • x denotes a value of type XX​::​const_void_pointer obtained by conversion from a value q or a value w,
  • y denotes a value of type XX​::​const_void_pointer obtained by conversion from a result value of YY​::​allocate, or else a value of type (possibly const) std​::​nullptr_t,
  • n denotes a value of type XX​::​size_type,
  • Args denotes a template parameter pack, and
  • args denotes a function parameter pack with the pattern Args&&.
The class template allocator_traits ([allocator.traits]) supplies a uniform interface to all allocator types.
This subclause describes the requirements on allocator types and thus on types used to instantiate allocator_traits.
A requirement is optional if a default for a given type or expression is specified.
Within the standard library allocator_traits template, an optional requirement that is not supplied by an allocator is replaced by the specified default type or expression.
[Note 1: 
There are no program-defined specializations of allocator_traits.
— end note]
typename X::pointer
Remarks: Default: T*
typename X::const_pointer
Mandates: XX​::​pointer is convertible to XX​::​const_pointer.
Remarks: Default: pointer_traits<XX​::​pointer>​::​rebind<const T>
typename X::void_pointer typename Y::void_pointer
Mandates: XX​::​pointer is convertible to XX​::​void_pointer.
XX​::​void_pointer and YY​::​void_pointer are the same type.
Remarks: Default: pointer_traits<XX​::​pointer>​::​rebind<void>
typename X::const_void_pointer typename Y::const_void_pointer
Mandates: XX​::​pointer, XX​::​const_pointer, and XX​::​void_pointer are convertible to XX​::​const_void_pointer.
XX​::​const_void_pointer and YY​::​const_void_pointer are the same type.
Remarks: Default: pointer_traits<XX​::​pointer>​::​rebind<const void>
typename X::value_type
Result: Identical to T.
typename X::size_type
Result: An unsigned integer type that can represent the size of the largest object in the allocation model.
Remarks: Default: make_unsigned_t<XX​::​difference_type>
typename X::difference_type
Result: A signed integer type that can represent the difference between any two pointers in the allocation model.
Remarks: Default: pointer_traits<XX​::​pointer>​::​difference_type
typename X::rebind<U>::other
Result: Y
Postconditions: For all U (including T), YY​::​rebind_alloc<T> is X.
Remarks: If Allocator is a class template instantiation of the form SomeAllocator<T, Args>, where Args is zero or more type arguments, and Allocator does not supply a rebind member template, the standard allocator_traits template uses SomeAllocator<U, Args> in place of Allocator​::​rebind<U>​::​other by default.
For allocator types that are not template instantiations of the above form, no default is provided.
[Note 2: 
The member class template rebind of X is effectively a typedef template.
In general, if the name Allocator is bound to SomeAllocator<T>, then Allocator​::​rebind<U>​::​other is the same type as SomeAllocator<U>, where SomeAllocator<T>​::​value_type is T and SomeAllocator<U>​::​value_type is U.
— end note]
*p
Result: T&
*q
Result: const T&
Postconditions: *q refers to the same object as *p.
p->m
Result: Type of T​::​m.
Preconditions: (*p).m is well-defined.
Effects: Equivalent to (*p).m.
q->m
Result: Type of T​::​m.
Preconditions: (*q).m is well-defined.
Effects: Equivalent to (*q).m.
static_cast<XX::pointer>(w)
Result: XX​::​pointer
Postconditions: static_cast<XX​::​pointer>(w) == p.
static_cast<XX::const_pointer>(x)
Result: XX​::​const_pointer
Postconditions: static_cast<XX​::​const_pointer>(x) == q.
pointer_traits<XX::pointer>::pointer_to(r)
Result: XX​::​pointer
Postconditions: Same as p.
a.allocate(n)
Result: XX​::​pointer
Effects: Memory is allocated for an array of n T and such an object is created but array elements are not constructed.
[Example 1: 
When reusing storage denoted by some pointer value p, launder(reinterpret_cast<T*>(new (p) byte[n * sizeof(T)])) can be used to implicitly create a suitable array object and obtain a pointer to it.
— end example]
Throws: allocate may throw an appropriate exception.
[Note 3: 
It is intended that a.allocate be an efficient means of allocating a single object of type T, even when sizeof(T) is small.
That is, there is no need for a container to maintain its own free list.
— end note]
Remarks: If n == 0, the return value is unspecified.
a.allocate(n, y)
Result: XX​::​pointer
Effects: Same as a.allocate(n).
The use of y is unspecified, but it is intended as an aid to locality.
Remarks: Default: a.allocate(n)
a.allocate_at_least(n)
Result: allocation_result<XX​::​pointer, XX​::​size_type>
Returns: allocation_result<XX​::​pointer, XX​::​size_type>{ptr, count} where ptr is memory allocated for an array of count T and such an object is created but array elements are not constructed, such that count  ≥ n.
If n == 0, the return value is unspecified.
Throws: allocate_at_least may throw an appropriate exception.
Remarks: Default: {a.allocate(n), n}.
a.deallocate(p, n)
Result: (not used)
Preconditions:
  • If p is memory that was obtained by a call to a.allocate_at_least, let ret be the value returned and req be the value passed as the first argument of that call.
    p is equal to ret.ptr and n is a value such that req  ≤ n  ≤ ret.count.
  • Otherwise, p is a pointer value obtained from allocate.
    n equals the value passed as the first argument to the invocation of allocate which returned p.
p has not been invalidated by an intervening call to deallocate.
Throws: Nothing.
a.max_size()
Result: XX​::​size_type
Returns: The largest value n that can meaningfully be passed to a.allocate(n).
Remarks: Default: numeric_limits<size_type>​::​max() / sizeof(value_type)
a1 == a2
Result: bool
Returns: true only if storage allocated from each can be deallocated via the other.
Throws: Nothing.
Remarks: operator== shall be reflexive, symmetric, and transitive.
a1 != a2
Result: bool
Returns: !(a1 == a2).
a == b
Result: bool
Returns: a == YY​::​rebind_alloc<T>(b).
a != b
Result: bool
Returns: !(a == b).
X u(a); X u = a;
Postconditions: u == a
Throws: Nothing.
X u(b);
Postconditions: Y(u) == b and u == X(b).
Throws: Nothing.
X u(std::move(a)); X u = std::move(a);
Postconditions: The value of a is unchanged and is equal to u.
Throws: Nothing.
X u(std::move(b));
Postconditions: u is equal to the prior value of X(b).
Throws: Nothing.
a.construct(c, args...)
Result: (not used)
Effects: Constructs an object of type C at c.
Remarks: Default: construct_at(c, std​::​forward<Args>(args)...)
a.destroy(c)
Result: (not used)
Effects: Destroys the object at c.
Remarks: Default: destroy_at(c)
a.select_on_container_copy_construction()
Result: X
Returns: Typically returns either a or X().
Remarks: Default: return a;
typename X::propagate_on_container_copy_assignment
Result: Identical to or derived from true_type or false_type.
Returns: true_type only if an allocator of type X should be copied when the client container is copy-assigned; if so, X shall meet the Cpp17CopyAssignable requirements (Table 34) and the copy operation shall not throw exceptions.
Remarks: Default: false_type
typename X::propagate_on_container_move_assignment
Result: Identical to or derived from true_type or false_type.
Returns: true_type only if an allocator of type X should be moved when the client container is move-assigned; if so, X shall meet the Cpp17MoveAssignable requirements (Table 33) and the move operation shall not throw exceptions.
Remarks: Default: false_type
typename X::propagate_on_container_swap
Result: Identical to or derived from true_type or false_type.
Returns: true_type only if an allocator of type X should be swapped when the client container is swapped; if so, X shall meet the Cpp17Swappable requirements ([swappable.requirements]) and the swap operation shall not throw exceptions.
Remarks: Default: false_type
typename X::is_always_equal
Result: Identical to or derived from true_type or false_type.
Returns: true_type only if the expression a1 == a2 is guaranteed to be true for any two (possibly const) values a1, a2 of type X.
Remarks: Default: is_empty<X>​::​type
An allocator type X shall meet the Cpp17CopyConstructible requirements (Table 32).
The XX​::​pointer, XX​::​const_pointer, XX​::​void_pointer, and XX​::​const_void_pointer types shall meet the Cpp17NullablePointer requirements (Table 36).
No constructor, comparison operator function, copy operation, move operation, or swap operation on these pointer types shall exit via an exception.
XX​::​pointer and XX​::​const_pointer shall also meet the requirements for a Cpp17RandomAccessIterator ([random.access.iterators]) and the additional requirement that, when p and (p + n) are dereferenceable pointer values for some integral value n, addressof(*(p + n)) == addressof(*p) + n is true.
Let x1 and x2 denote objects of (possibly different) types XX​::​void_pointer, XX​::​const_void_pointer, XX​::​pointer, or XX​::​const_pointer.
Then, x1 and x2 are equivalently-valued pointer values, if and only if both x1 and x2 can be explicitly converted to the two corresponding objects px1 and px2 of type XX​::​const_pointer, using a sequence of static_casts using only these four types, and the expression px1 == px2 evaluates to true.
Let w1 and w2 denote objects of type XX​::​void_pointer.
Then for the expressions w1 == w2 w1 != w2 either or both objects may be replaced by an equivalently-valued object of type XX​::​const_void_pointer with no change in semantics.
Let p1 and p2 denote objects of type XX​::​pointer.
Then for the expressions p1 == p2 p1 != p2 p1 < p2 p1 <= p2 p1 >= p2 p1 > p2 p1 - p2 either or both objects may be replaced by an equivalently-valued object of type XX​::​const_pointer with no change in semantics.
An allocator may constrain the types on which it can be instantiated and the arguments for which its construct or destroy members may be called.
If a type cannot be used with a particular allocator, the allocator class or the call to construct or destroy may fail to instantiate.
If the alignment associated with a specific over-aligned type is not supported by an allocator, instantiation of the allocator for that type may fail.
The allocator also may silently ignore the requested alignment.
[Note 4: 
Additionally, the member function allocate for that type can fail by throwing an object of type bad_alloc.
— end note]
[Example 2: 
The following is an allocator class template supporting the minimal interface that meets the requirements of [allocator.requirements.general]: template<class T> struct SimpleAllocator { using value_type = T; SimpleAllocator(ctor args); template<class U> SimpleAllocator(const SimpleAllocator<U>& other); T* allocate(std::size_t n); void deallocate(T* p, std::size_t n); template<class U> bool operator==(const SimpleAllocator<U>& rhs) const; };
— end example]
The following exposition-only concept defines the minimal requirements on an Allocator type.
template<class Alloc> concept simple-allocator = requires(Alloc alloc, size_t n) { { *alloc.allocate(n) } -> same_as<typename Alloc::value_type&>; { alloc.deallocate(alloc.allocate(n), n) }; } && copy_constructible<Alloc> && equality_comparable<Alloc>;
A type Alloc models simple-allocator if it meets the requirements of [allocator.requirements.general].

16.4.4.6.2 Allocator completeness requirements [allocator.requirements.completeness]

If X is an allocator class for type T, X additionally meets the allocator completeness requirements if, whether or not T is a complete type:

16.4.5 Constraints on programs [constraints]

16.4.5.1 Overview [constraints.overview]

Subclause [constraints] describes restrictions on C++ programs that use the facilities of the C++ standard library.
The following subclauses specify constraints on the program's use of namespaces, its use of various reserved names, its use of headers, its use of standard library classes as base classes ([derived.classes]), its definitions of replacement functions, and its installation of handler functions during execution.

16.4.5.2 Namespace use [namespace.constraints]

16.4.5.2.1 Namespace std [namespace.std]

Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std.
Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that
  • the added declaration depends on at least one program-defined type, and
  • the specialization meets the standard library requirements for the original template.153
The behavior of a C++ program is undefined if it declares an explicit or partial specialization of any standard library variable template, except where explicitly permitted by the specification of that variable template.
[Note 1: 
The requirements on an explicit or partial specialization are stated by each variable template that grants such permission.
— end note]
The behavior of a C++ program is undefined if it declares
  • an explicit specialization of any member function of a standard library class template, or
  • an explicit specialization of any member function template of a standard library class or class template, or
  • an explicit or partial specialization of any member class template of a standard library class or class template, or
  • a deduction guide for any standard library class template.
A program may explicitly instantiate a class template defined in the standard library only if the declaration
  • depends on the name of at least one program-defined type, and
  • the instantiation meets the standard library requirements for the original template.
Let F denote a standard library function ([global.functions]), a standard library static member function, or an instantiation of a standard library function template.
Unless F is designated an addressable function, the behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer to F.
[Note 2: 
Possible means of forming such pointers include application of the unary & operator ([expr.unary.op]), addressof ([specialized.addressof]), or a function-to-pointer standard conversion ([conv.func]).
— end note]
Moreover, the behavior of a C++ program is unspecified (possibly ill-formed) if it attempts to form a reference to F or if it attempts to form a pointer-to-member designating either a standard library non-static member function ([member.functions]) or an instantiation of a standard library member function template.
A translation unit shall not declare namespace std to be an inline namespace ([namespace.def]).
153)153)
Any library code that instantiates other library templates must be prepared to work adequately with any user-supplied specialization that meets the minimum requirements of this document.

16.4.5.2.2 Namespace posix [namespace.posix]

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace posix or to a namespace within namespace posix unless otherwise specified.
The namespace posix is reserved for use by ISO/IEC/IEEE 9945 and other POSIX standards.

16.4.5.2.3 Namespaces for future standardization [namespace.future]

Top-level namespaces whose namespace-name consists of std followed by one or more digits ([lex.name]) are reserved for future standardization.
The behavior of a C++ program is undefined if it adds declarations or definitions to such a namespace.
[Example 1: 
The top-level namespace std2 is reserved for use by future revisions of this International Standard.
— end example]

16.4.5.3 Reserved names [reserved.names]

16.4.5.3.1 General [reserved.names.general]

The C++ standard library reserves the following kinds of names:
If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by [library], its behavior is undefined.

16.4.5.3.2 Zombie names [zombie.names]

In namespace std, the names shown in Table 38 are reserved for previous standardization:
Table 38 — Zombie names in namespace std[tab:zombie.names.std]
auto_ptr
generate_header
pointer_to_binary_function
auto_ptr_ref
get_pointer_safety
pointer_to_unary_function
binary_function
get_temporary_buffer
ptr_fun
binary_negate
get_unexpected
random_shuffle
bind1st
gets
raw_storage_iterator
bind2nd
is_literal_type
result_of
binder1st
is_literal_type_v
result_of_t
binder2nd
istrstream
return_temporary_buffer
codecvt_mode
little_endian
set_unexpected
codecvt_utf16
mem_fun1_ref_t
strstream
codecvt_utf8
mem_fun1_t
strstreambuf
codecvt_utf8_utf16
mem_fun_ref_t
unary_function
const_mem_fun1_ref_t
mem_fun_ref
unary_negate
const_mem_fun1_t
mem_fun_t
uncaught_exception
const_mem_fun_ref_t
mem_fun
undeclare_no_pointers
const_mem_fun_t
not1
undeclare_reachable
consume_header
not2
unexpected_handler
declare_no_pointers
ostrstream
wbuffer_convert
declare_reachable
pointer_safety
wstring_convert
The names shown in Table 39 are reserved as members for previous standardization, and may not be used as a name for object-like macros in portable code:
Table 39 — Zombie object-like macros [tab:zombie.names.objmacro]
argument_type
op
second_argument_type
first_argument_type
open_mode
seek_dir
io_state
preferred
strict
The names shown in Table 40 are reserved as member functions for previous standardization, and may not be used as a name for function-like macros in portable code:
Table 40 — Zombie function-like macros [tab:zombie.names.fnmacro]
converted
freeze
from_bytes
pcount
stossc
to_bytes
The header names shown in Table 41 are reserved for previous standardization:
Table 41 — Zombie headers [tab:zombie.names.header]
<ccomplex>
<codecvt>
<cstdbool>
<ctgmath>
<strstream>
<ciso646>
<cstdalign>

16.4.5.3.3 Macro names [macro.names]

A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 4, or to the attribute-tokens described in [dcl.attr], except that the names likely and unlikely may be defined as function-like macros ([cpp.replace]).

16.4.5.3.4 External linkage [extern.names]

Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage,154 both in namespace std and in the global namespace.
Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.155
Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage,156 or as a name of namespace scope in the global namespace.
154)154)
The list of such reserved names includes errno, declared or defined in <cerrno>.
155)155)
The list of such reserved function signatures with external linkage includes setjmp(jmp_buf), declared or defined in <csetjmp>, and va_end(va_list), declared or defined in <cstdarg>.
156)156)
The function signatures declared in <cuchar>, <cwchar>, and <cwctype> are always reserved, notwithstanding the restrictions imposed in subclause 4.5.1 of Amendment 1 to the C Standard for these headers.

16.4.5.3.5 Types [extern.types]

For each type T from the C standard library, the types ​::​T and std​::​T are reserved to the implementation and, when defined, ​::​T shall be identical to std​::​T.

16.4.5.3.6 User-defined literal suffixes [usrlit.suffix]

Literal suffix identifiers ([over.literal]) that do not start with an underscore are reserved for future standardization.
Literal suffix identifiers that contain a double underscore __ are reserved for use by C++ implementations.

16.4.5.4 Headers [alt.headers]

If a file with a name equivalent to the derived file name for one of the C++ standard library headers is not provided as part of the implementation, and a file with that name is placed in any of the standard places for a source file to be included, the behavior is undefined.

16.4.5.5 Derived classes [derived.classes]

Virtual member function signatures defined for a base class in the C++ standard library may be overridden in a derived class defined in the program ([class.virtual]).

16.4.5.6 Replacement functions [replacement.functions]

[support] through [exec] and [depr] describe the behavior of numerous functions defined by the C++ standard library.
Under some circumstances, however, certain of these function descriptions also apply to replacement functions defined in the program.
A C++ program may provide the definition for any of the following dynamic memory allocation function signatures declared in header <new> ([basic.stc.dynamic], [new.syn]): operator new(std::size_t) operator new(std::size_t, std::align_val_t) operator new(std::size_t, const std::nothrow_t&) operator new(std::size_t, std::align_val_t, const std::nothrow_t&) operator delete(void*) operator delete(void*, std::size_t) operator delete(void*, std::align_val_t) operator delete(void*, std::size_t, std::align_val_t) operator delete(void*, const std::nothrow_t&) operator delete(void*, std::align_val_t, const std::nothrow_t&) operator new[](std::size_t) operator new[](std::size_t, std::align_val_t) operator new[](std::size_t, const std::nothrow_t&) operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) operator delete[](void*) operator delete[](void*, std::size_t) operator delete[](void*, std::align_val_t) operator delete[](void*, std::size_t, std::align_val_t) operator delete[](void*, const std::nothrow_t&) operator delete[](void*, std::align_val_t, const std::nothrow_t&)
A C++ program may provide the definition of the following function signature declared in header <debugging>: bool std::is_debugger_present() noexcept
The program's definitions are used instead of the default versions supplied by the implementation ([new.delete]).
Such replacement occurs prior to program startup ([basic.def.odr], [basic.start]).
The program's declarations shall not be specified as inline.
No diagnostic is required.

16.4.5.7 Handler functions [handler.functions]

The C++ standard library provides a default version of the following handler function ([support]):
A C++ program may install different handler functions during execution, by supplying a pointer to a function defined in the program or the library as an argument to (respectively): See also subclauses [alloc.errors], Storage allocation errors, and [support.exception], Exception handling.
A C++ program can get a pointer to the current handler function by calling the following functions:
Calling the set_* and get_* functions shall not incur a data race ([intro.races]).
A call to any of the set_* functions shall synchronize with subsequent calls to the same set_* function and to the corresponding get_* function.

16.4.5.8 Other functions [res.on.functions]

In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program.
If these components do not meet their requirements, this document places no requirements on the implementation.
In particular, the behavior is undefined in the following cases:
  • For replacement functions ([new.delete]), if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph.
  • For handler functions ([new.handler], [terminate.handler]), if the installed handler function does not implement the semantics of the applicable Required behavior: paragraph.
  • 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 Requirements subclause ([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.
  • If any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.
  • If an incomplete type ([basic.types.general]) is used as a template argument when instantiating a template component or evaluating a concept, unless specifically allowed for that component.

16.4.5.9 Function arguments [res.on.arguments]

Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
  • If an argument to a function has an invalid value (such as a value outside the domain of the function or a pointer invalid for its intended use), the behavior is undefined.
  • If a function argument is described as being an array, the pointer actually passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are in fact valid.
  • If a function argument is bound to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument, except that the argument passed to a move assignment operator may be a reference to *this ([lib.types.movedfrom]).
    [Note 1: 
    If the type of a parameter is a forwarding reference ([temp.deduct.call]) that is deduced to an lvalue reference type, then the argument is not bound to an rvalue reference.
    — end note]
    [Note 2: 
    If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g., by calling the function with the argument std​::​move(x)), the program is effectively asking that function to treat that lvalue as a temporary object.
    The implementation is free to optimize away aliasing checks which would possibly be needed if the argument was an lvalue.
    — end note]

16.4.5.10 Library object access [res.on.objects]

The behavior of a program is undefined if calls to standard library functions from different threads may introduce a data race.
The conditions under which this may occur are specified in [res.on.data.races].
[Note 1: 
Modifying an object of a standard library type that is shared between threads risks undefined behavior unless objects of that type are explicitly specified as being shareable without data races or the user supplies a locking mechanism.
— end note]
If an object of a standard library type is accessed, and the beginning of the object's lifetime does not happen before the access, or the access does not happen before the end of the object's lifetime, the behavior is undefined unless otherwise specified.
[Note 2: 
This applies even to objects such as mutexes intended for thread synchronization.
— end note]

16.4.5.11 Semantic requirements [res.on.requirements]

A sequence Args of template arguments is said to model a concept C if Args satisfies C ([temp.constr.decl]) and meets all semantic requirements (if any) given in the specification of C.
If the validity or meaning of a program depends on whether a sequence of template arguments models a concept, and the concept is satisfied but not modeled, the program is ill-formed, no diagnostic required.
If the semantic requirements of a declaration's constraints ([structure.requirements]) are not modeled at the point of use, the program is ill-formed, no diagnostic required.

16.4.6 Conforming implementations [conforming]

16.4.6.1 Overview [conforming.overview]

Subclause [conforming] describes the constraints upon, and latitude of, implementations of the C++ standard library.
An implementation's use of headers is discussed in [res.on.headers], its use of macros in [res.on.macro.definitions], non-member functions in [global.functions], member functions in [member.functions], data race avoidance in [res.on.data.races], access specifiers in [protection.within.classes], class derivation in [derivation], and exceptions in [res.on.exception.handling].

16.4.6.2 Headers [res.on.headers]

A C++ header may include other C++ headers.
A C++ header shall provide the declarations and definitions that appear in its synopsis.
A C++ header shown in its synopsis as including other C++ headers shall provide the declarations and definitions that appear in the synopses of those other headers.
Certain types and macros are defined in more than one header.
Every such entity shall be defined such that any header that defines it may be included after any other header that also defines it ([basic.def.odr]).
The C standard library headers shall include only their corresponding C++ standard library header, as described in [headers].

16.4.6.3 Restrictions on macro definitions [res.on.macro.definitions]

The names and global function signatures described in [contents] are reserved to the implementation.
All object-like macros defined by the C standard library and described in this Clause as expanding to integral constant expressions are also suitable for use in #if preprocessing directives, unless explicitly stated otherwise.

16.4.6.4 Non-member functions [global.functions]

It is unspecified whether any non-member functions in the C++ standard library are defined as inline.
A call to a non-member function signature described in [support] through [exec] and [depr] shall behave as if the implementation declared no additional non-member function signatures.157
An implementation shall not declare a non-member function signature with additional default arguments.
Unless otherwise specified, calls made by functions in the standard library to non-operator, non-member functions do not use functions from another namespace which are found through argument-dependent name lookup ([basic.lookup.argdep]).
[Note 1: 
The phrase “unless otherwise specified” applies to cases such as the swappable with requirements ([swappable.requirements]).
The exception for overloaded operators allows argument-dependent lookup in cases like that of ostream_iterator​::​operator=:
Effects: *out_stream << value; if (delim != 0) *out_stream << delim; return *this;
— end note]
157)157)
A valid C++ program always calls the expected library non-member function.
An implementation can also define additional non-member functions that would otherwise not be called by a valid C++ program.

16.4.6.5 Member functions [member.functions]

It is unspecified whether any member functions in the C++ standard library are defined as inline.
For a non-virtual member function described in the C++ standard library, an implementation may declare a different set of member function signatures, provided that any call to the member function that would select an overload from the set of declarations described in this document behaves as if that overload were selected.
[Note 1: 
For instance, an implementation can add parameters with default values, or replace a member function with default arguments with two or more member functions with equivalent behavior, or add additional signatures for a member function name.
— end note]

16.4.6.6 Friend functions [hidden.friends]

Whenever this document specifies a friend declaration of a function or function template within a class or class template definition, that declaration shall be the only declaration of that function or function template provided by an implementation.
[Note 1: 
In particular, a conforming implementation does not provide any additional declarations of that function or function template at namespace scope.
— end note]
[Note 2: 
Such a friend function or function template declaration is known as a hidden friend, as it is visible neither to ordinary unqualified lookup ([basic.lookup.unqual]) nor to qualified lookup ([basic.lookup.qual]).
— end note]

16.4.6.7 Constexpr functions and constructors [constexpr.functions]

This document explicitly requires that certain standard library functions are constexpr ([dcl.constexpr]).
An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.
Within any header that provides any non-defining declarations of constexpr functions or constructors an implementation shall provide corresponding definitions.

16.4.6.8 Requirements for stable algorithms [algorithm.stable]

When the requirements for an algorithm state that it is “stable” without further elaboration, it means:
  • For the sort algorithms the relative order of equivalent elements is preserved.
  • For the remove and copy algorithms the relative order of the elements that are not removed is preserved.
  • For the merge algorithms, for equivalent elements in the original two ranges, the elements from the first range (preserving their original order) precede the elements from the second range (preserving their original order).

16.4.6.9 Reentrancy [reentrancy]

Except where explicitly specified in this document, it is implementation-defined which functions in the C++ standard library may be recursively reentered.

16.4.6.10 Data race avoidance [res.on.data.races]

This subclause specifies requirements that implementations shall meet to prevent data races.
Every standard library function shall meet each requirement unless otherwise specified.
Implementations may prevent data races in cases other than those specified below.
A C++ standard library function shall not directly or indirectly access objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's arguments, including this.
A C++ standard library function shall not directly or indirectly modify objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's non-const arguments, including this.
[Note 1: 
This means, for example, that implementations can't use an object with static storage duration for internal purposes without synchronization because doing so can cause a data race even in programs that do not explicitly share objects between threads.
— end note]
A C++ standard library function shall not access objects indirectly accessible via its arguments or via elements of its container arguments except by invoking functions required by its specification on those container elements.
Operations on iterators obtained by calling a standard library container or string member function may access the underlying container, but shall not modify it.
[Note 2: 
In particular, container operations that invalidate iterators conflict with operations on iterators associated with that container.
— end note]
Implementations may share their own internal objects between threads if the objects are not visible to users and are protected against data races.
Unless otherwise specified, C++ standard library functions shall perform all operations solely within the current thread if those operations have effects that are visible to users.
[Note 3: 
This allows implementations to parallelize operations if there are no visible side effects.
— end note]

16.4.6.11 Protection within classes [protection.within.classes]

It is unspecified whether any function signature or class described in [support] through [exec] and [depr] is a friend of another class in the C++ standard library.

16.4.6.12 Derived classes [derivation]

An implementation may derive any class in the C++ standard library from a class with a name reserved to the implementation.
Certain classes defined in the C++ standard library are required to be derived from other classes in the C++ standard library.
An implementation may derive such a class directly from the required base or indirectly through a hierarchy of base classes with names reserved to the implementation.
In any case:
  • Every base class described as virtual shall be virtual;
  • Every base class not specified as virtual shall not be virtual;
  • Unless explicitly stated otherwise, types with distinct names shall be distinct types.
    [Note 1: 
    There is an implicit exception to this rule for types that are described as synonyms ([dcl.typedef], [namespace.udecl]), such as size_t ([support.types]) and streamoff ([stream.types]).
    — end note]
All types specified in the C++ standard library shall be non-final types unless otherwise specified.

16.4.6.13 Restrictions on exception handling [res.on.exception.handling]

Any of the functions defined in the C++ standard library can report a failure by throwing an exception of a type described in its Throws: paragraph, or of a type derived from a type named in the Throws: paragraph that would be caught by a handler ([except.handle]) for the base type.
Functions from the C standard library shall not throw exceptions158 except when such a function calls a program-supplied function that throws an exception.159
Destructor operations defined in the C++ standard library shall not throw exceptions.
Every destructor in the C++ standard library shall behave as if it had a non-throwing exception specification ([except.spec]).
Functions defined in the C++ standard library that do not have a Throws: paragraph but do have a potentially-throwing exception specification may throw implementation-defined exceptions.160
Implementations should report errors by throwing exceptions of or derived from the standard exception classes ([bad.alloc], [support.exception], [std.exceptions]).
An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
158)158)
That is, the C standard library functions can all be treated as if they are marked noexcept.
This allows implementations to make performance optimizations based on the absence of exceptions at runtime.
159)159)
The functions qsort() and bsearch() ([alg.c.library]) meet this condition.
160)160)
In particular, they can report a failure to allocate storage by throwing an exception of type bad_alloc, or a class derived from bad_alloc ([bad.alloc]).

16.4.6.14 Value of error codes [value.error.codes]

Certain functions in the C++ standard library report errors via a std​::​error_code object.
That object's category() member shall return std​::​system_category() for errors originating from the operating system, or a reference to an implementation-defined error_category object for errors originating elsewhere.
The implementation shall define the possible values of value() for each of these error categories.
[Example 1: 
For operating systems that are based on POSIX, implementations should define the std​::​system_category() values as identical to the POSIX errno values, with additional values as defined by the operating system's documentation.
Implementations for operating systems that are not based on POSIX should define values identical to the operating system's values.
For errors that do not originate from the operating system, the implementation may provide enums for the associated values.
— end example]

16.4.6.15 Moved-from state of library types [lib.types.movedfrom]

Objects of types defined in the C++ standard library may be moved from ([class.copy.ctor]).
Move operations may be explicitly specified or implicitly generated.
Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state ([defns.valid]).
An object of a type defined in the C++ standard library may be move-assigned ([class.copy.assign]) to itself.
Unless otherwise specified, such an assignment places the object in a valid but unspecified state.

17 Language support library [support]

17.1 General [support.general]

This Clause describes the function signatures that are called implicitly, and the types of objects generated implicitly, during the execution of some C++ programs.
It also describes the headers that declare these function signatures and define any related types.
The following subclauses describe common type definitions used throughout the library, characteristics of the predefined types, functions supporting start and termination of a C++ program, support for dynamic memory management, support for dynamic type identification, support for exception processing, support for initializer lists, and other runtime support, as summarized in Table 42.
Table 42 — Language support library summary [tab:support.summary]
Subclause
Header
Common definitions
<cstddef>, <cstdlib>
Implementation properties
<cfloat>, <climits>, <limits>, <version>
Arithmetic types
<cstdint>, <stdfloat>
Start and termination
<cstdlib>
Dynamic memory management
<new>
Type identification
<typeinfo>, <typeindex>
Source location
<source_location>
Exception handling
<exception>
Initializer lists
<initializer_list>
Comparisons
<compare>
Coroutines
<coroutine>
Other runtime support
<csetjmp>, <csignal>, <cstdarg>, <cstdlib>

17.2 Common definitions [support.types]

17.2.1 Header <cstddef> synopsis [cstddef.syn]

// all freestanding namespace std { using ptrdiff_t = see below; using size_t = see below; using max_align_t = see below; using nullptr_t = decltype(nullptr); enum class byte : unsigned char {}; // [support.types.byteops], byte type operations template<class IntType> constexpr byte& operator<<=(byte& b, IntType shift) noexcept; template<class IntType> constexpr byte operator<<(byte b, IntType shift) noexcept; template<class IntType> constexpr byte& operator>>=(byte& b, IntType shift) noexcept; template<class IntType> constexpr byte operator>>(byte b, IntType shift) noexcept; constexpr byte& operator|=(byte& l, byte r) noexcept; constexpr byte operator|(byte l, byte r) noexcept; constexpr byte& operator&=(byte& l, byte r) noexcept; constexpr byte operator&(byte l, byte r) noexcept; constexpr byte& operator^=(byte& l, byte r) noexcept; constexpr byte operator^(byte l, byte r) noexcept; constexpr byte operator~(byte b) noexcept; template<class IntType> constexpr IntType to_integer(byte b) noexcept; } #define NULL see below #define offsetof(P, D) see below
The contents and meaning of the header <cstddef> are the same as the C standard library header <stddef.h>, except that it does not declare the type wchar_t, that it also declares the type byte and its associated operations ([support.types.byteops]), and as noted in [support.types.nullptr] and [support.types.layout].
See also: ISO/IEC 9899:2018, 7.19

17.2.2 Header <cstdlib> synopsis [cstdlib.syn]

namespace std { using size_t = see below; // freestanding using div_t = see below; // freestanding using ldiv_t = see below; // freestanding using lldiv_t = see below; // freestanding } #define NULL see below // freestanding #define EXIT_FAILURE see below // freestanding #define EXIT_SUCCESS see below // freestanding #define RAND_MAX see below #define MB_CUR_MAX see below namespace std { // Exposition-only function type aliases extern "C" using c-atexit-handler = void(); // exposition only extern "C++" using atexit-handler = void(); // exposition only extern "C" using c-compare-pred = int(const void*, const void*); // exposition only extern "C++" using compare-pred = int(const void*, const void*); // exposition only // [support.start.term], start and termination [[noreturn]] void abort() noexcept; // freestanding int atexit(c-atexit-handler* func) noexcept; // freestanding int atexit(atexit-handler* func) noexcept; // freestanding int at_quick_exit(c-atexit-handler* func) noexcept; // freestanding int at_quick_exit(atexit-handler* func) noexcept; // freestanding [[noreturn]] void exit(int status); // freestanding [[noreturn]] void _Exit(int status) noexcept; // freestanding [[noreturn]] void quick_exit(int status) noexcept; // freestanding char* getenv(const char* name); int system(const char* string); // [c.malloc], C library memory allocation void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void free(void* ptr); void* malloc(size_t size); void* realloc(void* ptr, size_t size); double atof(const char* nptr); int atoi(const char* nptr); long int atol(const char* nptr); long long int atoll(const char* nptr); double strtod(const char* nptr, char** endptr); float strtof(const char* nptr, char** endptr); long double strtold(const char* nptr, char** endptr); long int strtol(const char* nptr, char** endptr, int base); long long int strtoll(const char* nptr, char** endptr, int base); unsigned long int strtoul(const char* nptr, char** endptr, int base); unsigned long long int strtoull(const char* nptr, char** endptr, int base); // [c.mb.wcs], multibyte / wide string and character conversion functions int mblen(const char* s, size_t n); int mbtowc(wchar_t* pwc, const char* s, size_t n); int wctomb(char* s, wchar_t wchar); size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); size_t wcstombs(char* s, const wchar_t* pwcs, size_t n); // [alg.c.library], C standard library algorithms void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, // freestanding c-compare-pred* compar); void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, // freestanding compare-pred* compar); void qsort(void* base, size_t nmemb, size_t size, c-compare-pred* compar); // freestanding void qsort(void* base, size_t nmemb, size_t size, compare-pred* compar); // freestanding // [c.math.rand], low-quality random number generation int rand(); void srand(unsigned int seed); // [c.math.abs], absolute values constexpr int abs(int j); // freestanding constexpr long int abs(long int j); // freestanding constexpr long long int abs(long long int j); // freestanding constexpr floating-point-type abs(floating-point-type j); // freestanding-deleted constexpr long int labs(long int j); // freestanding constexpr long long int llabs(long long int j); // freestanding constexpr div_t div(int numer, int denom); // freestanding constexpr ldiv_t div(long int numer, long int denom); // freestanding; see [library.c] constexpr lldiv_t div(long long int numer, long long int denom); // freestanding; see [library.c] constexpr ldiv_t ldiv(long int numer, long int denom); // freestanding constexpr lldiv_t lldiv(long long int numer, long long int denom); // freestanding }
The contents and meaning of the header <cstdlib> are the same as the C standard library header <stdlib.h>, except that it does not declare the type wchar_t, and except as noted in [support.types.nullptr], [support.types.layout], [support.start.term], [c.malloc], [c.mb.wcs], [alg.c.library], [c.math.rand], and [c.math.abs].
[Note 1: 
Several functions have additional overloads in this document, but they have the same behavior as in the C standard library.
— end note]
See also: ISO/IEC 9899:2018, 7.22

17.2.3 Null pointers [support.types.nullptr]

The type nullptr_t is a synonym for the type of a nullptr expression, and it has the characteristics described in [basic.fundamental] and [conv.ptr].
[Note 1: 
Although nullptr's address cannot be taken, the address of another nullptr_t object that is an lvalue can be taken.
— end note]
The macro NULL is an implementation-defined null pointer constant.161
See also: ISO/IEC 9899:2018, 7.19
161)161)
Possible definitions include 0 and 0L, but not (void*)0.

17.2.4 Sizes, alignments, and offsets [support.types.layout]

The macro offsetof(type, member-designator) has the same semantics as the corresponding macro in the C standard library header <stddef.h>, but accepts a restricted set of type arguments in this document.
Use of the offsetof macro with a type other than a standard-layout class ([class.prop]) is conditionally-supported.162
The expression offsetof(type, member-designator) is never type-dependent and it is value-dependent if and only if type is dependent.
The result of applying the offsetof macro to a static data member or a function member is undefined.
No operation invoked by the offsetof macro shall throw an exception and noexcept(offsetof(type, member-designator)) shall be true.
The type ptrdiff_t is an implementation-defined signed integer type that can hold the difference of two subscripts in an array object, as described in [expr.add].
The type size_t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object ([expr.sizeof]).
Recommended practice: An implementation should choose types for ptrdiff_t and size_t whose integer conversion ranks ([conv.rank]) are no greater than that of signed long int unless a larger size is necessary to contain all the possible values.
The type max_align_t is a trivially copyable standard-layout type whose alignment requirement is at least as great as that of every scalar type, and whose alignment requirement is supported in every context ([basic.align]).
std​::​is_trivially_default_constructible_v<max_align_t> is true.
See also: ISO/IEC 9899:2018, 7.19
162)162)
Note that offsetof is required to work as specified even if unary operator& is overloaded for any of the types involved.

17.2.5 byte type operations [support.types.byteops]

template<class IntType> constexpr byte& operator<<=(byte& b, IntType shift) noexcept;
Constraints: is_integral_v<IntType> is true.
Effects: Equivalent to: return b = b << shift;
template<class IntType> constexpr byte operator<<(byte b, IntType shift) noexcept;
Constraints: is_integral_v<IntType> is true.
Effects: Equivalent to: return static_cast<byte>(static_cast<unsigned int>(b) << shift);
template<class IntType> constexpr byte& operator>>=(byte& b, IntType shift) noexcept;
Constraints: is_integral_v<IntType> is true.
Effects: Equivalent to: return b = b >> shift;
template<class IntType> constexpr byte operator>>(byte b, IntType shift) noexcept;
Constraints: is_integral_v<IntType> is true.
Effects: Equivalent to: return static_cast<byte>(static_cast<unsigned int>(b) >> shift);
constexpr byte& operator|=(byte& l, byte r) noexcept;
Effects: Equivalent to: return l = l | r;
constexpr byte operator|(byte l, byte r) noexcept;
Effects: Equivalent to: return static_cast<byte>(static_cast<unsigned int>(l) | static_cast<unsigned int>(r));
constexpr byte& operator&=(byte& l, byte r) noexcept;
Effects: Equivalent to: return l = l & r;
constexpr byte operator&(byte l, byte r) noexcept;
Effects: Equivalent to: return static_cast<byte>(static_cast<unsigned int>(l) & static_cast<unsigned int>(r));
constexpr byte& operator^=(byte& l, byte r) noexcept;
Effects: Equivalent to: return l = l ^ r;
constexpr byte operator^(byte l, byte r) noexcept;
Effects: Equivalent to: return static_cast<byte>(static_cast<unsigned int>(l) ^ static_cast<unsigned int>(r));
constexpr byte operator~(byte b) noexcept;
Effects: Equivalent to: return static_cast<byte>(~static_cast<unsigned int>(b));
template<class IntType> constexpr IntType to_integer(byte b) noexcept;
Constraints: is_integral_v<IntType> is true.
Effects: Equivalent to: return static_cast<IntType>(b);

17.3 Implementation properties [support.limits]

17.3.1 General [support.limits.general]

The headers <limits>, <climits>, and <cfloat> supply characteristics of implementation-dependent arithmetic types ([basic.fundamental]).

17.3.2 Header <version> synopsis [version.syn]

The header <version> supplies implementation-dependent information about the C++ standard library (e.g., version number and release date).
Each of the macros defined in <version> is also defined after inclusion of any member of the set of library headers indicated in the corresponding comment in this synopsis.
[Note 1: 
Future revisions of this document might replace the values of these macros with greater values.
— end note]
#define __cpp_lib_adaptor_iterator_pair_constructor 202106L // also in <stack>, <queue> #define __cpp_lib_addressof_constexpr 201603L // freestanding, also in <memory> #define __cpp_lib_algorithm_default_value_type 202403L // also in <algorithm>, <ranges>, <string>, <deque>, <list>, <forward_list>, <vector> #define __cpp_lib_algorithm_iterator_requirements 202207L // also in <algorithm>, <numeric>, <memory> #define __cpp_lib_aligned_accessor 202411L // also in <mdspan> #define __cpp_lib_allocate_at_least 202302L // also in <memory> #define __cpp_lib_allocator_traits_is_always_equal 201411L // freestanding, also in <memory>, <scoped_allocator>, <string>, <deque>, <forward_list>, <list>, // <vector>, <map>, <set>, <unordered_map>, <unordered_set> #define __cpp_lib_any 201606L // also in <any> #define __cpp_lib_apply 201603L // freestanding, also in <tuple> #define __cpp_lib_array_constexpr 201811L // also in <iterator>, <array> #define __cpp_lib_as_const 201510L // freestanding, also in <utility> #define __cpp_lib_associative_heterogeneous_erasure 202110L // also in <map>, <set>, <unordered_map>, <unordered_set> #define __cpp_lib_associative_heterogeneous_insertion 202306L // also in <map>, <set>, <unordered_map>, <unordered_set> #define __cpp_lib_assume_aligned 201811L // freestanding, also in <memory> #define __cpp_lib_atomic_flag_test 201907L // freestanding, also in <atomic> #define __cpp_lib_atomic_float 201711L // freestanding, also in <atomic> #define __cpp_lib_atomic_is_always_lock_free 201603L // freestanding, also in <atomic> #define __cpp_lib_atomic_lock_free_type_aliases 201907L // also in <atomic> #define __cpp_lib_atomic_min_max 202403L // freestanding, also in <atomic> #define __cpp_lib_atomic_ref 202411L // freestanding, also in <atomic> #define __cpp_lib_atomic_shared_ptr 201711L // also in <memory> #define __cpp_lib_atomic_value_initialization 201911L // freestanding, also in <atomic>, <memory> #define __cpp_lib_atomic_wait 201907L // freestanding, also in <atomic> #define __cpp_lib_barrier 202302L // also in <barrier> #define __cpp_lib_bind_back 202306L // freestanding, also in <functional> #define __cpp_lib_bind_front 202306L // freestanding, also in <functional> #define __cpp_lib_bit_cast 201806L // freestanding, also in <bit> #define __cpp_lib_bitops 201907L // freestanding, also in <bit> #define __cpp_lib_bitset 202306L // also in <bitset> #define __cpp_lib_bool_constant 201505L // freestanding, also in <type_traits> #define __cpp_lib_bounded_array_traits 201902L // freestanding, also in <type_traits> #define __cpp_lib_boyer_moore_searcher 201603L // also in <functional> #define __cpp_lib_byte 201603L // freestanding, also in <cstddef> #define __cpp_lib_byteswap 202110L // freestanding, also in <bit> #define __cpp_lib_char8_t 201907L // freestanding, also in <atomic>, <filesystem>, <istream>, <limits>, <locale>, <ostream>, <string>, // <string_view> #define __cpp_lib_chrono 202306L // also in <chrono> #define __cpp_lib_chrono_udls 201304L // also in <chrono> #define __cpp_lib_clamp 201603L // also in <algorithm> #define __cpp_lib_common_reference 202302L // freestanding, also in <type_traits> #define __cpp_lib_common_reference_wrapper 202302L // freestanding, also in <functional> #define __cpp_lib_complex_udls 201309L // also in <complex> #define __cpp_lib_concepts 202207L // freestanding, also in <concepts>, <compare> #define __cpp_lib_constexpr_algorithms 202306L // also in <algorithm>, <utility> #define __cpp_lib_constexpr_atomic 202411L // also in <atomic> #define __cpp_lib_constexpr_bitset 202207L // also in <bitset> #define __cpp_lib_constexpr_charconv 202207L // freestanding, also in <charconv> #define __cpp_lib_constexpr_cmath 202306L // also in <cmath>, <cstdlib> #define __cpp_lib_constexpr_complex 202306L // also in <complex> #define __cpp_lib_constexpr_dynamic_alloc 201907L // also in <memory> #define __cpp_lib_constexpr_exceptions 202411L // also in <exception> #define __cpp_lib_constexpr_functional 201907L // freestanding, also in <functional> #define __cpp_lib_constexpr_iterator 201811L // freestanding, also in <iterator> #define __cpp_lib_constexpr_memory 202202L // freestanding, also in <memory> #define __cpp_lib_constexpr_new 202406L // freestanding, also in <new> #define __cpp_lib_constexpr_numeric 201911L // also in <numeric> #define __cpp_lib_constexpr_string 201907L // also in <string> #define __cpp_lib_constexpr_string_view 201811L // also in <string_view> #define __cpp_lib_constexpr_tuple 201811L // freestanding, also in <tuple> #define __cpp_lib_constexpr_typeinfo 202106L // freestanding, also in <typeinfo> #define __cpp_lib_constexpr_utility 201811L // freestanding, also in <utility> #define __cpp_lib_constexpr_vector 201907L // also in <vector> #define __cpp_lib_constrained_equality 202411L // freestanding, // also in <utility>, <tuple>, <optional>, <variant>, <expected> #define __cpp_lib_containers_ranges 202202L // also in <vector>, <list>, <forward_list>, <map>, <set>, <unordered_map>, <unordered_set>, // <deque>, <queue>, <stack>, <string> #define __cpp_lib_copyable_function 202306L // also in <functional> #define __cpp_lib_coroutine 201902L // freestanding, also in <coroutine> #define __cpp_lib_debugging 202403L // freestanding, also in <debugging> #define __cpp_lib_destroying_delete 201806L // freestanding, also in <new> #define __cpp_lib_enable_shared_from_this 201603L // also in <memory> #define __cpp_lib_endian 201907L // freestanding, also in <bit> #define __cpp_lib_erase_if 202002L // also in <string>, <deque>, <forward_list>, <list>, <vector>, <map>, <set>, <unordered_map>, // <unordered_set> #define __cpp_lib_exchange_function 201304L // freestanding, also in <utility> #define __cpp_lib_execution 201902L // also in <execution> #define __cpp_lib_expected 202211L // also in <expected> #define __cpp_lib_filesystem 201703L // also in <filesystem> #define __cpp_lib_flat_map 202207L // also in <flat_map> #define __cpp_lib_flat_set 202207L // also in <flat_set> #define __cpp_lib_format 202311L // also in <format> #define __cpp_lib_format_ranges 202207L // also in <format> #define __cpp_lib_format_path 202403L // also in <filesystem> #define __cpp_lib_format_uchar 202311L // also in <format> #define __cpp_lib_formatters 202302L // also in <stacktrace>, <thread> #define __cpp_lib_forward_like 202207L // freestanding, also in <utility> #define __cpp_lib_freestanding_algorithm 202311L // freestanding, also in <algorithm> #define __cpp_lib_freestanding_array 202311L // freestanding, also in <array> #define __cpp_lib_freestanding_char_traits 202306L // freestanding, also in <string> #define __cpp_lib_freestanding_charconv 202306L // freestanding, also in <charconv> #define __cpp_lib_freestanding_cstdlib 202306L // freestanding, also in <cstdlib>, <cmath> #define __cpp_lib_freestanding_cstring 202311L // freestanding, also in <cstring> #define __cpp_lib_freestanding_cwchar 202306L // freestanding, also in <cwchar> #define __cpp_lib_freestanding_errc 202306L // freestanding, also in <cerrno>, <system_error> #define __cpp_lib_freestanding_expected 202311L // freestanding, also in <expected> #define __cpp_lib_freestanding_feature_test_macros 202306L // freestanding #define __cpp_lib_freestanding_functional 202306L // freestanding, also in <functional> #define __cpp_lib_freestanding_iterator 202306L // freestanding, also in <iterator> #define __cpp_lib_freestanding_mdspan 202311L // freestanding, also in <mdspan> #define __cpp_lib_freestanding_memory 202306L // freestanding, also in <memory> #define __cpp_lib_freestanding_numeric 202311L // freestanding, also in <numeric> #define __cpp_lib_freestanding_operator_new see below // freestanding, also in <new> #define __cpp_lib_freestanding_optional 202311L // freestanding, also in <optional> #define __cpp_lib_freestanding_ranges 202306L // freestanding, also in <ranges> #define __cpp_lib_freestanding_ratio 202306L // freestanding, also in <ratio> #define __cpp_lib_freestanding_string_view 202311L // freestanding, also in <string_view> #define __cpp_lib_freestanding_tuple 202306L // freestanding, also in <tuple> #define __cpp_lib_freestanding_utility 202306L // freestanding, also in <utility> #define __cpp_lib_freestanding_variant 202311L // freestanding, also in <variant> #define __cpp_lib_fstream_native_handle 202306L // also in <fstream> #define __cpp_lib_function_ref 202306L // also in <functional> #define __cpp_lib_gcd_lcm 201606L // also in <numeric> #define __cpp_lib_generator 202207L // also in <generator> #define __cpp_lib_generic_associative_lookup 201304L // also in <map>, <set> #define __cpp_lib_generic_unordered_lookup 201811L // also in <unordered_map>, <unordered_set> #define __cpp_lib_hardware_interference_size 201703L // freestanding, also in <new> #define __cpp_lib_has_unique_object_representations 201606L // freestanding, also in <type_traits> #define __cpp_lib_hazard_pointer 202306L // also in <hazard_pointer> #define __cpp_lib_hypot 201603L // also in <cmath> #define __cpp_lib_incomplete_container_elements 201505L // also in <forward_list>, <list>, <vector> #define __cpp_lib_inplace_vector 202406L // also in <inplace_vector> #define __cpp_lib_int_pow2 202002L // freestanding, also in <bit> #define __cpp_lib_integer_comparison_functions 202002L // also in <utility> #define __cpp_lib_integer_sequence 201304L // freestanding, also in <utility> #define __cpp_lib_integral_constant_callable 201304L // freestanding, also in <type_traits> #define __cpp_lib_interpolate 201902L // also in <cmath>, <numeric> #define __cpp_lib_invoke 201411L // freestanding, also in <functional> #define __cpp_lib_invoke_r 202106L // freestanding, also in <functional> #define __cpp_lib_ios_noreplace 202207L // also in <ios> #define __cpp_lib_is_aggregate 201703L // freestanding, also in <type_traits> #define __cpp_lib_is_constant_evaluated 201811L // freestanding, also in <type_traits> #define __cpp_lib_is_final 201402L // freestanding, also in <type_traits> #define __cpp_lib_is_implicit_lifetime 202302L // freestanding, also in <type_traits> #define __cpp_lib_is_invocable 201703L // freestanding, also in <type_traits> #define __cpp_lib_is_layout_compatible 201907L // freestanding, also in <type_traits> #define __cpp_lib_is_nothrow_convertible 201806L // freestanding, also in <type_traits> #define __cpp_lib_is_null_pointer 201309L // freestanding, also in <type_traits> #define __cpp_lib_is_pointer_interconvertible 201907L // freestanding, also in <type_traits> #define __cpp_lib_is_scoped_enum 202011L // freestanding, also in <type_traits> #define __cpp_lib_is_sufficiently_aligned 202411L // also in <memory> #define __cpp_lib_is_swappable 201603L // freestanding, also in <type_traits> #define __cpp_lib_is_virtual_base_of 202406L // freestanding, also in <type_traits> #define __cpp_lib_is_within_lifetime 202306L // freestanding, also in <type_traits> #define __cpp_lib_jthread 201911L // also in <stop_token>, <thread> #define __cpp_lib_latch 201907L // also in <latch> #define __cpp_lib_launder 201606L // freestanding, also in <new> #define __cpp_lib_linalg 202412L // also in <linalg> #define __cpp_lib_list_remove_return_type 201806L // also in <forward_list>, <list> #define __cpp_lib_logical_traits 201510L // freestanding, also in <type_traits> #define __cpp_lib_make_from_tuple 201606L // freestanding, also in <tuple> #define __cpp_lib_make_reverse_iterator 201402L // freestanding, also in <iterator> #define __cpp_lib_make_unique 201304L // also in <memory> #define __cpp_lib_map_try_emplace 201411L // also in <map> #define __cpp_lib_math_constants 201907L // also in <numbers> #define __cpp_lib_math_special_functions 201603L // also in <cmath> #define __cpp_lib_mdspan 202406L // freestanding, also in <mdspan> #define __cpp_lib_memory_resource 201603L // also in <memory_resource> #define __cpp_lib_modules 202207L // freestanding #define __cpp_lib_move_iterator_concept 202207L // freestanding, also in <iterator> #define __cpp_lib_move_only_function 202110L // also in <functional> #define __cpp_lib_node_extract 201606L // also in <map>, <set>, <unordered_map>, <unordered_set> #define __cpp_lib_nonmember_container_access 201411L // freestanding, also in <array>, <deque>, <forward_list>, <iterator>, <list>, <map>, <regex>, <set>, // <string>, <unordered_map>, <unordered_set>, <vector> #define __cpp_lib_not_fn 202306L // freestanding, also in <functional> #define __cpp_lib_null_iterators 201304L // freestanding, also in <iterator> #define __cpp_lib_optional 202110L // also in <optional> #define __cpp_lib_optional_range_support 202406L // freestanding, also in <optional> #define __cpp_lib_out_ptr 202311L // freestanding, also in <memory> #define __cpp_lib_parallel_algorithm 201603L // also in <algorithm>, <numeric> #define __cpp_lib_philox_engine 202406L // also in <random> #define __cpp_lib_polymorphic_allocator 201902L // also in <memory_resource> #define __cpp_lib_print 202406L // also in <print>, <ostream> #define __cpp_lib_quoted_string_io 201304L // also in <iomanip> #define __cpp_lib_ranges 202406L // also in <algorithm>, <functional>, <iterator>, <memory>, <ranges> #define __cpp_lib_ranges_as_const 202311L // freestanding, also in <ranges> #define __cpp_lib_ranges_as_rvalue 202207L // freestanding, also in <ranges> #define __cpp_lib_ranges_cache_latest 202411L // also in <ranges> #define __cpp_lib_ranges_cartesian_product 202207L // freestanding, also in <ranges> #define __cpp_lib_ranges_chunk 202202L // freestanding, also in <ranges> #define __cpp_lib_ranges_chunk_by 202202L // freestanding, also in <ranges> #define __cpp_lib_ranges_concat 202403L // freestanding, also in <ranges> #define __cpp_lib_ranges_contains 202207L // also in <algorithm> #define __cpp_lib_ranges_enumerate 202302L // also in <ranges> #define __cpp_lib_ranges_find_last 202207L // also in <algorithm> #define __cpp_lib_ranges_fold 202207L // also in <algorithm> #define __cpp_lib_ranges_generate_random 202403L // also in <random> #define __cpp_lib_ranges_iota 202202L // also in <numeric> #define __cpp_lib_ranges_join_with 202202L // freestanding, also in <ranges> #define __cpp_lib_ranges_repeat 202207L // freestanding, also in <ranges> #define __cpp_lib_ranges_slide 202202L // freestanding, also in <ranges> #define __cpp_lib_ranges_starts_ends_with 202106L // also in <algorithm> #define __cpp_lib_ranges_stride 202207L // freestanding, also in <ranges> #define __cpp_lib_ranges_to_container 202202L // freestanding, also in <ranges> #define __cpp_lib_ranges_zip 202110L // freestanding, also in <ranges>, <tuple>, <utility> #define __cpp_lib_ratio 202306L // freestanding, also in <ratio> #define __cpp_lib_raw_memory_algorithms 202411L // also in <memory> #define __cpp_lib_rcu 202306L // also in <rcu> #define __cpp_lib_reference_from_temporary 202202L // freestanding, also in <type_traits> #define __cpp_lib_reference_wrapper 202403L // freestanding, also in <functional> #define __cpp_lib_remove_cvref 201711L // freestanding, also in <type_traits> #define __cpp_lib_result_of_sfinae 201210L // freestanding, also in <functional>, <type_traits> #define __cpp_lib_robust_nonmodifying_seq_ops 201304L // also in <algorithm> #define __cpp_lib_sample 201603L // also in <algorithm> #define __cpp_lib_saturation_arithmetic 202311L // also in <numeric> #define __cpp_lib_scoped_lock 201703L // also in <mutex> #define __cpp_lib_semaphore 201907L // also in <semaphore> #define __cpp_lib_senders 202406L // also in <execution> #define __cpp_lib_shared_mutex 201505L // also in <shared_mutex> #define __cpp_lib_shared_ptr_arrays 201707L // also in <memory> #define __cpp_lib_shared_ptr_weak_type 201606L // also in <memory> #define __cpp_lib_shared_timed_mutex 201402L // also in <shared_mutex> #define __cpp_lib_shift 202202L // also in <algorithm> #define __cpp_lib_simd 202411L // also in <simd> #define __cpp_lib_smart_ptr_for_overwrite 202002L // also in <memory> #define __cpp_lib_smart_ptr_owner_equality 202306L // also in <memory> #define __cpp_lib_source_location 201907L // freestanding, also in <source_location> #define __cpp_lib_span 202311L // freestanding, also in <span> #define __cpp_lib_span_initializer_list 202311L // freestanding, also in <span> #define __cpp_lib_spanstream 202106L // also in <spanstream> #define __cpp_lib_ssize 201902L // freestanding, also in <iterator> #define __cpp_lib_sstream_from_string_view 202306L // also in <sstream> #define __cpp_lib_stacktrace 202011L // also in <stacktrace> #define __cpp_lib_start_lifetime_as 202207L // freestanding, also in <memory> #define __cpp_lib_starts_ends_with 201711L // also in <string>, <string_view> #define __cpp_lib_stdatomic_h 202011L // also in <stdatomic.h> #define __cpp_lib_string_contains 202011L // also in <string>, <string_view> #define __cpp_lib_string_resize_and_overwrite 202110L // also in <string> #define __cpp_lib_string_udls 201304L // also in <string> #define __cpp_lib_string_view 202403L // also in <string>, <string_view> #define __cpp_lib_submdspan 202411L // freestanding, also in <mdspan> #define __cpp_lib_syncbuf 201803L // also in <syncstream> #define __cpp_lib_text_encoding 202306L // also in <text_encoding> #define __cpp_lib_three_way_comparison 201907L // freestanding, also in <compare> #define __cpp_lib_to_address 201711L // freestanding, also in <memory> #define __cpp_lib_to_array 201907L // freestanding, also in <array> #define __cpp_lib_to_chars 202306L // also in <charconv> #define __cpp_lib_to_string 202306L // also in <string> #define __cpp_lib_to_underlying 202102L // freestanding, also in <utility> #define __cpp_lib_transformation_trait_aliases 201304L // freestanding, also in <type_traits> #define __cpp_lib_transparent_operators 201510L // freestanding, also in <memory>, <functional> #define __cpp_lib_tuple_element_t 201402L // freestanding, also in <tuple> #define __cpp_lib_tuple_like 202311L // also in <utility>, <tuple>, <map>, <unordered_map> #define __cpp_lib_tuples_by_type 201304L // freestanding, also in <utility>, <tuple> #define __cpp_lib_type_identity 201806L // freestanding, also in <type_traits> #define __cpp_lib_type_trait_variable_templates 201510L // freestanding, also in <type_traits> #define __cpp_lib_uncaught_exceptions 201411L // freestanding, also in <exception> #define __cpp_lib_unordered_map_try_emplace 201411L // also in <unordered_map> #define __cpp_lib_unreachable 202202L // freestanding, also in <utility> #define __cpp_lib_unwrap_ref 201811L // freestanding, also in <type_traits> #define __cpp_lib_variant 202306L // also in <variant> #define __cpp_lib_void_t 201411L // freestanding, also in <type_traits>
The macro __cpp_lib_freestanding_operator_new is defined to the integer literal 202306L if all the default versions of the replaceable global allocation functions meet the requirements of a hosted implementation, and to the integer literal 0 otherwise ([new.delete]).
Recommended practice: Freestanding implementations should only define a macro from <version> if the implementation provides the corresponding facility in its entirety.

17.3.3 Header <limits> synopsis [limits.syn]

// all freestanding namespace std { // [round.style], enumeration float_round_style enum float_round_style; // [numeric.limits], class template numeric_limits template<class T> class numeric_limits; template<class T> class numeric_limits<const T>; template<class T> class numeric_limits<volatile T>; template<class T> class numeric_limits<const volatile T>; template<> class numeric_limits<bool>; template<> class numeric_limits<char>; template<> class numeric_limits<signed char>; template<> class numeric_limits<unsigned char>; template<> class numeric_limits<char8_t>; template<> class numeric_limits<char16_t>; template<> class numeric_limits<char32_t>; template<> class numeric_limits<wchar_t>; template<> class numeric_limits<short>; template<> class numeric_limits<int>; template<> class numeric_limits<long>; template<> class numeric_limits<long long>; template<> class numeric_limits<unsigned short>; template<> class numeric_limits<unsigned int>; template<> class numeric_limits<unsigned long>; template<> class numeric_limits<unsigned long long>; template<> class numeric_limits<float>; template<> class numeric_limits<double>; template<> class numeric_limits<long double>; }

17.3.4 Enum float_round_style [round.style]

namespace std { enum float_round_style { round_indeterminate = -1, round_toward_zero = 0, round_to_nearest = 1, round_toward_infinity = 2, round_toward_neg_infinity = 3 }; }
The rounding mode for floating-point arithmetic is characterized by the values:
  • round_indeterminate if the rounding style is indeterminable
  • round_toward_zero if the rounding style is toward zero
  • round_to_nearest if the rounding style is to the nearest representable value
  • round_toward_infinity if the rounding style is toward infinity
  • round_toward_neg_infinity if the rounding style is toward negative infinity

17.3.5 Class template numeric_limits [numeric.limits]

17.3.5.1 General [numeric.limits.general]

The numeric_limits class template provides a C++ program with information about various properties of the implementation's representation of the arithmetic types.
namespace std { template<class T> class numeric_limits { public: static constexpr bool is_specialized = false; static constexpr T min() noexcept { return T(); } static constexpr T max() noexcept { return T(); } static constexpr T lowest() noexcept { return T(); } static constexpr int digits = 0; static constexpr int digits10 = 0; static constexpr int max_digits10 = 0; static constexpr bool is_signed = false; static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = 0; static constexpr T epsilon() noexcept { return T(); } static constexpr T round_error() noexcept { return T(); } static constexpr int min_exponent = 0; static constexpr int min_exponent10 = 0; static constexpr int max_exponent = 0; static constexpr int max_exponent10 = 0; static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; static constexpr T infinity() noexcept { return T(); } static constexpr T quiet_NaN() noexcept { return T(); } static constexpr T signaling_NaN() noexcept { return T(); } static constexpr T denorm_min() noexcept { return T(); } static constexpr bool is_iec559 = false; static constexpr bool is_bounded = false; static constexpr bool is_modulo = false; static constexpr bool traps = false; static constexpr bool tinyness_before = false; static constexpr float_round_style round_style = round_toward_zero; }; }
For all members declared static constexpr in the numeric_limits template, specializations shall define these values in such a way that they are usable as constant expressions.
For the numeric_limits primary template, all data members are value-initialized and all member functions return a value-initialized object.
[Note 1: 
This means all members have zero or false values unless numeric_limits is specialized for a type.
— end note]
Specializations shall be provided for each arithmetic type, both floating-point and integer, including bool.
The member is_specialized shall be true for all such specializations of numeric_limits.
The value of each member of a specialization of numeric_limits on a cv-qualified type cv T shall be equal to the value of the corresponding member of the specialization on the unqualified type T.
Non-arithmetic standard types, such as complex<T>, shall not have specializations.

17.3.5.2 numeric_limits members [numeric.limits.members]

Each member function defined in this subclause is signal-safe ([support.signal]).
[Note 1: 
The arithmetic specification described in ISO/IEC 10967-1:2012 is commonly termed LIA-1.
— end note]
static constexpr T min() noexcept;
Minimum finite value.163
For floating-point types with subnormal numbers, returns the minimum positive normalized value.
Meaningful for all specializations in which is_bounded != false, or is_bounded == false && is_signed == false.
static constexpr T max() noexcept;
Maximum finite value.164
Meaningful for all specializations in which is_bounded != false.
static constexpr T lowest() noexcept;
A finite value x such that there is no other finite value y where y < x.165
Meaningful for all specializations in which is_bounded != false.
static constexpr int digits;
Number of radix digits that can be represented without change.
For integer types, the number of non-sign bits in the representation.
For floating-point types, the number of radix digits in the significand.166
static constexpr int digits10;
Number of base 10 digits that can be represented without change.167
Meaningful for all specializations in which is_bounded != false.
static constexpr int max_digits10;
Number of base 10 digits required to ensure that values which differ are always differentiated.
Meaningful for all floating-point types.
static constexpr bool is_signed;
true if the type is signed.
Meaningful for all specializations.
static constexpr bool is_integer;
true if the type is integer.
Meaningful for all specializations.
static constexpr bool is_exact;
true if the type uses an exact representation.
All integer types are exact, but not all exact types are integer.
For example, rational and fixed-exponent representations are exact but not integer.
Meaningful for all specializations.
static constexpr int radix;
For floating-point types, specifies the base or radix of the exponent representation (often 2).168
For integer types, specifies the base of the representation.169
Meaningful for all specializations.
static constexpr T epsilon() noexcept;
Machine epsilon: the difference between 1 and the least value greater than 1 that is representable.170
Meaningful for all floating-point types.
static constexpr T round_error() noexcept;
Measure of the maximum rounding error.171
static constexpr int min_exponent;
Minimum negative integer such that radix raised to the power of one less than that integer is a normalized floating-point number.172
Meaningful for all floating-point types.
static constexpr int min_exponent10;
Minimum negative integer such that 10 raised to that power is in the range of normalized floating-point numbers.173
Meaningful for all floating-point types.
static constexpr int max_exponent;
Maximum positive integer such that radix raised to the power one less than that integer is a representable finite floating-point number.174
Meaningful for all floating-point types.
static constexpr int max_exponent10;
Maximum positive integer such that 10 raised to that power is in the range of representable finite floating-point numbers.175
Meaningful for all floating-point types.
static constexpr bool has_infinity;
true if the type has a representation for positive infinity.
Meaningful for all floating-point types.
Shall be true for all specializations in which is_iec559 != false.
static constexpr bool has_quiet_NaN;
true if the type has a representation for a quiet (non-signaling) “Not a Number”.176
Meaningful for all floating-point types.
Shall be true for all specializations in which is_iec559 != false.
static constexpr bool has_signaling_NaN;
true if the type has a representation for a signaling “Not a Number”.177
Meaningful for all floating-point types.
Shall be true for all specializations in which is_iec559 != false.
static constexpr T infinity() noexcept;
Representation of positive infinity, if available.178
Meaningful for all specializations for which has_infinity != false.
Required in specializations for which is_iec559 != false.
static constexpr T quiet_NaN() noexcept;
Representation of a quiet “Not a Number”, if available.179
Meaningful for all specializations for which has_quiet_NaN != false.
Required in specializations for which is_iec559 != false.
static constexpr T signaling_NaN() noexcept;
Representation of a signaling “Not a Number”, if available.180
Meaningful for all specializations for which has_signaling_NaN != false.
Required in specializations for which is_iec559 != false.
static constexpr T denorm_min() noexcept;
Minimum positive subnormal value, if available.181
Otherwise, minimum positive normalized value.
Meaningful for all floating-point types.
static constexpr bool is_iec559;
true if and only if the type adheres to ISO/IEC 60559.182
[Note 2: 
The value is true for any of the types float16_t, float32_t, float64_t, or float128_t, if present ([basic.extended.fp]).
— end note]
Meaningful for all floating-point types.
static constexpr bool is_bounded;
true if the set of values representable by the type is finite.183
[Note 3: 
All fundamental types ([basic.fundamental]) are bounded.
This member would be false for arbitrary precision types.
— end note]
Meaningful for all specializations.
static constexpr bool is_modulo;
true if the type is modulo.184
A type is modulo if, for any operation involving +, -, or * on values of that type whose result would fall outside the range [min(), max()], the value returned differs from the true value by an integer multiple of max() - min() + 1.
[Example 1: 
is_modulo is false for signed integer types ([basic.fundamental]) unless an implementation, as an extension to this document, defines signed integer overflow to wrap.
— end example]
Meaningful for all specializations.
static constexpr bool traps;
true if, at the start of the program, there exists a value of the type that would cause an arithmetic operation using that value to trap.185
Meaningful for all specializations.
static constexpr bool tinyness_before;
true if tinyness is detected before rounding.186
Meaningful for all floating-point types.
static constexpr float_round_style round_style;
The rounding style for the type.187
Meaningful for all floating-point types.
Specializations for integer types shall return round_toward_zero.
163)163)
Equivalent to CHAR_MIN, SHRT_MIN, FLT_MIN, DBL_MIN, etc.
164)164)
Equivalent to CHAR_MAX, SHRT_MAX, FLT_MAX, DBL_MAX, etc.
165)165)
lowest() is necessary because not all floating-point representations have a smallest (most negative) value that is the negative of the largest (most positive) finite value.
166)166)
Equivalent to FLT_MANT_DIG, DBL_MANT_DIG, LDBL_MANT_DIG.
167)167)
Equivalent to FLT_DIG, DBL_DIG, LDBL_DIG.
168)168)
Equivalent to FLT_RADIX.
169)169)
Distinguishes types with bases other than 2 (e.g., BCD).
170)170)
Equivalent to FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON.
171)171)
Rounding error is described in ISO/IEC 10967-1:2012 Section 5.2.4 and Annex C Rationale Section C.5.2.4 — Rounding and rounding constants.
172)172)
Equivalent to FLT_MIN_EXP, DBL_MIN_EXP, LDBL_MIN_EXP.
173)173)
Equivalent to FLT_MIN_10_EXP, DBL_MIN_10_EXP, LDBL_MIN_10_EXP.
174)174)
Equivalent to FLT_MAX_EXP, DBL_MAX_EXP, LDBL_MAX_EXP.
175)175)
Equivalent to FLT_MAX_10_EXP, DBL_MAX_10_EXP, LDBL_MAX_10_EXP.
176)176)
Required by ISO/IEC 10967-1:2012.
177)177)
Required by ISO/IEC 10967-1:2012.
178)178)
Required by ISO/IEC 10967-1:2012.
179)179)
Required by ISO/IEC 10967-1:2012.
180)180)
Required by ISO/IEC 10967-1:2012.
181)181)
Required by ISO/IEC 10967-1:2012.
182)182)
ISO/IEC 60559:2020 is the same as IEEE 754-2019.
183)183)
Required by ISO/IEC 10967-1:2012.
184)184)
Required by ISO/IEC 10967-1:2012.
185)185)
Required by ISO/IEC 10967-1:2012.
186)186)
Refer to ISO/IEC 60559.
Required by ISO/IEC 10967-1:2012.
187)187)
Equivalent to FLT_ROUNDS.
Required by ISO/IEC 10967-1:2012.

17.3.5.3 numeric_limits specializations [numeric.special]

All members shall be provided for all specializations.
However, many values are only required to be meaningful under certain conditions (for example, epsilon() is only meaningful if is_integer is false).
Any value that is not “meaningful” shall be set to 0 or false.
[Example 1: namespace std { template<> class numeric_limits<float> { public: static constexpr bool is_specialized = true; static constexpr float min() noexcept { return 1.17549435E-38F; } static constexpr float max() noexcept { return 3.40282347E+38F; } static constexpr float lowest() noexcept { return -3.40282347E+38F; } static constexpr int digits = 24; static constexpr int digits10 = 6; static constexpr int max_digits10 = 9; static constexpr bool is_signed = true; static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = 2; static constexpr float epsilon() noexcept { return 1.19209290E-07F; } static constexpr float round_error() noexcept { return 0.5F; } static constexpr int min_exponent = -125; static constexpr int min_exponent10 = - 37; static constexpr int max_exponent = +128; static constexpr int max_exponent10 = + 38; static constexpr bool has_infinity = true; static constexpr bool has_quiet_NaN = true; static constexpr bool has_signaling_NaN = true; static constexpr float infinity() noexcept { return value; } static constexpr float quiet_NaN() noexcept { return value; } static constexpr float signaling_NaN() noexcept { return value; } static constexpr float denorm_min() noexcept { return min(); } static constexpr bool is_iec559 = true; static constexpr bool is_bounded = true; static constexpr bool is_modulo = false; static constexpr bool traps = true; static constexpr bool tinyness_before = true; static constexpr float_round_style round_style = round_to_nearest; }; } — end example]
The specialization for bool shall be provided as follows: namespace std { template<> class numeric_limits<bool> { public: static constexpr bool is_specialized = true; static constexpr bool min() noexcept { return false; } static constexpr bool max() noexcept { return true; } static constexpr bool lowest() noexcept { return false; } static constexpr int digits = 1; static constexpr int digits10 = 0; static constexpr int max_digits10 = 0; static constexpr bool is_signed = false; static constexpr bool is_integer = true; static constexpr bool is_exact = true; static constexpr int radix = 2; static constexpr bool epsilon() noexcept { return 0; } static constexpr bool round_error() noexcept { return 0; } static constexpr int min_exponent = 0; static constexpr int min_exponent10 = 0; static constexpr int max_exponent = 0; static constexpr int max_exponent10 = 0; static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; static constexpr bool infinity() noexcept { return 0; } static constexpr bool quiet_NaN() noexcept { return 0; } static constexpr bool signaling_NaN() noexcept { return 0; } static constexpr bool denorm_min() noexcept { return 0; } static constexpr bool is_iec559 = false; static constexpr bool is_bounded = true; static constexpr bool is_modulo = false; static constexpr bool traps = false; static constexpr bool tinyness_before = false; static constexpr float_round_style round_style = round_toward_zero; }; }

17.3.6 Header <climits> synopsis [climits.syn]

// all freestanding #define CHAR_BIT see below #define SCHAR_MIN see below #define SCHAR_MAX see below #define UCHAR_MAX see below #define CHAR_MIN see below #define CHAR_MAX see below #define MB_LEN_MAX see below #define SHRT_MIN see below #define SHRT_MAX see below #define USHRT_MAX see below #define INT_MIN see below #define INT_MAX see below #define UINT_MAX see below #define LONG_MIN see below #define LONG_MAX see below #define ULONG_MAX see below #define LLONG_MIN see below #define LLONG_MAX see below #define ULLONG_MAX see below
The header <climits> defines all macros the same as the C standard library header <limits.h>.
[Note 1: 
Except for CHAR_BIT and MB_LEN_MAX, a macro referring to an integer type T defines a constant whose type is the promoted type of T ([conv.prom]).
— end note]
See also: ISO/IEC 9899:2018, 5.2.4.2.1

17.3.7 Header <cfloat> synopsis [cfloat.syn]

// all freestanding #define FLT_ROUNDS see below #define FLT_EVAL_METHOD see below #define FLT_HAS_SUBNORM see below #define DBL_HAS_SUBNORM see below #define LDBL_HAS_SUBNORM see below #define FLT_RADIX see below #define FLT_MANT_DIG see below #define DBL_MANT_DIG see below #define LDBL_MANT_DIG see below #define FLT_DECIMAL_DIG see below #define DBL_DECIMAL_DIG see below #define LDBL_DECIMAL_DIG see below #define DECIMAL_DIG see below #define FLT_DIG see below #define DBL_DIG see below #define LDBL_DIG see below #define FLT_MIN_EXP see below #define DBL_MIN_EXP see below #define LDBL_MIN_EXP see below #define FLT_MIN_10_EXP see below #define DBL_MIN_10_EXP see below #define LDBL_MIN_10_EXP see below #define FLT_MAX_EXP see below #define DBL_MAX_EXP see below #define LDBL_MAX_EXP see below #define FLT_MAX_10_EXP see below #define DBL_MAX_10_EXP see below #define LDBL_MAX_10_EXP see below #define FLT_MAX see below #define DBL_MAX see below #define LDBL_MAX see below #define FLT_EPSILON see below #define DBL_EPSILON see below #define LDBL_EPSILON see below #define FLT_MIN see below #define DBL_MIN see below #define LDBL_MIN see below #define FLT_TRUE_MIN see below #define DBL_TRUE_MIN see below #define LDBL_TRUE_MIN see below
The header <cfloat> defines all macros the same as the C standard library header <float.h>.
See also: ISO/IEC 9899:2018, 5.2.4.2.2

17.4 Arithmetic types [support.arith.types]

17.4.1 Header <cstdint> synopsis [cstdint.syn]

The header <cstdint> supplies integer types having specified widths, and macros that specify limits of integer types.
// all freestanding namespace std { using int8_t = signed integer type; // optional using int16_t = signed integer type; // optional using int32_t = signed integer type; // optional using int64_t = signed integer type; // optional using intN_t = see below; // optional using int_fast8_t = signed integer type; using int_fast16_t = signed integer type; using int_fast32_t = signed integer type; using int_fast64_t = signed integer type; using int_fastN_t = see below; // optional using int_least8_t = signed integer type; using int_least16_t = signed integer type; using int_least32_t = signed integer type; using int_least64_t = signed integer type; using int_leastN_t = see below; // optional using intmax_t = signed integer type; using intptr_t = signed integer type; // optional using uint8_t = unsigned integer type; // optional using uint16_t = unsigned integer type; // optional using uint32_t = unsigned integer type; // optional using uint64_t = unsigned integer type; // optional using uintN_t = see below; // optional using uint_fast8_t = unsigned integer type; using uint_fast16_t = unsigned integer type; using uint_fast32_t = unsigned integer type; using uint_fast64_t = unsigned integer type; using uint_fastN_t = see below; // optional using uint_least8_t = unsigned integer type; using uint_least16_t = unsigned integer type; using uint_least32_t = unsigned integer type; using uint_least64_t = unsigned integer type; using uint_leastN_t = see below; // optional using uintmax_t = unsigned integer type; using uintptr_t = unsigned integer type; // optional } #define INTN_MIN see below #define INTN_MAX see below #define UINTN_MAX see below #define INT_FASTN_MIN see below #define INT_FASTN_MAX see below #define UINT_FASTN_MAX see below #define INT_LEASTN_MIN see below #define INT_LEASTN_MAX see below #define UINT_LEASTN_MAX see below #define INTMAX_MIN see below #define INTMAX_MAX see below #define UINTMAX_MAX see below #define INTPTR_MIN see below // optional #define INTPTR_MAX see below // optional #define UINTPTR_MAX see below // optional #define PTRDIFF_MIN see below #define PTRDIFF_MAX see below #define SIZE_MAX see below #define SIG_ATOMIC_MIN see below #define SIG_ATOMIC_MAX see below #define WCHAR_MIN see below #define WCHAR_MAX see below #define WINT_MIN see below #define WINT_MAX see below #define INTN_C(value) see below #define UINTN_C(value) see below #define INTMAX_C(value) see below #define UINTMAX_C(value) see below
The header defines all types and macros the same as the C standard library header <stdint.h>.
See also: ISO/IEC 9899:2018, 7.20
All types that use the placeholder N are optional when N is not 8, 16, 32, or 64.
The exact-width types intN_t and uintN_t for N = 8, 16, 32, and 64 are also optional; however, if an implementation defines integer types with the corresponding width and no padding bits, it defines the corresponding typedef-names.
Each of the macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef-name.
[Note 1: 
The macros INTN_C and UINTN_C correspond to the typedef-names int_leastN_t and uint_leastN_t, respectively.
— end note]

17.4.2 Header <stdfloat> synopsis [stdfloat.syn]

The header <stdfloat> defines type aliases for the optional extended floating-point types that are specified in [basic.extended.fp].
namespace std { #if defined(__STDCPP_FLOAT16_T__) using float16_t = implementation-defined; // see [basic.extended.fp] #endif #if defined(__STDCPP_FLOAT32_T__) using float32_t = implementation-defined; // see [basic.extended.fp] #endif #if defined(__STDCPP_FLOAT64_T__) using float64_t = implementation-defined; // see [basic.extended.fp] #endif #if defined(__STDCPP_FLOAT128_T__) using float128_t = implementation-defined; // see [basic.extended.fp] #endif #if defined(__STDCPP_BFLOAT16_T__) using bfloat16_t = implementation-defined; // see [basic.extended.fp] #endif }

17.5 Startup and termination [support.start.term]

[Note 1: 
The header <cstdlib> declares the functions described in this subclause.
— end note]
[[noreturn]] void _Exit(int status) noexcept;
Effects: This function has the semantics specified in the C standard library.
Remarks: The program is terminated without executing destructors for objects of automatic, thread, or static storage duration and without calling functions passed to atexit() ([basic.start.term]).
The function _Exit is signal-safe.
[[noreturn]] void abort() noexcept;
Effects: This function has the semantics specified in the C standard library.
Remarks: The program is terminated without executing destructors for objects of automatic, thread, or static storage duration and without calling functions passed to atexit() ([basic.start.term]).
The function abort is signal-safe.
int atexit(c-atexit-handler* f) noexcept; int atexit(atexit-handler* f) noexcept;
Effects: The atexit() functions register the function pointed to by f to be called without arguments at normal program termination.
It is unspecified whether a call to atexit() that does not happen before a call to exit() will succeed.
[Note 2: 
The atexit() functions do not introduce a data race ([res.on.data.races]).
— end note]
Implementation limits: The implementation shall support the registration of at least 32 functions.
Returns: The atexit() function returns zero if the registration succeeds, nonzero if it fails.
[[noreturn]] void exit(int status);
Effects:
  • First, objects with thread storage duration and associated with the current thread are destroyed.
    Next, objects with static storage duration are destroyed and functions registered by calling atexit are called.188
    See [basic.start.term] for the order of destructions and calls.
    (Objects with automatic storage duration are not destroyed as a result of calling exit().)189
    If a registered function invoked by exit exits via an exception, the function std​::​terminate is invoked ([except.terminate]).
  • Next, all open C streams (as mediated by the function signatures declared in <cstdio>) with unwritten buffered data are flushed, all open C streams are closed, and all files created by calling tmpfile() are removed.
  • Finally, control is returned to the host environment.
    If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned.
    If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned.
    Otherwise the status returned is implementation-defined.190
int at_quick_exit(c-atexit-handler* f) noexcept; int at_quick_exit(atexit-handler* f) noexcept;
Effects: The at_quick_exit() functions register the function pointed to by f to be called without arguments when quick_exit is called.
It is unspecified whether a call to at_quick_exit() that does not happen before all calls to quick_exit will succeed.
[Note 3: 
The at_quick_exit() functions do not introduce a data race ([res.on.data.races]).
— end note]
[Note 4: 
The order of registration could be indeterminate if at_quick_exit was called from more than one thread.
— end note]
[Note 5: 
The at_quick_exit registrations are distinct from the atexit registrations, and applications might need to call both registration functions with the same argument.
— end note]
Implementation limits: The implementation shall support the registration of at least 32 functions.
Returns: Zero if the registration succeeds, nonzero if it fails.
[[noreturn]] void quick_exit(int status) noexcept;
Effects: Functions registered by calls to at_quick_exit are called in the reverse order of their registration, except that a function shall be called after any previously registered functions that had already been called at the time it was registered.
Objects shall not be destroyed as a result of calling quick_exit.
If a registered function invoked by quick_exit exits via an exception, the function std​::​terminate is invoked ([except.terminate]).
[Note 6: 
A function registered via at_quick_exit is invoked by the thread that calls quick_exit, which can be a different thread than the one that registered it, so registered functions cannot rely on the identity of objects with thread storage duration.
— end note]
After calling registered functions, quick_exit shall call _Exit(status).
Remarks: The function quick_exit is signal-safe when the functions registered with at_quick_exit are.
See also: ISO/IEC 9899:2018, 7.22.4
188)188)
A function is called for every time it is registered.
189)189)
Objects with automatic storage duration are all destroyed in a program whose main function ([basic.start.main]) contains no objects with automatic storage duration and executes the call to exit().
Control can be transferred directly to such a main function by throwing an exception that is caught in main.
190)190)
The macros EXIT_FAILURE and EXIT_SUCCESS are defined in <cstdlib>.

17.6 Dynamic memory management [support.dynamic]

17.6.1 General [support.dynamic.general]

The header <new> defines several functions that manage the allocation of dynamic storage in a program.
It also defines components for reporting storage management errors.

17.6.2 Header <new> synopsis [new.syn]

// all freestanding namespace std { // [alloc.errors], storage allocation errors class bad_alloc; class bad_array_new_length; struct destroying_delete_t { explicit destroying_delete_t() = default; }; inline constexpr destroying_delete_t destroying_delete{}; // global operator new control enum class align_val_t : size_t {}; struct nothrow_t { explicit nothrow_t() = default; }; extern const nothrow_t nothrow; using new_handler = void (*)(); new_handler get_new_handler() noexcept; new_handler set_new_handler(new_handler new_p) noexcept; // [ptr.launder], pointer optimization barrier template<class T> constexpr T* launder(T* p) noexcept; // [hardware.interference], hardware interference size inline constexpr size_t hardware_destructive_interference_size = implementation-defined; inline constexpr size_t hardware_constructive_interference_size = implementation-defined; } // [new.delete], storage allocation and deallocation void* operator new(std::size_t size); void* operator new(std::size_t size, std::align_val_t alignment); void* operator new(std::size_t size, const std::nothrow_t&) noexcept; void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; void operator delete(void* ptr) noexcept; void operator delete(void* ptr, std::size_t size) noexcept; void operator delete(void* ptr, std::align_val_t alignment) noexcept; void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept; void operator delete(void* ptr, const std::nothrow_t&) noexcept; void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept; void* operator new[](std::size_t size); void* operator new[](std::size_t size, std::align_val_t alignment); void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; void* operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept; void operator delete[](void* ptr) noexcept; void operator delete[](void* ptr, std::size_t size) noexcept; void operator delete[](void* ptr, std::align_val_t alignment) noexcept; void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept; void operator delete[](void* ptr, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept; constexpr void* operator new (std::size_t size, void* ptr) noexcept; constexpr void* operator new[](std::size_t size, void* ptr) noexcept; void operator delete (void* ptr, void*) noexcept; void operator delete[](void* ptr, void*) noexcept;

17.6.3 Storage allocation and deallocation [new.delete]

17.6.3.1 General [new.delete.general]

Except where otherwise specified, the provisions of [basic.stc.dynamic] apply to the library versions of operator new and operator delete.
If the value of an alignment argument passed to any of these functions is not a valid alignment value, the behavior is undefined.
On freestanding implementations, it is implementation-defined whether the default versions of the replaceable global allocation functions satisfy the required behaviors described in [new.delete.single] and [new.delete.array].
[Note 1: 
A freestanding implementation's default versions of the replaceable global allocation functions can cause undefined behavior when invoked.
During constant evaluation, the behaviors of those default versions are irrelevant, as those calls are omitted ([expr.new]).
— end note]
Recommended practice: If any of the default versions of the replaceable global allocation functions meet the requirements of a hosted implementation, they all should.

17.6.3.2 Single-object forms [new.delete.single]

void* operator new(std::size_t size); void* operator new(std::size_t size, std::align_val_t alignment);
Effects: The allocation functions called by a new-expression ([expr.new]) to allocate size bytes of storage.
The second form is called for a type with new-extended alignment, and the first form is called otherwise.
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else throw a bad_alloc exception.
This requirement is binding on any replacement versions of these functions.
Default behavior:
  • Executes a loop: Within the loop, the function first attempts to allocate the requested storage.
    Whether the attempt involves a call to the C standard library functions malloc or aligned_alloc is unspecified.
  • Returns a pointer to the allocated storage if the attempt is successful.
    Otherwise, if the current new_handler ([get.new.handler]) is a null pointer value, throws bad_alloc.
  • Otherwise, the function calls the current new_handler function.
    If the called function returns, the loop repeats.
  • The loop terminates when an attempt to allocate the requested storage is successful or when a called new_handler function does not return.
void* operator new(std::size_t size, const std::nothrow_t&) noexcept; void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept;
Effects: Same as above, except that these are called by a placement version of a new-expression when a C++ program prefers a null pointer result as an error indication, instead of a bad_alloc exception.
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else return a null pointer.
Each of these nothrow versions of operator new returns a pointer obtained as if acquired from the (possibly replaced) corresponding non-placement function.
This requirement is binding on any replacement versions of these functions.
Default behavior: Calls operator new(size), or operator new(size, alignment), respectively.
If the call returns normally, returns the result of that call.
Otherwise, returns a null pointer.
[Example 1: T* p1 = new T; // throws bad_alloc if it fails T* p2 = new(nothrow) T; // returns nullptr if it fails — end example]
void operator delete(void* ptr) noexcept; void operator delete(void* ptr, std::size_t size) noexcept; void operator delete(void* ptr, std::align_val_t alignment) noexcept; void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept;
Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced) operator new(std​::​size_t) or operator new(std​::​size_t, std​::​align_val_t) which has not been invalidated by an intervening call to operator delete.
If the alignment parameter is not present, ptr was returned by an allocation function without an alignment parameter.
If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.
If present, the size argument is equal to the size argument passed to the allocation function that returned ptr.
Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by a delete-expression ([expr.delete]) to render the value of ptr invalid.
Replaceable: A C++ program may define functions with any of these function signatures, and thereby displace the default versions defined by the C++ standard library.
If a function without a size parameter is defined, the program should also define the corresponding function with a size parameter.
If a function with a size parameter is defined, the program shall also define the corresponding version without the size parameter.
[Note 1: 
The default behavior below might change in the future, which will require replacing both deallocation functions when replacing the allocation function.
— end note]
Required behavior: A call to an operator delete with a size parameter may be changed to a call to the corresponding operator delete without a size parameter, without affecting memory allocation.
[Note 2: 
A conforming implementation is for operator delete(void* ptr, std​::​size_t size) to simply call operator delete(ptr).
— end note]
Default behavior: The functions that have a size parameter forward their other parameters to the corresponding function without a size parameter.
[Note 3: 
See the note in the above Replaceable: paragraph.
— end note]
Default behavior: If ptr is null, does nothing.
Otherwise, reclaims the storage allocated by the earlier call to operator new.
Remarks: It is unspecified under what conditions part or all of such reclaimed storage will be allocated by subsequent calls to operator new or any of aligned_alloc, calloc, malloc, or realloc, declared in <cstdlib>.
void operator delete(void* ptr, const std::nothrow_t&) noexcept; void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;
Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced) operator new(std​::​size_t) or operator new(std​::​size_t, std​::​align_val_t) which has not been invalidated by an intervening call to operator delete.
If the alignment parameter is not present, ptr was returned by an allocation function without an alignment parameter.
If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.
Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by the implementation to render the value of ptr invalid when the constructor invoked from a nothrow placement version of the new-expression throws an exception.
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Default behavior: Calls operator delete(ptr), or operator delete(ptr, alignment), respectively.

17.6.3.3 Array forms [new.delete.array]

void* operator new[](std::size_t size); void* operator new[](std::size_t size, std::align_val_t alignment);
Effects: The allocation functions called by the array form of a new-expression ([expr.new]) to allocate size bytes of storage.
The second form is called for a type with new-extended alignment, and the first form is called otherwise.191
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Required behavior: Same as for the corresponding single-object forms.
This requirement is binding on any replacement versions of these functions.
Default behavior: Returns operator new(size), or operator new(size, alignment), respectively.
void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; void* operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept;
Effects: Same as above, except that these are called by a placement version of a new-expression when a C++ program prefers a null pointer result as an error indication, instead of a bad_alloc exception.
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else return a null pointer.
Each of these nothrow versions of operator new[] returns a pointer obtained as if acquired from the (possibly replaced) corresponding non-placement function.
This requirement is binding on any replacement versions of these functions.
Default behavior: Calls operator new[](size), or operator new[](size, alignment), respectively.
If the call returns normally, returns the result of that call.
Otherwise, returns a null pointer.
void operator delete[](void* ptr) noexcept; void operator delete[](void* ptr, std::size_t size) noexcept; void operator delete[](void* ptr, std::align_val_t alignment) noexcept; void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept;
Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced) operator new[](std​::​size_t) or operator new[](std​::​size_t, std​::​align_val_t) which has not been invalidated by an intervening call to operator delete[].
If the alignment parameter is not present, ptr was returned by an allocation function without an alignment parameter.
If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.
If present, the size argument is equal to the size argument passed to the allocation function that returned ptr.
Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by the array form of a delete-expression to render the value of ptr invalid.
Replaceable: A C++ program may define functions with any of these function signatures, and thereby displace the default versions defined by the C++ standard library.
If a function without a size parameter is defined, the program should also define the corresponding function with a size parameter.
If a function with a size parameter is defined, the program shall also define the corresponding version without the size parameter.
[Note 1: 
The default behavior below might change in the future, which will require replacing both deallocation functions when replacing the allocation function.
— end note]
Required behavior: A call to an operator delete[] with a size parameter may be changed to a call to the corresponding operator delete[] without a size parameter, without affecting memory allocation.
[Note 2: 
A conforming implementation is for operator delete[](void* ptr, std​::​size_t size) to simply call operator delete[](ptr).
— end note]
Default behavior: The functions that have a size parameter forward their other parameters to the corresponding function without a size parameter.
The functions that do not have a size parameter forward their parameters to the corresponding operator delete (single-object) function.
void operator delete[](void* ptr, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;
Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced) operator new[](std​::​size_t) or operator new[](std​::​size_t, std​::​align_val_t) which has not been invalidated by an intervening call to operator delete[].
If the alignment parameter is not present, ptr was returned by an allocation function without an alignment parameter.
If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.
Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by the implementation to render the value of ptr invalid when the constructor invoked from a nothrow placement version of the array new-expression throws an exception.
Replaceable: A C++ program may define functions with either of these function signatures, and thereby displace the default versions defined by the C++ standard library.
Default behavior: Calls operator delete[](ptr), or operator delete[](ptr, alignment), respectively.
191)191)
It is not the direct responsibility of operator new[] or operator delete[] to note the repetition count or element size of the array.
Those operations are performed elsewhere in the array new and delete expressions.
The array new expression, can, however, increase the size argument to operator new[] to obtain space to store supplemental information.

17.6.3.4 Non-allocating forms [new.delete.placement]

These functions are reserved; a C++ program may not define functions that displace the versions in the C++ standard library ([constraints]).
The provisions of [basic.stc.dynamic] do not apply to these reserved placement forms of operator new and operator delete.
constexpr void* operator new(std::size_t size, void* ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.
[Example 1: 
This can be useful for constructing an object at a known address: void* place = operator new(sizeof(Something)); Something* p = new (place) Something();
— end example]
constexpr void* operator new[](std::size_t size, void* ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.
void operator delete(void* ptr, void*) noexcept;
Effects: Intentionally performs no action.
Remarks: Default function called when any part of the initialization in a placement new-expression that invokes the library's non-array placement operator new terminates by throwing an exception ([expr.new]).
void operator delete[](void* ptr, void*) noexcept;
Effects: Intentionally performs no action.
Remarks: Default function called when any part of the initialization in a placement new-expression that invokes the library's array placement operator new terminates by throwing an exception ([expr.new]).

17.6.3.5 Data races [new.delete.dataraces]

For purposes of determining the existence of data races, the library versions of operator new, user replacement versions of global operator new, the C standard library functions aligned_alloc, calloc, and malloc, the library versions of operator delete, user replacement versions of operator delete, the C standard library function free, and the C standard library function realloc shall not introduce a data race ([res.on.data.races]).
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.

17.6.4 Storage allocation errors [alloc.errors]

17.6.4.1 Class bad_alloc [bad.alloc]

namespace std { class bad_alloc : public exception { public: // see [exception] for the specification of the special member functions constexpr const char* what() const noexcept override; }; }
The class bad_alloc defines the type of objects thrown as exceptions by the implementation to report a failure to allocate storage.
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

17.6.4.2 Class bad_array_new_length [new.badlength]

namespace std { class bad_array_new_length : public bad_alloc { public: // see [exception] for the specification of the special member functions constexpr const char* what() const noexcept override; }; }
The class bad_array_new_length defines the type of objects thrown as exceptions by the implementation to report an attempt to allocate an array of size less than zero or greater than an implementation-defined limit ([expr.new]).
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

17.6.4.3 Type new_handler [new.handler]

using new_handler = void (*)();
The type of a handler function to be called by operator new() or operator new[]() ([new.delete]) when they cannot satisfy a request for additional storage.
Required behavior: A new_handler shall perform one of the following:
  • make more storage available for allocation and then return;
  • throw an exception of type bad_alloc or a class derived from bad_alloc;
  • terminate execution of the program without returning to the caller.

17.6.4.4 set_new_handler [set.new.handler]

new_handler set_new_handler(new_handler new_p) noexcept;
Effects: Establishes the function designated by new_p as the current new_handler.
Returns: The previous new_handler.
Remarks: The initial new_handler is a null pointer.

17.6.4.5 get_new_handler [get.new.handler]

new_handler get_new_handler() noexcept;
Returns: The current new_handler.
[Note 1: 
This can be a null pointer value.
— end note]

17.6.5 Pointer optimization barrier [ptr.launder]

template<class T> constexpr T* launder(T* p) noexcept;
Mandates: !is_function_v<T> && !is_void_v<T> is true.
Preconditions: p represents the address A of a byte in memory.
An object X that is within its lifetime and whose type is similar to T is located at the address A.
All bytes of storage that would be reachable through ([basic.compound]) the result are reachable through p.
Returns: A value of type T* that points to X.
Remarks: An invocation of this function may be used in a core constant expression if and only if the (converted) value of its argument may be used in place of the function invocation.
[Note 1: 
If a new object is created in storage occupied by an existing object of the same type, a pointer to the original object can be used to refer to the new object unless its complete object is a const object or it is a base class subobject; in the latter cases, this function can be used to obtain a usable pointer to the new object.
— end note]
[Example 1: struct X { int n; }; const X *p = new const X{3}; const int a = p->n; new (const_cast<X*>(p)) const X{5}; // p does not point to new object ([basic.life]) because its type is const const int b = p->n; // undefined behavior const int c = std::launder(p)->n; // OK — end example]

17.6.6 Hardware interference size [hardware.interference]

inline constexpr size_t hardware_destructive_interference_size = implementation-defined;
This number is the minimum recommended offset between two concurrently-accessed objects to avoid additional performance degradation due to contention introduced by the implementation.
It shall be at least alignof(max_align_t).
[Example 1: struct keep_apart { alignas(hardware_destructive_interference_size) atomic<int> cat; alignas(hardware_destructive_interference_size) atomic<int> dog; }; — end example]
inline constexpr size_t hardware_constructive_interference_size = implementation-defined;
This number is the maximum recommended size of contiguous memory occupied by two objects accessed with temporal locality by concurrent threads.
It shall be at least alignof(max_align_t).
[Example 2: struct together { atomic<int> dog; int puppy; }; struct kennel { // Other data members... alignas(sizeof(together)) together pack; // Other data members... }; static_assert(sizeof(together) <= hardware_constructive_interference_size); — end example]

17.7 Type identification [support.rtti]

17.7.1 General [support.rtti.general]

The header <typeinfo> defines a type associated with type information generated by the implementation.
It also defines two types for reporting dynamic type identification errors.
The header <typeindex> defines a wrapper type for use as an index type in associative containers ([associative]) and in unordered associative containers ([unord]).

17.7.2 Header <typeinfo> synopsis [typeinfo.syn]

// all freestanding namespace std { class type_info; class bad_cast; class bad_typeid; }

17.7.3 Class type_info [type.info]

namespace std { class type_info { public: virtual ~type_info(); constexpr bool operator==(const type_info& rhs) const noexcept; bool before(const type_info& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; type_info(const type_info&) = delete; // cannot be copied type_info& operator=(const type_info&) = delete; // cannot be copied }; }
The class type_info describes type information generated by the implementation ([expr.typeid]).
Objects of this class effectively store a pointer to a name for the type, and an encoded value suitable for comparing two types for equality or collating order.
The names, encoding rule, and collating sequence for types are all unspecified and may differ between programs.
constexpr bool operator==(const type_info& rhs) const noexcept;
Effects: Compares the current object with rhs.
Returns: true if the two values describe the same type.
bool before(const type_info& rhs) const noexcept;
Effects: Compares the current object with rhs.
Returns: true if *this precedes rhs in the implementation's collation order.
size_t hash_code() const noexcept;
Returns: An unspecified value, except that within a single execution of the program, it shall return the same value for any two type_info objects which compare equal.
Remarks: An implementation should return different values for two type_info objects which do not compare equal.
const char* name() const noexcept;
Returns: An implementation-defined ntbs.
Remarks: The message may be a null-terminated multibyte string, suitable for conversion and display as a wstring ([string.classes], [locale.codecvt]).

17.7.4 Class bad_cast [bad.cast]

namespace std { class bad_cast : public exception { public: // see [exception] for the specification of the special member functions constexpr const char* what() const noexcept override; }; }
The class bad_cast defines the type of objects thrown as exceptions by the implementation to report the execution of an invalid dynamic_cast expression ([expr.dynamic.cast]).
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

17.7.5 Class bad_typeid [bad.typeid]

namespace std { class bad_typeid : public exception { public: // see [exception] for the specification of the special member functions constexpr const char* what() const noexcept override; }; }
The class bad_typeid defines the type of objects thrown as exceptions by the implementation to report a null pointer in a typeid expression ([expr.typeid]).
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

17.7.6 Header <typeindex> synopsis [type.index.synopsis]

#include <compare> // see [compare.syn] namespace std { class type_index; template<class T> struct hash; template<> struct hash<type_index>; }

17.7.7 Class type_index [type.index]

namespace std { class type_index { public: type_index(const type_info& rhs) noexcept; bool operator==(const type_index& rhs) const noexcept; bool operator< (const type_index& rhs) const noexcept; bool operator> (const type_index& rhs) const noexcept; bool operator<=(const type_index& rhs) const noexcept; bool operator>=(const type_index& rhs) const noexcept; strong_ordering operator<=>(const type_index& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; private: const type_info* target; // exposition only // Note that the use of a pointer here, rather than a reference, // means that the default copy/move constructor and assignment // operators will be provided and work as expected. }; }
The class type_index provides a simple wrapper for type_info which can be used as an index type in associative containers ([associative]) and in unordered associative containers ([unord]).
type_index(const type_info& rhs) noexcept;
Effects: Constructs a type_index object, the equivalent of target = &rhs.
bool operator==(const type_index& rhs) const noexcept;
Returns: *target == *rhs.target.
bool operator<(const type_index& rhs) const noexcept;
Returns: target->before(*rhs.target).
bool operator>(const type_index& rhs) const noexcept;
Returns: rhs.target->before(*target).
bool operator<=(const type_index& rhs) const noexcept;
Returns: !rhs.target->before(*target).
bool operator>=(const type_index& rhs) const noexcept;
Returns: !target->before(*rhs.target).
strong_ordering operator<=>(const type_index& rhs) const noexcept;
Effects: Equivalent to: if (*target == *rhs.target) return strong_ordering::equal; if (target->before(*rhs.target)) return strong_ordering::less; return strong_ordering::greater;
size_t hash_code() const noexcept;
Returns: target->hash_code().
const char* name() const noexcept;
Returns: target->name().
template<> struct hash<type_index>;
For an object index of type type_index, hash<type_index>()(index) shall evaluate to the same result as index.hash_code().

17.8 Source location [support.srcloc]

17.8.1 Header <source_location> synopsis [source.location.syn]

The header <source_location> defines the class source_location that provides a means to obtain source location information.
// all freestanding namespace std { struct source_location; }

17.8.2 Class source_location [support.srcloc.class]

17.8.2.1 General [support.srcloc.class.general]

namespace std { struct source_location { // source location construction static consteval source_location current() noexcept; constexpr source_location() noexcept; // source location field access constexpr uint_least32_t line() const noexcept; constexpr uint_least32_t column() const noexcept; constexpr const char* file_name() const noexcept; constexpr const char* function_name() const noexcept; private: uint_least32_t line_; // exposition only uint_least32_t column_; // exposition only const char* file_name_; // exposition only const char* function_name_; // exposition only }; }
All of the following conditions are true:
  • is_nothrow_move_constructible_v<source_location>
  • is_nothrow_move_assignable_v<source_location>
  • is_nothrow_swappable_v<source_location>
[Note 1: 
The intent of source_location is to have a small size and efficient copying.
It is unspecified whether the copy/move constructors and the copy/move assignment operators are trivial and/or constexpr.
— end note]
The data members file_name_ and function_name_ always each refer to an ntbs.
The copy/move constructors and the copy/move assignment operators of source_location meet the following postconditions: Given two objects lhs and rhs of type source_location, where lhs is a copy/move result of rhs, and where rhs_p is a value denoting the state of rhs before the corresponding copy/move operation, then each of the following conditions is true:
  • strcmp(lhs.file_name(), rhs_p.file_name()) == 0
  • strcmp(lhs.function_name(), rhs_p.function_name()) == 0
  • lhs.line() == rhs_p.line()
  • lhs.column() == rhs_p.column()

17.8.2.2 Creation [support.srcloc.cons]

static consteval source_location current() noexcept;
Returns:
  • When invoked by a function call whose postfix-expression is a (possibly parenthesized) id-expression naming current, returns a source_location with an implementation-defined value.
    The value should be affected by #line ([cpp.line]) in the same manner as for __LINE__ and __FILE__.
    The values of the exposition-only data members of the returned source_location object are indicated in Table 43.
    Table 43 — Value of object returned by current[tab:support.srcloc.current]
    Element
    Value
    line_
    A presumed line number ([cpp.predefined]).
    Line numbers are presumed to be 1-indexed; however, an implementation is encouraged to use 0 when the line number is unknown.
    column_
    An implementation-defined value denoting some offset from the start of the line denoted by line_.
    Column numbers are presumed to be 1-indexed; however, an implementation is encouraged to use 0 when the column number is unknown.
    file_name_
    A presumed name of the current source file ([cpp.predefined]) as an ntbs.
    function_name_
    A name of the current function such as in __func__ ([dcl.fct.def.general]) if any, an empty string otherwise.
  • Otherwise, when invoked in some other way, returns a source_location whose data members are initialized with valid but unspecified values.
Remarks: Any call to current that appears as a default member initializer ([class.mem]), or as a subexpression thereof, should correspond to the location of the constructor definition or aggregate initialization that uses the default member initializer.
Any call to current that appears as a default argument ([dcl.fct.default]), or as a subexpression thereof, should correspond to the location of the invocation of the function that uses the default argument ([expr.call]).
[Example 1: struct s { source_location member = source_location::current(); int other_member; s(source_location loc = source_location::current()) : member(loc) // values of member refer to the location of the calling function ([dcl.fct.default]) {} s(int blather) : // values of member refer to this location other_member(blather) {} s(double) // values of member refer to this location {} }; void f(source_location a = source_location::current()) { source_location b = source_location::current(); // values in b refer to this line } void g() { f(); // f's first argument corresponds to this line of code source_location c = source_location::current(); f(c); // f's first argument gets the same values as c, above } — end example]
constexpr source_location() noexcept;
Effects: The data members are initialized with valid but unspecified values.

17.8.2.3 Observers [support.srcloc.obs]

constexpr uint_least32_t line() const noexcept;
Returns: line_.
constexpr uint_least32_t column() const noexcept;
Returns: column_.
constexpr const char* file_name() const noexcept;
Returns: file_name_.
constexpr const char* function_name() const noexcept;
Returns: function_name_.

17.9 Exception handling [support.exception]

17.9.1 General [support.exception.general]

The header <exception> defines several types and functions related to the handling of exceptions in a C++ program.

17.9.2 Header <exception> synopsis [exception.syn]

// all freestanding namespace std { class exception; class bad_exception; class nested_exception; using terminate_handler = void (*)(); terminate_handler get_terminate() noexcept; terminate_handler set_terminate(terminate_handler f) noexcept; [[noreturn]] void terminate() noexcept; constexpr int uncaught_exceptions() noexcept; using exception_ptr = unspecified; constexpr exception_ptr current_exception() noexcept; [[noreturn]] constexpr void rethrow_exception(exception_ptr p); template<class E> constexpr exception_ptr make_exception_ptr(E e) noexcept; template<class T> [[noreturn]] constexpr void throw_with_nested(T&& t); template<class E> constexpr void rethrow_if_nested(const E& e); }

17.9.3 Class exception [exception]

namespace std { class exception { public: constexpr exception() noexcept; constexpr exception(const exception&) noexcept; constexpr exception& operator=(const exception&) noexcept; constexpr virtual ~exception(); constexpr virtual const char* what() const noexcept; }; }
The class exception defines the base class for the types of objects thrown as exceptions by C++ standard library components, and certain expressions, to report errors detected during program execution.
Except where explicitly specified otherwise, each standard library class T that derives from class exception has the following publicly accessible member functions, each of them having a non-throwing exception specification ([except.spec]):
  • default constructor (unless the class synopsis shows other constructors)
  • copy constructor
  • copy assignment operator
The copy constructor and the copy assignment operator meet the following postcondition: If two objects lhs and rhs both have dynamic type T and lhs is a copy of rhs, then strcmp(lhs.what(), rhs.what()) is equal to 0.
The what() member function of each such T satisfies the constraints specified for exception​::​what() (see below).
constexpr exception(const exception& rhs) noexcept; constexpr exception& operator=(const exception& rhs) noexcept;
Postconditions: If *this and rhs both have dynamic type exception then the value of the expression strcmp(what(), rhs.what()) shall equal 0.
constexpr virtual ~exception();
Effects: Destroys an object of class exception.
constexpr virtual const char* what() const noexcept;
Returns: An implementation-defined ntbs, which during constant evaluation is encoded with the ordinary literal encoding ([lex.ccon]).
Remarks: The message may be a null-terminated multibyte string, suitable for conversion and display as a wstring ([string.classes], [locale.codecvt]).
The return value remains valid until the exception object from which it is obtained is destroyed or a non-const member function of the exception object is called.

17.9.4 Class bad_exception [bad.exception]

namespace std { class bad_exception : public exception { public: // see [exception] for the specification of the special member functions constexpr const char* what() const noexcept override; }; }
The class bad_exception defines the type of the object referenced by the exception_ptr returned from a call to current_exception ([propagation]) when the currently active exception object fails to copy.
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

17.9.5 Abnormal termination [exception.terminate]

17.9.5.1 Type terminate_handler [terminate.handler]

using terminate_handler = void (*)();
The type of a handler function to be invoked by terminate when terminating exception processing.
Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller.
Default behavior: The implementation's default terminate_handler calls abort().

17.9.5.2 set_terminate [set.terminate]

terminate_handler set_terminate(terminate_handler f) noexcept;
Effects: Establishes the function designated by f as the current handler function for terminating exception processing.
Returns: The previous terminate_handler.
Remarks: It is unspecified whether a null pointer value designates the default terminate_handler.

17.9.5.3 get_terminate [get.terminate]

terminate_handler get_terminate() noexcept;
Returns: The current terminate_handler.
[Note 1: 
This can be a null pointer value.
— end note]

17.9.5.4 terminate [terminate]

[[noreturn]] void terminate() noexcept;
Effects: Calls a terminate_handler function.
It is unspecified which terminate_handler function will be called if an exception is active during a call to set_terminate.
Otherwise calls the current terminate_handler function.
[Note 1: 
A default terminate_handler is always considered a callable handler in this context.
— end note]
Remarks: Called by the implementation when exception handling must be abandoned for any of several reasons ([except.terminate]).
May also be called directly by the program.

17.9.6 uncaught_exceptions [uncaught.exceptions]

constexpr int uncaught_exceptions() noexcept;
Returns: The number of uncaught exceptions.
Remarks: When uncaught_exceptions() > 0, throwing an exception can result in a call of the function std​::​terminate.

17.9.7 Exception propagation [propagation]

using exception_ptr = unspecified;
The type exception_ptr can be used to refer to an exception object.
exception_ptr meets the requirements of Cpp17NullablePointer (Table 36).
Two non-null values of type exception_ptr are equivalent and compare equal if and only if they refer to the same exception.
The default constructor of exception_ptr produces the null value of the type.
exception_ptr shall not be implicitly convertible to any arithmetic, enumeration, or pointer type.
[Note 1: 
An implementation can use a reference-counted smart pointer as exception_ptr.
— end note]
For purposes of determining the presence of a data race, operations on exception_ptr objects shall access and modify only the exception_ptr objects themselves and not the exceptions they refer to.
Use of rethrow_exception on exception_ptr objects that refer to the same exception object shall not introduce a data race.
[Note 2: 
If rethrow_exception rethrows the same exception object (rather than a copy), concurrent access to that rethrown exception object can introduce a data race.
Changes in the number of exception_ptr objects that refer to a particular exception do not introduce a data race.
— end note]
All member functions are marked constexpr.
constexpr exception_ptr current_exception() noexcept;
Returns: An exception_ptr object that refers to the currently handled exception or a copy of the currently handled exception, or a null exception_ptr object if no exception is being handled.
The referenced object shall remain valid at least as long as there is an exception_ptr object that refers to it.
If the function needs to allocate memory and the attempt fails, it returns an exception_ptr object that refers to an instance of bad_alloc.
It is unspecified whether the return values of two successive calls to current_exception refer to the same exception object.
[Note 3: 
That is, it is unspecified whether current_exception creates a new copy each time it is called.
— end note]
If the attempt to copy the current exception object throws an exception, the function returns an exception_ptr object that refers to the thrown exception or, if this is not possible, to an instance of bad_exception.
[Note 4: 
The copy constructor of the thrown exception can also fail, so the implementation can substitute a bad_exception object to avoid infinite recursion.
— end note]
[[noreturn]] constexpr void rethrow_exception(exception_ptr p);
Preconditions: p is not a null pointer.
Effects: Let u be the exception object to which p refers, or a copy of that exception object.
It is unspecified whether a copy is made, and memory for the copy is allocated in an unspecified way.
  • If allocating memory to form u fails, throws an instance of bad_alloc;
  • otherwise, if copying the exception to which p refers to form u throws an exception, throws that exception;
  • otherwise, throws u.
template<class E> constexpr exception_ptr make_exception_ptr(E e) noexcept;
Effects: Creates an exception_ptr object that refers to a copy of e, as if: try { throw e; } catch(...) { return current_exception(); }
[Note 5: 
This function is provided for convenience and efficiency reasons.
— end note]

17.9.8 nested_exception [except.nested]

namespace std { class nested_exception { public: constexpr nested_exception() noexcept; constexpr nested_exception(const nested_exception&) noexcept = default; constexpr nested_exception& operator=(const nested_exception&) noexcept = default; constexpr virtual ~nested_exception() = default; // access functions [[noreturn]] constexpr void rethrow_nested() const; constexpr exception_ptr nested_ptr() const noexcept; }; template<class T> [[noreturn]] constexpr void throw_with_nested(T&& t); template<class E> constexpr void rethrow_if_nested(const E& e); }
The class nested_exception is designed for use as a mixin through multiple inheritance.
It captures the currently handled exception and stores it for later use.
[Note 1: 
nested_exception has a virtual destructor to make it a polymorphic class.
Its presence can be tested for with dynamic_cast.
— end note]
constexpr nested_exception() noexcept;
Effects: The constructor calls current_exception() and stores the returned value.
[[noreturn]] constexpr void rethrow_nested() const;
Effects: If nested_ptr() returns a null pointer, the function calls the function std​::​terminate.
Otherwise, it throws the stored exception captured by *this.
constexpr exception_ptr nested_ptr() const noexcept;
Returns: The stored exception captured by this nested_exception object.
template<class T> [[noreturn]] constexpr void throw_with_nested(T&& t);
Let U be decay_t<T>.
Preconditions: U meets the Cpp17CopyConstructible requirements.
Throws: If is_class_v<U> && !is_final_v<U> && !is_base_of_v<nested_exception, U> is true, an exception of unspecified type that is publicly derived from both U and nested_exception and constructed from std​::​forward<T>(t), otherwise std​::​forward<T>(t).
template<class E> constexpr void rethrow_if_nested(const E& e);
Effects: If E is not a polymorphic class type, or if nested_exception is an inaccessible or ambiguous base class of E, there is no effect.
Otherwise, performs: if (auto p = dynamic_cast<const nested_exception*>(addressof(e))) p->rethrow_nested();

17.10 Initializer lists [support.initlist]

17.10.1 General [support.initlist.general]

The header <initializer_list> defines a class template and several support functions related to list-initialization (see [dcl.init.list]).
All functions specified in [support.initlist] are signal-safe ([support.signal]).

17.10.2 Header <initializer_list> synopsis [initializer.list.syn]

// all freestanding namespace std { template<class E> class initializer_list { public: using value_type = E; using reference = const E&; using const_reference = const E&; using size_type = size_t; using iterator = const E*; using const_iterator = const E*; constexpr initializer_list() noexcept; constexpr size_t size() const noexcept; // number of elements constexpr const E* begin() const noexcept; // first element constexpr const E* end() const noexcept; // one past the last element }; // [support.initlist.range], initializer list range access template<class E> constexpr const E* begin(initializer_list<E> il) noexcept; template<class E> constexpr const E* end(initializer_list<E> il) noexcept; }
An object of type initializer_list<E> provides access to an array of objects of type const E.
[Note 1: 
A pair of pointers or a pointer plus a length would be obvious representations for initializer_list.
initializer_list is used to implement initializer lists as specified in [dcl.init.list].
Copying an initializer_list does not copy the underlying elements.
— end note]
If an explicit specialization or partial specialization of initializer_list is declared, the program is ill-formed.

17.10.3 Initializer list constructors [support.initlist.cons]

constexpr initializer_list() noexcept;
Postconditions: size() == 0.

17.10.4 Initializer list access [support.initlist.access]

constexpr const E* begin() const noexcept;
Returns: A pointer to the beginning of the array.
If size() == 0 the values of begin() and end() are unspecified but they shall be identical.
constexpr const E* end() const noexcept;
Returns: begin() + size().
constexpr size_t size() const noexcept;
Returns: The number of elements in the array.
Complexity: Constant time.

17.10.5 Initializer list range access [support.initlist.range]

template<class E> constexpr const E* begin(initializer_list<E> il) noexcept;
Returns: il.begin().
template<class E> constexpr const E* end(initializer_list<E> il) noexcept;
Returns: il.end().

17.11 Comparisons [cmp]

17.11.1 Header <compare> synopsis [compare.syn]

The header <compare> specifies types, objects, and functions for use primarily in connection with the three-way comparison operator.
// all freestanding namespace std { // [cmp.categories], comparison category types class partial_ordering; class weak_ordering; class strong_ordering; // named comparison functions constexpr bool is_eq (partial_ordering cmp) noexcept { return cmp == 0; } constexpr bool is_neq (partial_ordering cmp) noexcept { return cmp != 0; } constexpr bool is_lt (partial_ordering cmp) noexcept { return cmp < 0; } constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; } constexpr bool is_gt (partial_ordering cmp) noexcept { return cmp > 0; } constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; } // [cmp.common], common comparison category type template<class... Ts> struct common_comparison_category { using type = see below; }; template<class... Ts> using common_comparison_category_t = typename common_comparison_category<Ts...>::type; // [cmp.concept], concept three_way_comparable template<class T, class Cat = partial_ordering> concept three_way_comparable = see below; template<class T, class U, class Cat = partial_ordering> concept three_way_comparable_with = see below; // [cmp.result], result of three-way comparison template<class T, class U = T> struct compare_three_way_result; template<class T, class U = T> using compare_three_way_result_t = typename compare_three_way_result<T, U>::type; // [comparisons.three.way], class compare_three_way struct compare_three_way; // [cmp.alg], comparison algorithms inline namespace unspecified { inline constexpr unspecified strong_order = unspecified; inline constexpr unspecified weak_order = unspecified; inline constexpr unspecified partial_order = unspecified; inline constexpr unspecified compare_strong_order_fallback = unspecified; inline constexpr unspecified compare_weak_order_fallback = unspecified; inline constexpr unspecified compare_partial_order_fallback = unspecified; } }

17.11.2 Comparison category types [cmp.categories]

17.11.2.1 Preamble [cmp.categories.pre]

The types partial_ordering, weak_ordering, and strong_ordering are collectively termed the comparison category types.
Each is specified in terms of an exposition-only data member named value whose value typically corresponds to that of an enumerator from one of the following exposition-only enumerations: enum class ord { equal = 0, equivalent = equal, less = -1, greater = 1 }; // exposition only enum class ncmp { unordered = -127 }; // exposition only
[Note 1: 
The type strong_ordering corresponds to the term total ordering in mathematics.
— end note]
The relational and equality operators for the comparison category types are specified with an anonymous parameter of unspecified type.
This type shall be selected by the implementation such that these parameters can accept literal 0 as a corresponding argument.
[Example 1: 
nullptr_t meets this requirement.
— end example]
In this context, the behavior of a program that supplies an argument other than a literal 0 is undefined.
For the purposes of [cmp.categories], substitutability is the property that f(a) == f(b) is true whenever a == b is true, where f denotes a function that reads only comparison-salient state that is accessible via the argument's public const members.

17.11.2.2 Class partial_ordering [cmp.partialord]

The partial_ordering type is typically used as the result type of a three-way comparison operator ([expr.spaceship]) for a type that admits all of the six two-way comparison operators ([expr.rel], [expr.eq]), for which equality need not imply substitutability, and that permits two values to be incomparable.192
namespace std { class partial_ordering { int value; // exposition only bool is_ordered; // exposition only // exposition-only constructors constexpr explicit partial_ordering(ord v) noexcept : value(int(v)), is_ordered(true) {} // exposition only constexpr explicit partial_ordering(ncmp v) noexcept : value(int(v)), is_ordered(false) {} // exposition only public: // valid values static const partial_ordering less; static const partial_ordering equivalent; static const partial_ordering greater; static const partial_ordering unordered; // comparisons friend constexpr bool operator==(partial_ordering v, unspecified) noexcept; friend constexpr bool operator==(partial_ordering v, partial_ordering w) noexcept = default; friend constexpr bool operator< (partial_ordering v, unspecified) noexcept; friend constexpr bool operator> (partial_ordering v, unspecified) noexcept; friend constexpr bool operator<=(partial_ordering v, unspecified) noexcept; friend constexpr bool operator>=(partial_ordering v, unspecified) noexcept; friend constexpr bool operator< (unspecified, partial_ordering v) noexcept; friend constexpr bool operator> (unspecified, partial_ordering v) noexcept; friend constexpr bool operator<=(unspecified, partial_ordering v) noexcept; friend constexpr bool operator>=(unspecified, partial_ordering v) noexcept; friend constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept; friend constexpr partial_ordering operator<=>(unspecified, partial_ordering v) noexcept; }; // valid values' definitions inline constexpr partial_ordering partial_ordering::less(ord::less); inline constexpr partial_ordering partial_ordering::equivalent(ord::equivalent); inline constexpr partial_ordering partial_ordering::greater(ord::greater); inline constexpr partial_ordering partial_ordering::unordered(ncmp::unordered); }
constexpr bool operator==(partial_ordering v, unspecified) noexcept; constexpr bool operator< (partial_ordering v, unspecified) noexcept; constexpr bool operator> (partial_ordering v, unspecified) noexcept; constexpr bool operator<=(partial_ordering v, unspecified) noexcept; constexpr bool operator>=(partial_ordering v, unspecified) noexcept;
Returns: For operator@, v.is_ordered && v.value @ 0.
constexpr bool operator< (unspecified, partial_ordering v) noexcept; constexpr bool operator> (unspecified, partial_ordering v) noexcept; constexpr bool operator<=(unspecified, partial_ordering v) noexcept; constexpr bool operator>=(unspecified, partial_ordering v) noexcept;
Returns: For operator@, v.is_ordered && 0 @ v.value.
constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept;
Returns: v.
constexpr partial_ordering operator<=>(unspecified, partial_ordering v) noexcept;
Returns: v < 0 ? partial_ordering​::​greater : v > 0 ? partial_ordering​::​less : v.
192)192)
That is, a < b, a == b, and a > b might all be false.

17.11.2.3 Class weak_ordering [cmp.weakord]

The weak_ordering type is typically used as the result type of a three-way comparison operator ([expr.spaceship]) for a type that admits all of the six two-way comparison operators ([expr.rel], [expr.eq]) and for which equality need not imply substitutability.
namespace std { class weak_ordering { int value; // exposition only // exposition-only constructors constexpr explicit weak_ordering(ord v) noexcept : value(int(v)) {} // exposition only public: // valid values static const weak_ordering less; static const weak_ordering equivalent; static const weak_ordering greater; // conversions constexpr operator partial_ordering() const noexcept; // comparisons friend constexpr bool operator==(weak_ordering v, unspecified) noexcept; friend constexpr bool operator==(weak_ordering v, weak_ordering w) noexcept = default; friend constexpr bool operator< (weak_ordering v, unspecified) noexcept; friend constexpr bool operator> (weak_ordering v, unspecified) noexcept; friend constexpr bool operator<=(weak_ordering v, unspecified) noexcept; friend constexpr bool operator>=(weak_ordering v, unspecified) noexcept; friend constexpr bool operator< (unspecified, weak_ordering v) noexcept; friend constexpr bool operator> (unspecified, weak_ordering v) noexcept; friend constexpr bool operator<=(unspecified, weak_ordering v) noexcept; friend constexpr bool operator>=(unspecified, weak_ordering v) noexcept; friend constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept; friend constexpr weak_ordering operator<=>(unspecified, weak_ordering v) noexcept; }; // valid values' definitions inline constexpr weak_ordering weak_ordering::less(ord::less); inline constexpr weak_ordering weak_ordering::equivalent(ord::equivalent); inline constexpr weak_ordering weak_ordering::greater(ord::greater); }
constexpr operator partial_ordering() const noexcept;
Returns: value == 0 ? partial_ordering::equivalent : value < 0 ? partial_ordering::less : partial_ordering::greater
constexpr bool operator==(weak_ordering v, unspecified) noexcept; constexpr bool operator< (weak_ordering v, unspecified) noexcept; constexpr bool operator> (weak_ordering v, unspecified) noexcept; constexpr bool operator<=(weak_ordering v, unspecified) noexcept; constexpr bool operator>=(weak_ordering v, unspecified) noexcept;
Returns: v.value @ 0 for operator@.
constexpr bool operator< (unspecified, weak_ordering v) noexcept; constexpr bool operator> (unspecified, weak_ordering v) noexcept; constexpr bool operator<=(unspecified, weak_ordering v) noexcept; constexpr bool operator>=(unspecified, weak_ordering v) noexcept;
Returns: 0 @ v.value for operator@.
constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept;
Returns: v.
constexpr weak_ordering operator<=>(unspecified, weak_ordering v) noexcept;
Returns: v < 0 ? weak_ordering​::​greater : v > 0 ? weak_ordering​::​less : v.

17.11.2.4 Class strong_ordering [cmp.strongord]

The strong_ordering type is typically used as the result type of a three-way comparison operator ([expr.spaceship]) for a type that admits all of the six two-way comparison operators ([expr.rel], [expr.eq]) and for which equality does imply substitutability.
namespace std { class strong_ordering { int value; // exposition only // exposition-only constructors constexpr explicit strong_ordering(ord v) noexcept : value(int(v)) {} // exposition only public: // valid values static const strong_ordering less; static const strong_ordering equal; static const strong_ordering equivalent; static const strong_ordering greater; // conversions constexpr operator partial_ordering() const noexcept; constexpr operator weak_ordering() const noexcept; // comparisons friend constexpr bool operator==(strong_ordering v, unspecified) noexcept; friend constexpr bool operator==(strong_ordering v, strong_ordering w) noexcept = default; friend constexpr bool operator< (strong_ordering v, unspecified) noexcept; friend constexpr bool operator> (strong_ordering v, unspecified) noexcept; friend constexpr bool operator<=(strong_ordering v, unspecified) noexcept; friend constexpr bool operator>=(strong_ordering v, unspecified) noexcept; friend constexpr bool operator< (unspecified, strong_ordering v) noexcept; friend constexpr bool operator> (unspecified, strong_ordering v) noexcept; friend constexpr bool operator<=(unspecified, strong_ordering v) noexcept; friend constexpr bool operator>=(unspecified, strong_ordering v) noexcept; friend constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept; friend constexpr strong_ordering operator<=>(unspecified, strong_ordering v) noexcept; }; // valid values' definitions inline constexpr strong_ordering strong_ordering::less(ord::less); inline constexpr strong_ordering strong_ordering::equal(ord::equal); inline constexpr strong_ordering strong_ordering::equivalent(ord::equivalent); inline constexpr strong_ordering strong_ordering::greater(ord::greater); }
constexpr operator partial_ordering() const noexcept;
Returns: value == 0 ? partial_ordering::equivalent : value < 0 ? partial_ordering::less : partial_ordering::greater
constexpr operator weak_ordering() const noexcept;
Returns: value == 0 ? weak_ordering::equivalent : value < 0 ? weak_ordering::less : weak_ordering::greater
constexpr bool operator==(strong_ordering v, unspecified) noexcept; constexpr bool operator< (strong_ordering v, unspecified) noexcept; constexpr bool operator> (strong_ordering v, unspecified) noexcept; constexpr bool operator<=(strong_ordering v, unspecified) noexcept; constexpr bool operator>=(strong_ordering v, unspecified) noexcept;
Returns: v.value @ 0 for operator@.
constexpr bool operator< (unspecified, strong_ordering v) noexcept; constexpr bool operator> (unspecified, strong_ordering v) noexcept; constexpr bool operator<=(unspecified, strong_ordering v) noexcept; constexpr bool operator>=(unspecified, strong_ordering v) noexcept;
Returns: 0 @ v.value for operator@.
constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept;
Returns: v.
constexpr strong_ordering operator<=>(unspecified, strong_ordering v) noexcept;
Returns: v < 0 ? strong_ordering​::​greater : v > 0 ? strong_ordering​::​less : v.

17.11.3 Class template common_comparison_category [cmp.common]

The type common_comparison_category provides an alias for the strongest comparison category to which all of the template arguments can be converted.
[Note 1: 
A comparison category type is stronger than another if they are distinct types and an instance of the former can be converted to an instance of the latter.
— end note]
template<class... Ts> struct common_comparison_category { using type = see below; };
Remarks: The member typedef-name type denotes the common comparison type ([class.spaceship]) of Ts..., the expanded parameter pack, or void if any element of Ts is not a comparison category type.
[Note 2: 
This is std​::​strong_ordering if the expansion is empty.
— end note]

17.11.4 Concept three_way_comparable [cmp.concept]

template<class T, class Cat> concept compares-as = // exposition only same_as<common_comparison_category_t<T, Cat>, Cat>; template<class T, class U> concept partially-ordered-with = // exposition only requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t < u } -> boolean-testable; { t > u } -> boolean-testable; { t <= u } -> boolean-testable; { t >= u } -> boolean-testable; { u < t } -> boolean-testable; { u > t } -> boolean-testable; { u <= t } -> boolean-testable; { u >= t } -> boolean-testable; };
Let t and u be lvalues of types const remove_reference_t<T> and const remove_reference_t<U>, respectively.
T and U model partially-ordered-with<T, U> only if
  • t < u, t <= u, t > u, t >= u, u < t, u <= t, u > t, and u >= t have the same domain,
  • bool(t < u) == bool(u > t) is true,
  • bool(u < t) == bool(t > u) is true,
  • bool(t <= u) == bool(u >= t) is true, and
  • bool(u <= t) == bool(t >= u) is true.
template<class T, class Cat = partial_ordering> concept three_way_comparable = weakly-equality-comparable-with<T, T> && partially-ordered-with<T, T> && requires(const remove_reference_t<T>& a, const remove_reference_t<T>& b) { { a <=> b } -> compares-as<Cat>; };
Let a and b be lvalues of type const remove_reference_t<T>.
T and Cat model three_way_comparable<T, Cat> only if
  • (a <=> b == 0) == bool(a == b) is true,
  • (a <=> b != 0) == bool(a != b) is true,
  • ((a <=> b) <=> 0) and (0 <=> (b <=> a)) are equal,
  • (a <=> b < 0) == bool(a < b) is true,
  • (a <=> b > 0) == bool(a > b) is true,
  • (a <=> b <= 0) == bool(a <= b) is true,
  • (a <=> b >= 0) == bool(a >= b) is true, and
  • if Cat is convertible to strong_ordering, T models totally_ordered ([concept.totallyordered]).
template<class T, class U, class Cat = partial_ordering> concept three_way_comparable_with = three_way_comparable<T, Cat> && three_way_comparable<U, Cat> && comparison-common-type-with<T, U> && three_way_comparable< common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>, Cat> && weakly-equality-comparable-with<T, U> && partially-ordered-with<T, U> && requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t <=> u } -> compares-as<Cat>; { u <=> t } -> compares-as<Cat>; };
Let t and t2 be lvalues denoting distinct equal objects of types const remove_reference_t<T> and remove_cvref_t<T>, respectively, and let u and u2 be lvalues denoting distinct equal objects of types const remove_reference_t<U> and remove_cvref_t<U>, respectively.
Let C be common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>.
Let CONVERT_TO_LVALUE<C>(E) be defined as in [concepts.compare.general].
T, U, and Cat model three_way_comparable_with<T, U, Cat> only if
  • t <=> u and u <=> t have the same domain,
  • ((t <=> u) <=> 0) and (0 <=> (u <=> t)) are equal,
  • (t <=> u == 0) == bool(t == u) is true,
  • (t <=> u != 0) == bool(t != u) is true,
  • Cat(t <=> u) == Cat(CONVERT_TO_LVALUE<C>(t2) <=> CONVERT_TO_LVALUE<C>(u2)) is true,
  • (t <=> u < 0) == bool(t < u) is true,
  • (t <=> u > 0) == bool(t > u) is true,
  • (t <=> u <= 0) == bool(t <= u) is true,
  • (t <=> u >= 0) == bool(t >= u) is true, and
  • if Cat is convertible to strong_ordering, T and U model totally_ordered_with<T, U> ([concept.totallyordered]).

17.11.5 Result of three-way comparison [cmp.result]

The behavior of a program that adds specializations for the compare_three_way_result template defined in this subclause is undefined.
For the compare_three_way_result type trait applied to the types T and U, let t and u denote lvalues of types const remove_reference_t<T> and const remove_reference_t<U>, respectively.
If the expression t <=> u is well-formed when treated as an unevaluated operand ([expr.context]), the member typedef-name type denotes the type decltype(t <=> u).
Otherwise, there is no member type.

17.11.6 Comparison algorithms [cmp.alg]

The name strong_order denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression strong_order(E, F) is expression-equivalent ([defns.expression.equivalent]) to the following:
  • If the decayed types of E and F differ, strong_order(E, F) is ill-formed.
  • Otherwise, strong_ordering(strong_order(E, F)) if it is a well-formed expression where the meaning of strong_order is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]).
  • Otherwise, if the decayed type T of E is a floating-point type, yields a value of type strong_ordering that is consistent with the ordering observed by T's comparison operators, and if numeric_limits<T>​::​is_iec559 is true, is additionally consistent with the totalOrder operation as specified in ISO/IEC 60559.
  • Otherwise, strong_ordering(compare_three_way()(E, F)) if it is a well-formed expression.
  • Otherwise, strong_order(E, F) is ill-formed.
[Note 1: 
Ill-formed cases above result in substitution failure when strong_order(E, F) appears in the immediate context of a template instantiation.
— end note]
The name weak_order denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression weak_order(E, F) is expression-equivalent ([defns.expression.equivalent]) to the following:
  • If the decayed types of E and F differ, weak_order(E, F) is ill-formed.
  • Otherwise, weak_ordering(weak_order(E, F)) if it is a well-formed expression where the meaning of weak_order is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]).
  • Otherwise, if the decayed type T of E is a floating-point type, yields a value of type weak_ordering that is consistent with the ordering observed by T's comparison operators and strong_order, and if numeric_limits<T>​::​is_iec559 is true, is additionally consistent with the following equivalence classes, ordered from lesser to greater:
  • Otherwise, weak_ordering(compare_three_way()(E, F)) if it is a well-formed expression.
  • Otherwise, weak_ordering(strong_order(E, F)) if it is a well-formed expression.
  • Otherwise, weak_order(E, F) is ill-formed.
[Note 2: 
Ill-formed cases above result in substitution failure when weak_order(E, F) appears in the immediate context of a template instantiation.
— end note]
The name partial_order denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression partial_order(E, F) is expression-equivalent ([defns.expression.equivalent]) to the following:
  • If the decayed types of E and F differ, partial_order(E, F) is ill-formed.
  • Otherwise, partial_ordering(partial_order(E, F)) if it is a well-formed expression where the meaning of partial_order is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]).
  • Otherwise, partial_ordering(compare_three_way()(E, F)) if it is a well-formed expression.
  • Otherwise, partial_ordering(weak_order(E, F)) if it is a well-formed expression.
  • Otherwise, partial_order(E, F) is ill-formed.
[Note 3: 
Ill-formed cases above result in substitution failure when partial_order(E, F) appears in the immediate context of a template instantiation.
— end note]
The name compare_strong_order_fallback denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression compare_strong_order_fallback(E, F) is expression-equivalent ([defns.expression.equivalent]) to:
  • If the decayed types of E and F differ, compare_strong_order_fallback(E, F) is ill-formed.
  • Otherwise, strong_order(E, F) if it is a well-formed expression.
  • Otherwise, if the expressions E == F and E < F are both well-formed and each of decltype(E == F) and decltype(E < F) models boolean-testable, E == F ? strong_ordering::equal : E < F ? strong_ordering::less : strong_ordering::greater except that E and F are evaluated only once.
  • Otherwise, compare_strong_order_fallback(E, F) is ill-formed.
[Note 4: 
Ill-formed cases above result in substitution failure when compare_strong_order_fallback(E, F) appears in the immediate context of a template instantiation.
— end note]
The name compare_weak_order_fallback denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression compare_weak_order_fallback(E, F) is expression-equivalent ([defns.expression.equivalent]) to:
  • If the decayed types of E and F differ, compare_weak_order_fallback(E, F) is ill-formed.
  • Otherwise, weak_order(E, F) if it is a well-formed expression.
  • Otherwise, if the expressions E == F and E < F are both well-formed and each of decltype(E == F) and decltype(E < F) models boolean-testable, E == F ? weak_ordering::equivalent : E < F ? weak_ordering::less : weak_ordering::greater except that E and F are evaluated only once.
  • Otherwise, compare_weak_order_fallback(E, F) is ill-formed.
[Note 5: 
Ill-formed cases above result in substitution failure when compare_weak_order_fallback(E, F) appears in the immediate context of a template instantiation.
— end note]
The name compare_partial_order_fallback denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expression compare_partial_order_fallback(E, F) is expression-equivalent ([defns.expression.equivalent]) to:
  • If the decayed types of E and F differ, compare_partial_order_fallback(E, F) is ill-formed.
  • Otherwise, partial_order(E, F) if it is a well-formed expression.
  • Otherwise, if the expressions E == F, E < F, and F < E are all well-formed and each of decltype(E == F), decltype(E < F), and decltype(F < E) models boolean-testable, E == F ? partial_ordering::equivalent : E < F ? partial_ordering::less : F < E ? partial_ordering::greater : partial_ordering::unordered except that E and F are evaluated only once.
  • Otherwise, compare_partial_order_fallback(E, F) is ill-formed.
[Note 6: 
Ill-formed cases above result in substitution failure when compare_partial_order_fallback(E, F) appears in the immediate context of a template instantiation.
— end note]

17.12 Coroutines [support.coroutine]

17.12.1 General [support.coroutine.general]

The header <coroutine> defines several types providing compile and run-time support for coroutines in a C++ program.

17.12.2 Header <coroutine> synopsis [coroutine.syn]

// all freestanding #include <compare> // see [compare.syn] namespace std { // [coroutine.traits], coroutine traits template<class R, class... ArgTypes> struct coroutine_traits; // [coroutine.handle], coroutine handle template<class Promise = void> struct coroutine_handle; // [coroutine.handle.compare], comparison operators constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; // [coroutine.handle.hash], hash support template<class T> struct hash; template<class P> struct hash<coroutine_handle<P>>; // [coroutine.noop], no-op coroutines struct noop_coroutine_promise; template<> struct coroutine_handle<noop_coroutine_promise>; using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; noop_coroutine_handle noop_coroutine() noexcept; // [coroutine.trivial.awaitables], trivial awaitables struct suspend_never; struct suspend_always; }

17.12.3 Coroutine traits [coroutine.traits]

17.12.3.1 General [coroutine.traits.general]

Subclause [coroutine.traits] defines requirements on classes representing coroutine traits, and defines the class template coroutine_traits that meets those requirements.

17.12.3.2 Class template coroutine_traits [coroutine.traits.primary]

The header <coroutine> defines the primary template coroutine_traits such that if ArgTypes is a parameter pack of types and if the qualified-id R​::​promise_type is valid and denotes a type ([temp.deduct]), then coroutine_traits<R, ArgTypes...> has the following publicly accessible member: using promise_type = typename R::promise_type;
Otherwise, coroutine_traits<R, ArgTypes...> has no members.
Program-defined specializations of this template shall define a publicly accessible nested type named promise_type.

17.12.4 Class template coroutine_handle [coroutine.handle]

17.12.4.1 General [coroutine.handle.general]

namespace std { template<> struct coroutine_handle<void> { // [coroutine.handle.con], construct/reset constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; coroutine_handle& operator=(nullptr_t) noexcept; // [coroutine.handle.export.import], export/import constexpr void* address() const noexcept; static constexpr coroutine_handle from_address(void* addr); // [coroutine.handle.observers], observers constexpr explicit operator bool() const noexcept; bool done() const; // [coroutine.handle.resumption], resumption void operator()() const; void resume() const; void destroy() const; private: void* ptr; // exposition only }; template<class Promise> struct coroutine_handle { // [coroutine.handle.con], construct/reset constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept; static coroutine_handle from_promise(Promise&); coroutine_handle& operator=(nullptr_t) noexcept; // [coroutine.handle.export.import], export/import constexpr void* address() const noexcept; static constexpr coroutine_handle from_address(void* addr); // [coroutine.handle.conv], conversion constexpr operator coroutine_handle<>() const noexcept; // [coroutine.handle.observers], observers constexpr explicit operator bool() const noexcept; bool done() const; // [coroutine.handle.resumption], resumption void operator()() const; void resume() const; void destroy() const; // [coroutine.handle.promise], promise access Promise& promise() const; private: void* ptr; // exposition only }; }
An object of type coroutine_handle<T> is called a coroutine handle and can be used to refer to a suspended or executing coroutine.
A coroutine_handle object whose member address() returns a null pointer value does not refer to any coroutine.
Two coroutine_handle objects refer to the same coroutine if and only if their member address() returns the same non-null value.
If a program declares an explicit or partial specialization of coroutine_handle, the behavior is undefined.

17.12.4.2 Construct/reset [coroutine.handle.con]

constexpr coroutine_handle() noexcept; constexpr coroutine_handle(nullptr_t) noexcept;
Postconditions: address() == nullptr.
static coroutine_handle from_promise(Promise& p);
Preconditions: p is a reference to a promise object of a coroutine.
Postconditions: addressof(h.promise()) == addressof(p).
Returns: A coroutine handle h referring to the coroutine.
coroutine_handle& operator=(nullptr_t) noexcept;
Postconditions: address() == nullptr.
Returns: *this.

17.12.4.3 Conversion [coroutine.handle.conv]

constexpr operator coroutine_handle<>() const noexcept;
Effects: Equivalent to: return coroutine_handle<>​::​from_address(address());

17.12.4.4 Export/import [coroutine.handle.export.import]

constexpr void* address() const noexcept;
Returns: ptr.
static constexpr coroutine_handle<> coroutine_handle<>::from_address(void* addr);
Preconditions: addr was obtained via a prior call to address on an object whose type is a specialization of coroutine_handle.
Postconditions: from_address(address()) == *this.
static constexpr coroutine_handle<Promise> coroutine_handle<Promise>::from_address(void* addr);
Preconditions: addr was obtained via a prior call to address on an object of type cv coroutine_handle<Promise>.
Postconditions: from_address(address()) == *this.

17.12.4.5 Observers [coroutine.handle.observers]

constexpr explicit operator bool() const noexcept;
Returns: address() != nullptr.
bool done() const;
Preconditions: *this refers to a suspended coroutine.
Returns: true if the coroutine is suspended at its final suspend point, otherwise false.

17.12.4.6 Resumption [coroutine.handle.resumption]

Resuming a coroutine via resume, operator(), or destroy on an execution agent other than the one on which it was suspended has implementation-defined behavior unless each execution agent either is an instance of std​::​thread or std​::​jthread, or is the thread that executes main.
[Note 1: 
A coroutine that is resumed on a different execution agent should avoid relying on consistent thread identity throughout, such as holding a mutex object across a suspend point.
— end note]
[Note 2: 
A concurrent resumption of the coroutine can result in a data race.
— end note]
void operator()() const; void resume() const;
Preconditions: *this refers to a suspended coroutine.
The coroutine is not suspended at its final suspend point.
Effects: Resumes the execution of the coroutine.
void destroy() const;
Preconditions: *this refers to a suspended coroutine.
Effects: Destroys the coroutine ([dcl.fct.def.coroutine]).

17.12.4.7 Promise access [coroutine.handle.promise]

Promise& promise() const;
Preconditions: *this refers to a coroutine.
Returns: A reference to the promise of the coroutine.

17.12.4.8 Comparison operators [coroutine.handle.compare]

constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept;
Returns: x.address() == y.address().
constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
Returns: compare_three_way()(x.address(), y.address()).

17.12.4.9 Hash support [coroutine.handle.hash]

template<class P> struct hash<coroutine_handle<P>>;
The specialization is enabled ([unord.hash]).

17.12.5 No-op coroutines [coroutine.noop]

17.12.5.1 Class noop_coroutine_promise [coroutine.promise.noop]

struct noop_coroutine_promise {};
The class noop_coroutine_promise defines the promise type for the coroutine referred to by noop_coroutine_handle ([coroutine.syn]).

17.12.5.2 Class coroutine_handle<noop_coroutine_promise> [coroutine.handle.noop]

17.12.5.2.1 General [coroutine.handle.noop.general]

namespace std { template<> struct coroutine_handle<noop_coroutine_promise> { // [coroutine.handle.noop.conv], conversion constexpr operator coroutine_handle<>() const noexcept; // [coroutine.handle.noop.observers], observers constexpr explicit operator bool() const noexcept; constexpr bool done() const noexcept; // [coroutine.handle.noop.resumption], resumption constexpr void operator()() const noexcept; constexpr void resume() const noexcept; constexpr void destroy() const noexcept; // [coroutine.handle.noop.promise], promise access noop_coroutine_promise& promise() const noexcept; // [coroutine.handle.noop.address], address constexpr void* address() const noexcept; private: coroutine_handle(unspecified); void* ptr; // exposition only }; }

17.12.5.2.2 Conversion [coroutine.handle.noop.conv]

constexpr operator coroutine_handle<>() const noexcept;
Effects: Equivalent to: return coroutine_handle<>​::​from_address(address());

17.12.5.2.3 Observers [coroutine.handle.noop.observers]

constexpr explicit operator bool() const noexcept;
Returns: true.
constexpr bool done() const noexcept;
Returns: false.

17.12.5.2.4 Resumption [coroutine.handle.noop.resumption]

constexpr void operator()() const noexcept; constexpr void resume() const noexcept; constexpr void destroy() const noexcept;
Effects: None.
Remarks: If noop_coroutine_handle is converted to coroutine_handle<>, calls to operator(), resume and destroy on that handle will also have no observable effects.

17.12.5.2.5 Promise access [coroutine.handle.noop.promise]

noop_coroutine_promise& promise() const noexcept;
Returns: A reference to the promise object associated with this coroutine handle.

17.12.5.2.6 Address [coroutine.handle.noop.address]

constexpr void* address() const noexcept;
Returns: ptr.
Remarks: A noop_coroutine_handle's ptr is always a non-null pointer value.

17.12.5.3 Function noop_coroutine [coroutine.noop.coroutine]

noop_coroutine_handle noop_coroutine() noexcept;
Returns: A handle to a coroutine that has no observable effects when resumed or destroyed.
Remarks: A handle returned from noop_coroutine may or may not compare equal to a handle returned from another invocation of noop_coroutine.

17.12.6 Trivial awaitables [coroutine.trivial.awaitables]

namespace std { struct suspend_never { constexpr bool await_ready() const noexcept { return true; } constexpr void await_suspend(coroutine_handle<>) const noexcept {} constexpr void await_resume() const noexcept {} }; struct suspend_always { constexpr bool await_ready() const noexcept { return false; } constexpr void await_suspend(coroutine_handle<>) const noexcept {} constexpr void await_resume() const noexcept {} }; }
[Note 1: 
The types suspend_never and suspend_always can be used to indicate that an await-expression either never suspends or always suspends, and in either case does not produce a value.
— end note]

17.13 Other runtime support [support.runtime]

17.13.1 General [support.runtime.general]

Headers <csetjmp> (nonlocal jumps), <csignal> (signal handling), <cstdarg> (variable arguments), and <cstdlib> (runtime environment getenv, system), provide further compatibility with C code.
Calls to the function getenv ([cstdlib.syn]) shall not introduce a data race ([res.on.data.races]) provided that nothing modifies the environment.
[Note 1: 
Calls to the POSIX functions setenv and putenv modify the environment.
— end note]
A call to the setlocale function may introduce a data race with other calls to the setlocale function or with calls to functions that are affected by the current C locale.
The implementation shall behave as if no library function other than locale​::​global calls the setlocale function.

17.13.2 Header <cstdarg> synopsis [cstdarg.syn]

// all freestanding namespace std { using va_list = see below; } #define va_arg(V, P) see below #define va_copy(VDST, VSRC) see below #define va_end(V) see below #define va_start(V, P) see below
The contents of the header <cstdarg> are the same as the C standard library header <stdarg.h>, with the following changes:
  • In lieu of the default argument promotions specified in ISO/IEC 9899:2018 6.5.2.2, the definition in [expr.call] applies.
  • The restrictions that C places on the second parameter to the va_start macro in header <stdarg.h> are different in this document.
    The parameter parmN is the rightmost parameter in the variable parameter list of the function definition (the one just before the ...).193
    If the parameter parmN is a pack expansion ([temp.variadic]) or an entity resulting from a lambda capture ([expr.prim.lambda]), the program is ill-formed, no diagnostic required.
    If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.
See also: ISO/IEC 9899:2018, 7.16.1.1
193)193)
Note that va_start is required to work as specified even if unary operator& is overloaded for the type of parmN.

17.13.3 Header <csetjmp> synopsis [csetjmp.syn]

namespace std { using jmp_buf = see below; [[noreturn]] void longjmp(jmp_buf env, int val); } #define setjmp(env) see below
The contents of the header <csetjmp> are the same as the C standard library header <setjmp.h>.
The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this document.
A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any objects with automatic storage duration.
A call to setjmp or longjmp has undefined behavior if invoked in a suspension context of a coroutine ([expr.await]).
See also: ISO/IEC 9899:2018, 7.13

17.13.4 Header <csignal> synopsis [csignal.syn]

namespace std { using sig_atomic_t = see below; // [support.signal], signal handlers extern "C" using signal-handler = void(int); // exposition only signal-handler* signal(int sig, signal-handler* func); int raise(int sig); } #define SIG_DFL see below #define SIG_ERR see below #define SIG_IGN see below #define SIGABRT see below #define SIGFPE see below #define SIGILL see below #define SIGINT see below #define SIGSEGV see below #define SIGTERM see below
The contents of the header <csignal> are the same as the C standard library header <signal.h>.

17.13.5 Signal handlers [support.signal]

A call to the function signal synchronizes with any resulting invocation of the signal handler so installed.
A plain lock-free atomic operation is an invocation of a function f from [atomics], such that:
  • f is the function atomic_is_lock_free(), or
  • f is the member function is_lock_free(), or
  • f is a non-static member function of class atomic_flag, or
  • f is a non-member function, and the first parameter of f has type cv atomic_flag*, or
  • f is a non-static member function invoked on an object A, such that A.is_lock_free() yields true, or
  • f is a non-member function, and for every pointer-to-atomic argument A passed to f, atomic_is_lock_free(A) yields true.
An evaluation is signal-safe unless it includes one of the following:
  • a call to any standard library function, except for plain lock-free atomic operations and functions explicitly identified as signal-safe;
    [Note 1: 
    This implicitly excludes the use of new and delete expressions that rely on a library-provided memory allocator.
    — end note]
  • an access to an object with thread storage duration;
  • a dynamic_cast expression;
  • throwing of an exception;
  • control entering a try-block or function-try-block;
  • initialization of a variable with static storage duration requiring dynamic initialization ([basic.start.dynamic], [stmt.dcl])194 ; or
  • waiting for the completion of the initialization of a variable with static storage duration ([stmt.dcl]).
A signal handler invocation has undefined behavior if it includes an evaluation that is not signal-safe.
The function signal is signal-safe if it is invoked with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler.
See also: ISO/IEC 9899:2018, 7.14
194)194)
Such initialization can occur because it is the first odr-use ([basic.def.odr]) of that variable.

17.14 C headers [support.c.headers]

17.14.1 General [support.c.headers.general]

For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 44.
The intended use of these headers is for interoperability only.
It is possible that C++ source files need to include one of these headers in order to be valid C. Source files that are not intended to also be valid C should not use any of the C headers.
[Note 1: 
The C headers either have no effect, such as <stdbool.h> and <stdalign.h>, or otherwise the corresponding header of the form <cname> provides the same facilities and assuredly defines them in namespace std.
— end note]
[Example 1: 
The following source file is both valid C++ and valid C. Viewed as C++, it declares a function with C language linkage; viewed as C it simply declares a function (and provides a prototype).
#include <stdbool.h> // for bool in C, no effect in C++ #include <stddef.h> // for size_t #ifdef __cplusplus // see [cpp.predefined] extern "C" // see [dcl.link] #endif void f(bool b[], size_t n); — end example]
Table 44 — C headers [tab:c.headers]
<assert.h>
<inttypes.h>
<signal.h>
<stddef.h>
<time.h>
<ctype.h>
<limits.h>
<stdarg.h>
<stdint.h>
<uchar.h>
<errno.h>
<locale.h>
<stdio.h>
<wchar.h>
<fenv.h>
<math.h>
<stdlib.h>
<wctype.h>
<float.h>
<setjmp.h>
<string.h>

17.14.2 Header <complex.h> synopsis [complex.h.syn]

#include <complex>
The header <complex.h> behaves as if it simply includes the header <complex>.
[Note 1: 
Names introduced by <complex> in namespace std are not placed into the global namespace scope by <complex.h>.
— end note]

17.14.3 Header <iso646.h> synopsis [iso646.h.syn]

The C++ header <iso646.h> is empty.
[Note 1: 
and, and_eq, bitand, bitor, compl, not_eq, not, or, or_eq, xor, and xor_eq are keywords in C++ ([lex.key]).
— end note]

17.14.4 Header <stdalign.h> synopsis [stdalign.h.syn]

The contents of the C++ header <stdalign.h> are the same as the C standard library header <stdalign.h>, with the following changes: The header <stdalign.h> does not define a macro named alignas.
See also: ISO/IEC 9899:2018, 7.15

17.14.5 Header <stdbool.h> synopsis [stdbool.h.syn]

The contents of the C++ header <stdbool.h> are the same as the C standard library header <stdbool.h>, with the following changes: The header <stdbool.h> does not define macros named bool, true, or false.
See also: ISO/IEC 9899:2018, 7.18

17.14.6 Header <tgmath.h> synopsis [tgmath.h.syn]

#include <cmath> #include <complex>
The header <tgmath.h> behaves as if it simply includes the headers <cmath> and <complex>.
[Note 1: 
The overloads provided in C by type-generic macros are already provided in <complex> and <cmath> by “sufficient” additional overloads.
— end note]
[Note 2: 
Names introduced by <cmath> or <complex> in namespace std are not placed into the global namespace scope by <tgmath.h>.
— end note]

17.14.7 Other C headers [support.c.headers.other]

Every C header other than <complex.h>, <iso646.h>, <stdalign.h>,
<stdatomic.h>, <stdbit.h>, <stdbool.h>, <stdckdint.h>, and
<tgmath.h>, each of which has a name of the form <name.h>, behaves as if each name placed in the standard library namespace by the corresponding <cname> header is placed within the global namespace scope, except for the functions described in [sf.cmath], the std​::​lerp function overloads ([c.math.lerp]), the declaration of std​::​byte ([cstddef.syn]), and the functions and function templates described in [support.types.byteops].
It is unspecified whether these names are first declared or defined within namespace scope ([basic.scope.namespace]) of the namespace std and are then injected into the global namespace scope by explicit using-declarations ([namespace.udecl]).
[Example 1: 
The header <cstdlib> assuredly provides its declarations and definitions within the namespace std.
It may also provide these names within the global namespace.
The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in ISO/IEC 9899.
It may also provide these names within the namespace std.
— end example]

18 Concepts library [concepts]

18.1 General [concepts.general]

This Clause describes library components that C++ programs may use to perform compile-time validation of template arguments and perform function dispatch based on properties of types.
The purpose of these concepts is to establish a foundation for equational reasoning in programs.
The following subclauses describe language-related concepts, comparison concepts, object concepts, and callable concepts as summarized in Table 45.
Table 45 — Fundamental concepts library summary [tab:concepts.summary]
Subclause
Header
Equality preservation
Language-related concepts
<concepts>
Comparison concepts
Object concepts
Callable concepts

18.2 Equality preservation [concepts.equality]

An expression is equality-preserving if, given equal inputs, the expression results in equal outputs.
The inputs to an expression are the set of the expression's operands.
The output of an expression is the expression's result and all operands modified by the expression.
For the purposes of this subclause, the operands of an expression are the largest subexpressions that include only:
[Example 1: 
The operands of the expression a = std​::​move(b) are a and std​::​move(b).
— end example]
Not all input values need be valid for a given expression.
[Example 2: 
For integers a and b, the expression a / b is not well-defined when b is 0.
This does not preclude the expression a / b being equality-preserving.
— end example]
The domain of an expression is the set of input values for which the expression is required to be well-defined.
Expressions required to be equality-preserving are further required to be stable: two evaluations of such an expression with the same input objects are required to have equal outputs absent any explicit intervening modification of those input objects.
[Note 1: 
This requirement allows generic code to reason about the current values of objects based on knowledge of the prior values as observed via equality-preserving expressions.
It effectively forbids spontaneous changes to an object, changes to an object from another thread of execution, changes to an object as side effects of non-modifying expressions, and changes to an object as side effects of modifying a distinct object if those changes could be observable to a library function via an equality-preserving expression that is required to be valid for that object.
— end note]
Expressions declared in a requires-expression in the library clauses are required to be equality-preserving, except for those annotated with the comment “not required to be equality-preserving.
An expression so annotated may be equality-preserving, but is not required to be so.
An expression that may alter the value of one or more of its inputs in a manner observable to equality-preserving expressions is said to modify those inputs.
The library clauses use a notational convention to specify which expressions declared in a requires-expression modify which inputs: except where otherwise specified, an expression operand that is a non-constant lvalue or rvalue may be modified.
Operands that are constant lvalues or rvalues are required to not be modified.
For the purposes of this subclause, the cv-qualification and value category of each operand are determined by assuming that each template type parameter denotes a cv-unqualified complete non-array object type.
Where a requires-expression declares an expression that is non-modifying for some constant lvalue operand, additional variations of that expression that accept a non-constant lvalue or (possibly constant) rvalue for the given operand are also required except where such an expression variation is explicitly required with differing semantics.
These implicit expression variations are required to meet the semantic requirements of the declared expression.
The extent to which an implementation validates the syntax of the variations is unspecified.
[Example 3: template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // #1 a = std::move(b); // #2 a = c; // #3 };
For the above example:
  • Expression #1 does not modify either of its operands, #2 modifies both of its operands, and #3 modifies only its first operand a.
  • Expression #1 implicitly requires additional expression variations that meet the requirements for c == d (including non-modification), as if the expressions c == b; c == std::move(d); c == std::move(b); std::move(c) == d; std::move(c) == b; std::move(c) == std::move(d); std::move(c) == std::move(b); a == d; a == b; a == std::move(d); a == std::move(b); std::move(a) == d; std::move(a) == b; std::move(a) == std::move(d); std::move(a) == std::move(b); had been declared as well.
  • Expression #3 implicitly requires additional expression variations that meet the requirements for a = c (including non-modification of the second operand), as if the expressions a = b and a = std​::​move(c) had been declared.
    Expression #3 does not implicitly require an expression variation with a non-constant rvalue second operand, since expression #2 already specifies exactly such an expression explicitly.
— end example]
[Example 4: 
The following type T meets the explicitly stated syntactic requirements of concept C above but does not meet the additional implicit requirements: struct T { bool operator==(const T&) const { return true; } bool operator==(T&) = delete; };
T fails to meet the implicit requirements of C, so T satisfies but does not model C.
Since implementations are not required to validate the syntax of implicit requirements, it is unspecified whether an implementation diagnoses as ill-formed a program that requires C<T>.
— end example]

18.3 Header <concepts> synopsis [concepts.syn]

// all freestanding namespace std { // [concepts.lang], language-related concepts // [concept.same], concept same_as template<class T, class U> concept same_as = see below; // [concept.derived], concept derived_from template<class Derived, class Base> concept derived_from = see below; // [concept.convertible], concept convertible_to template<class From, class To> concept convertible_to = see below; // [concept.commonref], concept common_reference_with template<class T, class U> concept common_reference_with = see below; // [concept.common], concept common_with template<class T, class U> concept common_with = see below; // [concepts.arithmetic], arithmetic concepts template<class T> concept integral = see below; template<class T> concept signed_integral = see below; template<class T> concept unsigned_integral = see below; template<class T> concept floating_point = see below; // [concept.assignable], concept assignable_from template<class LHS, class RHS> concept assignable_from = see below; // [concept.swappable], concept swappable namespace ranges { inline namespace unspecified { inline constexpr unspecified swap = unspecified; } } template<class T> concept swappable = see below; template<class T, class U> concept swappable_with = see below; // [concept.destructible], concept destructible template<class T> concept destructible = see below; // [concept.constructible], concept constructible_from template<class T, class... Args> concept constructible_from = see below; // [concept.default.init], concept default_initializable template<class T> concept default_initializable = see below; // [concept.moveconstructible], concept move_constructible template<class T> concept move_constructible = see below; // [concept.copyconstructible], concept copy_constructible template<class T> concept copy_constructible = see below; // [concepts.compare], comparison concepts // [concept.equalitycomparable], concept equality_comparable template<class T> concept equality_comparable = see below; template<class T, class U> concept equality_comparable_with = see below; // [concept.totallyordered], concept totally_ordered template<class T> concept totally_ordered = see below; template<class T, class U> concept totally_ordered_with = see below; // [concepts.object], object concepts template<class T> concept movable = see below; template<class T> concept copyable = see below; template<class T> concept semiregular = see below; template<class T> concept regular = see below; // [concepts.callable], callable concepts // [concept.invocable], concept invocable template<class F, class... Args> concept invocable = see below; // [concept.regularinvocable], concept regular_invocable template<class F, class... Args> concept regular_invocable = see below; // [concept.predicate], concept predicate template<class F, class... Args> concept predicate = see below; // [concept.relation], concept relation template<class R, class T, class U> concept relation = see below; // [concept.equiv], concept equivalence_relation template<class R, class T, class U> concept equivalence_relation = see below; // [concept.strictweakorder], concept strict_weak_order template<class R, class T, class U> concept strict_weak_order = see below; }

18.4 Language-related concepts [concepts.lang]

18.4.1 General [concepts.lang.general]

Subclause [concepts.lang] contains the definition of concepts corresponding to language features.
These concepts express relationships between types, type classifications, and fundamental type properties.

18.4.2 Concept same_as [concept.same]

template<class T, class U> concept same-as-impl = is_same_v<T, U>; // exposition only template<class T, class U> concept same_as = same-as-impl<T, U> && same-as-impl<U, T>;
[Note 1: 
same_as<T, U> subsumes same_as<U, T> and vice versa.
— end note]

18.4.3 Concept derived_from [concept.derived]

template<class Derived, class Base> concept derived_from = is_base_of_v<Base, Derived> && is_convertible_v<const volatile Derived*, const volatile Base*>;
[Note 1: 
derived_from<Derived, Base> is satisfied if and only if Derived is publicly and unambiguously derived from Base, or Derived and Base are the same class type ignoring cv-qualifiers.
— end note]

18.4.4 Concept convertible_to [concept.convertible]

Given types From and To and an expression E whose type and value category are the same as those of declval<From>(), convertible_to<From, To> requires E to be both implicitly and explicitly convertible to type To.
The implicit and explicit conversions are required to produce equal results.
template<class From, class To> concept convertible_to = is_convertible_v<From, To> && requires { static_cast<To>(declval<From>()); };
Let FromR be add_rvalue_reference_t<From> and test be the invented function: To test(FromR (&f)()) { return f(); } and let f be a function with no arguments and return type FromR such that f() is equality-preserving.
Types From and To model convertible_to<From, To> only if:
  • To is not an object or reference-to-object type, or static_cast<To>(f()) is equal to test(f).
  • FromR is not a reference-to-object type, or
    • If FromR is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by f() after either above expression is valid but unspecified ([lib.types.movedfrom]).
    • Otherwise, the object referred to by f() is not modified by either above expression.

18.4.5 Concept common_reference_with [concept.commonref]

For two types T and U, if common_reference_t<T, U> is well-formed and denotes a type C such that both convertible_to<T, C> and convertible_to<U, C> are modeled, then T and U share a common reference type, C.
[Note 1: 
C can be the same as T or U, or can be a different type.
C can be a reference type.
— end note]
template<class T, class U> concept common_reference_with = same_as<common_reference_t<T, U>, common_reference_t<U, T>> && convertible_to<T, common_reference_t<T, U>> && convertible_to<U, common_reference_t<T, U>>;
Let C be common_reference_t<T, U>.
Let t1 and t2 be equality-preserving expressions ([concepts.equality]) such that decltype((t1)) and decltype((t2)) are each T, and let u1 and u2 be equality-preserving expressions such that decltype((u1)) and decltype((u2)) are each U.
T and U model common_reference_with<T, U> only if
  • C(t1) equals C(t2) if and only if t1 equals t2, and
  • C(u1) equals C(u2) if and only if u1 equals u2.
[Note 2: 
Users can customize the behavior of common_reference_with by specializing the basic_common_reference class template ([meta.trans.other]).
— end note]

18.4.6 Concept common_with [concept.common]

If T and U can both be explicitly converted to some third type, C, then T and U share a common type, C.
[Note 1: 
C can be the same as T or U, or can be a different type.
C is not necessarily unique.
— end note]
template<class T, class U> concept common_with = same_as<common_type_t<T, U>, common_type_t<U, T>> && requires { static_cast<common_type_t<T, U>>(declval<T>()); static_cast<common_type_t<T, U>>(declval<U>()); } && common_reference_with< add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>> && common_reference_with< add_lvalue_reference_t<common_type_t<T, U>>, common_reference_t< add_lvalue_reference_t<const T>, add_lvalue_reference_t<const U>>>;
Let C be common_type_t<T, U>.
Let t1 and t2 be equality-preserving expressions ([concepts.equality]) such that decltype((t1)) and decltype((t2)) are each T, and let u1 and u2 be equality-preserving expressions such that decltype((u1)) and decltype((u2)) are each U.
T and U model common_with<T, U> only if
  • C(t1) equals C(t2) if and only if t1 equals t2, and
  • C(u1) equals C(u2) if and only if u1 equals u2.
[Note 2: 
Users can customize the behavior of common_with by specializing the common_type class template ([meta.trans.other]).
— end note]

18.4.7 Arithmetic concepts [concepts.arithmetic]

template<class T> concept integral = is_integral_v<T>; template<class T> concept signed_integral = integral<T> && is_signed_v<T>; template<class T> concept unsigned_integral = integral<T> && !signed_integral<T>; template<class T> concept floating_point = is_floating_point_v<T>;
[Note 1: 
signed_integral can be modeled even by types that are not signed integer types ([basic.fundamental]); for example, char.
— end note]
[Note 2: 
unsigned_integral can be modeled even by types that are not unsigned integer types ([basic.fundamental]); for example, bool.
— end note]

18.4.8 Concept assignable_from [concept.assignable]

template<class LHS, class RHS> concept assignable_from = is_lvalue_reference_v<LHS> && common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> && requires(LHS lhs, RHS&& rhs) { { lhs = std::forward<RHS>(rhs) } -> same_as<LHS>; };
Let:
  • lhs be an lvalue that refers to an object lcopy such that decltype((lhs)) is LHS,
  • rhs be an expression such that decltype((rhs)) is RHS, and
  • rcopy be a distinct object that is equal to rhs.
LHS and RHS model assignable_from<LHS, RHS> only if
  • addressof(lhs = rhs) == addressof(lcopy).
  • After evaluating lhs = rhs:
    • lhs is equal to rcopy, unless rhs is a non-const xvalue that refers to lcopy.
    • If rhs is a non-const xvalue, the resulting state of the object to which it refers is valid but unspecified ([lib.types.movedfrom]).
    • Otherwise, if rhs is a glvalue, the object to which it refers is not modified.
[Note 1: 
Assignment need not be a total function ([structure.requirements]); in particular, if assignment to an object x can result in a modification of some other object y, then x = y is likely not in the domain of =.
— end note]

18.4.9 Concept swappable [concept.swappable]

Let t1 and t2 be equality-preserving expressions that denote distinct equal objects of type T, and let u1 and u2 similarly denote distinct equal objects of type U.
[Note 1: 
t1 and u1 can denote distinct objects, or the same object.
— end note]
An operation exchanges the values denoted by t1 and u1 if and only if the operation modifies neither t2 nor u2 and:
  • If T and U are the same type, the result of the operation is that t1 equals u2 and u1 equals t2.
  • If T and U are different types and common_reference_with<decltype((t1)), decltype((u1))> is modeled, the result of the operation is that C(t1) equals C(u2) and C(u1) equals C(t2) where C is common_reference_t<decltype((t1)), decltype((u1))>.
The name ranges​::​swap denotes a customization point object ([customization.point.object]).
The expression ranges​::​swap(E1, E2) for subexpressions E1 and E2 is expression-equivalent to an expression S determined as follows:
  • S is (void)swap(E1, E2)195 if E1 or E2 has class or enumeration type ([basic.compound]) and that expression is valid, with overload resolution performed in a context that includes the declaration template<class T> void swap(T&, T&) = delete; and does not include a declaration of ranges​::​swap.
    If the function selected by overload resolution does not exchange the values denoted by E1 and E2, the program is ill-formed, no diagnostic required.
    [Note 2: 
    This precludes calling unconstrained program-defined overloads of swap.
    When the deleted overload is viable, program-defined overloads need to be more specialized ([temp.func.order]) to be selected.
    — end note]
  • Otherwise, if E1 and E2 are lvalues of array types ([basic.compound]) with equal extent and ranges​::​swap(*E1, *E2) is a valid expression, S is (void)ranges​::​swap_ranges(E1, E2), except that noexcept(S) is equal to noexcept(​ranges​::​swap(*E1, *E2)).
  • Otherwise, if E1 and E2 are lvalues of the same type T that models move_constructible<T> and assignable_from<T&, T>, S is an expression that exchanges the denoted values.
    S is a constant expression if noexcept(S) is equal to is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>.
  • Otherwise, ranges​::​swap(E1, E2) is ill-formed.
    [Note 3: 
    This case can result in substitution failure when ranges​::​swap(E1, E2) appears in the immediate context of a template instantiation.
    — end note]
[Note 4: 
Whenever ranges​::​swap(E1, E2) is a valid expression, it exchanges the values denoted by E1 and E2 and has type void.
— end note]
template<class T> concept swappable = requires(T& a, T& b) { ranges::swap(a, b); };
template<class T, class U> concept swappable_with = common_reference_with<T, U> && requires(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<T>(t)); ranges::swap(std::forward<U>(u), std::forward<U>(u)); ranges::swap(std::forward<T>(t), std::forward<U>(u)); ranges::swap(std::forward<U>(u), std::forward<T>(t)); };
[Note 5: 
The semantics of the swappable and swappable_with concepts are fully defined by the ranges​::​swap customization point object.
— end note]
[Example 1: 
User code can ensure that the evaluation of swap calls is performed in an appropriate context under the various conditions as follows: #include <cassert> #include <concepts> #include <utility> namespace ranges = std::ranges; template<class T, std::swappable_with<T> U> void value_swap(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<U>(u)); } template<std::swappable T> void lv_swap(T& t1, T& t2) { ranges::swap(t1, t2); } namespace N { struct A { int m; }; struct Proxy { A* a; Proxy(A& a) : a{&a} {} friend void swap(Proxy x, Proxy y) { ranges::swap(*x.a, *y.a); } }; Proxy proxy(A& a) { return Proxy{ a }; } } int main() { int i = 1, j = 2; lv_swap(i, j); assert(i == 2 && j == 1); N::A a1 = { 5 }, a2 = { -5 }; value_swap(a1, proxy(a2)); assert(a1.m == -5 && a2.m == 5); }
— end example]
195)195)
The name swap is used here unqualified.

18.4.10 Concept destructible [concept.destructible]

The destructible concept specifies properties of all types, instances of which can be destroyed at the end of their lifetime, or reference types.
template<class T> concept destructible = is_nothrow_destructible_v<T>;
[Note 1: 
Unlike the Cpp17Destructible requirements (Table 35), this concept forbids destructors that are potentially throwing, even if a particular invocation of the destructor does not actually throw.
— end note]

18.4.11 Concept constructible_from [concept.constructible]

The constructible_from concept constrains the initialization of a variable of a given type with a particular set of argument types.
template<class T, class... Args> concept constructible_from = destructible<T> && is_constructible_v<T, Args...>;

18.4.12 Concept default_initializable [concept.default.init]

template<class T> constexpr bool is-default-initializable = see below; // exposition only template<class T> concept default_initializable = constructible_from<T> && requires { T{}; } && is-default-initializable<T>;
For a type T, is-default-initializable<T> is true if and only if the variable definition T t; is well-formed for some invented variable t; otherwise it is false.
Access checking is performed as if in a context unrelated to T.
Only the validity of the immediate context of the variable initialization is considered.

18.4.13 Concept move_constructible [concept.moveconstructible]

template<class T> concept move_constructible = constructible_from<T, T> && convertible_to<T, T>;
If T is an object type, then let rv be an rvalue of type T and u2 a distinct object of type T equal to rv.
T models move_constructible only if
  • After the definition T u = rv;, u is equal to u2.
  • T(rv) is equal to u2.
  • If T is not const, rv's resulting state is valid but unspecified ([lib.types.movedfrom]); otherwise, it is unchanged.

18.4.14 Concept copy_constructible [concept.copyconstructible]

template<class T> concept copy_constructible = move_constructible<T> && constructible_from<T, T&> && convertible_to<T&, T> && constructible_from<T, const T&> && convertible_to<const T&, T> && constructible_from<T, const T> && convertible_to<const T, T>;
If T is an object type, then let v be an lvalue of type T or const T or an rvalue of type const T.
T models copy_constructible only if

18.5 Comparison concepts [concepts.compare]

18.5.1 General [concepts.compare.general]

Subclause [concepts.compare] describes concepts that establish relationships and orderings on values of possibly differing object types.
Given an expression E and a type C, let CONVERT_TO_LVALUE<C>(E) be:
  • static_cast<const C&>(as_const(E)) if that is a valid expression, and
  • static_cast<const C&>(std​::​move(E)) otherwise.

18.5.2 Boolean testability [concept.booleantestable]

The exposition-only boolean-testable concept specifies the requirements on expressions that are convertible to bool and for which the logical operators ([expr.log.and], [expr.log.or], [expr.unary.op]) have the conventional semantics.
template<class T> concept boolean-testable-impl = convertible_to<T, bool>; // exposition only
Let e be an expression such that decltype((e)) is T.
T models boolean-testable-impl only if
  • either remove_cvref_t<T> is not a class type, or a search for the names operator&& and operator|| in the scope of remove_cvref_t<T> finds nothing; and
  • argument-dependent lookup ([basic.lookup.argdep]) for the names operator&& and operator|| with T as the only argument type finds no disqualifying declaration (defined below).
A disqualifying parameter is a function parameter whose declared type P
  • is not dependent on a template parameter, and there exists an implicit conversion sequence ([over.best.ics]) from e to P; or
  • is dependent on one or more template parameters, and either
    • P contains no template parameter that participates in template argument deduction ([temp.deduct.type]), or
    • template argument deduction using the rules for deducing template arguments in a function call ([temp.deduct.call]) and e as the argument succeeds.
A key parameter of a function template D is a function parameter of type cv X or reference thereto, where X names a specialization of a class template that has the same innermost enclosing non-inline namespace as D, and X contains at least one template parameter that participates in template argument deduction.
[Example 1: 
In namespace Z { template<class> struct C {}; template<class T> void operator&&(C<T> x, T y); template<class T> void operator||(C<type_identity_t<T>> x, T y); } the declaration of Z​::​operator&& contains one key parameter, C<T> x, and the declaration of Z​::​operator|| contains no key parameters.
— end example]
A disqualifying declaration is
  • a (non-template) function declaration that contains at least one disqualifying parameter; or
  • a function template declaration that contains at least one disqualifying parameter, where
    • at least one disqualifying parameter is a key parameter; or
    • the declaration contains no key parameters; or
    • the declaration declares a function template to which no name is bound ([dcl.meaning]).
[Note 1: 
The intention is to ensure that given two types T1 and T2 that each model boolean-testable-impl, the && and || operators within the expressions declval<T1>() && declval<T2>() and declval<T1>() || declval<T2>() resolve to the corresponding built-in operators.
— end note]
template<class T> concept boolean-testable = // exposition only boolean-testable-impl<T> && requires(T&& t) { { !std::forward<T>(t) } -> boolean-testable-impl; };
Let e be an expression such that decltype((e)) is T.
T models boolean-testable only if bool(e) == !bool(!e).
[Example 2: 
The types bool, true_type ([meta.type.synop]), int*, and bitset<N>​::​reference ([template.bitset]) model boolean-testable.
— end example]

18.5.3 Comparison common types [concept.comparisoncommontype]

template<class T, class U, class C = common_reference_t<const T&, const U&>> concept comparison-common-type-with-impl = // exposition only same_as<common_reference_t<const T&, const U&>, common_reference_t<const U&, const T&>> && requires { requires convertible_to<const T&, const C&> || convertible_to<T, const C&>; requires convertible_to<const U&, const C&> || convertible_to<U, const C&>; }; template<class T, class U> concept comparison-common-type-with = // exposition only comparison-common-type-with-impl<remove_cvref_t<T>, remove_cvref_t<U>>;
Let C be common_reference_t<const T&, const U&>.
Let t1 and t2 be equality-preserving expressions that are lvalues of type remove_cvref_t<T>, and let u1 and u2 be equality-preserving expressions that are lvalues of type remove_cvref_t<U>.
T and U model comparison-common-type-with<T, U> only if
  • CONVERT_TO_LVALUE<C>(t1) equals CONVERT_TO_LVALUE<C>(t2) if and only if t1 equals t2, and
  • CONVERT_TO_LVALUE<C>(u1) equals CONVERT_TO_LVALUE<C>(u2) if and only if u1 equals u2

18.5.4 Concept equality_comparable [concept.equalitycomparable]

template<class T, class U> concept weakly-equality-comparable-with = // exposition only requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) { { t == u } -> boolean-testable; { t != u } -> boolean-testable; { u == t } -> boolean-testable; { u != t } -> boolean-testable; };
Given types T and U, let t and u be lvalues of types const remove_reference_t<T> and const remove_reference_t<U> respectively.
T and U model weakly-equality-comparable-with<T, U> only if
  • t == u, u == t, t != u, and u != t have the same domain.
  • bool(u == t) == bool(t == u).
  • bool(t != u) == !bool(t == u).
  • bool(u != t) == bool(t != u).
template<class T> concept equality_comparable = weakly-equality-comparable-with<T, T>;
Let a and b be objects of type T.
T models equality_comparable only if bool(a == b) is true when a is equal to b ([concepts.equality]), and false otherwise.
[Note 1: 
The requirement that the expression a == b is equality-preserving implies that == is transitive and symmetric.
— end note]
template<class T, class U> concept equality_comparable_with = equality_comparable<T> && equality_comparable<U> && comparison-common-type-with<T, U> && equality_comparable< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && weakly-equality-comparable-with<T, U>;
Given types T and U, let t and t2 be lvalues denoting distinct equal objects of types const remove_reference_t<T> and remove_cvref_t<T>, respectively, let u and u2 be lvalues denoting distinct equal objects of types const remove_reference_t<U> and remove_cvref_t<U>, respectively, and let C be: common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&> T and U model equality_comparable_with<T, U> only if bool(t == u) == bool(CONVERT_TO_LVALUE<C>(t2) == CONVERT_TO_LVALUE<C>(u2))

18.5.5 Concept totally_ordered [concept.totallyordered]

template<class T> concept totally_ordered = equality_comparable<T> && partially-ordered-with<T, T>;
Given a type T, let a, b, and c be lvalues of type const remove_reference_t<T>.
T models totally_ordered only if
  • Exactly one of bool(a < b), bool(a > b), or bool(a == b) is true.
  • If bool(a < b) and bool(b < c), then bool(a < c).
  • bool(a <= b) == !bool(b < a).
  • bool(a >= b) == !bool(a < b).
template<class T, class U> concept totally_ordered_with = totally_ordered<T> && totally_ordered<U> && equality_comparable_with<T, U> && totally_ordered< common_reference_t< const remove_reference_t<T>&, const remove_reference_t<U>&>> && partially-ordered-with<T, U>;
Given types T and U, let t and t2 be lvalues denoting distinct equal objects of types const remove_reference_t<T> and remove_cvref_t<T>, respectively, let u and u2 be lvalues denoting distinct equal objects of types const remove_reference_t<U> and remove_cvref_t<U>, respectively, and let C be: common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&> T and U model totally_ordered_with<T, U> only if
  • bool(t < u) == bool(CONVERT_TO_LVALUE<C>(t2) < CONVERT_TO_LVALUE<C>(u2)).
  • bool(t > u) == bool(CONVERT_TO_LVALUE<C>(t2) > CONVERT_TO_LVALUE<C>(u2)).
  • bool(t <= u) == bool(CONVERT_TO_LVALUE<C>(t2) <= CONVERT_TO_LVALUE<C>(u2)).
  • bool(t >= u) == bool(CONVERT_TO_LVALUE<C>(t2) >= CONVERT_TO_LVALUE<C>(u2)).
  • bool(u < t) == bool(CONVERT_TO_LVALUE<C>(u2) < CONVERT_TO_LVALUE<C>(t2)).
  • bool(u > t) == bool(CONVERT_TO_LVALUE<C>(u2) > CONVERT_TO_LVALUE<C>(t2)).
  • bool(u <= t) == bool(CONVERT_TO_LVALUE<C>(u2) <= CONVERT_TO_LVALUE<C>(t2)).
  • bool(u >= t) == bool(CONVERT_TO_LVALUE<C>(u2) >= CONVERT_TO_LVALUE<C>(t2)).

18.6 Object concepts [concepts.object]

This subclause describes concepts that specify the basis of the value-oriented programming style on which the library is based.
template<class T> concept movable = is_object_v<T> && move_constructible<T> && assignable_from<T&, T> && swappable<T>; template<class T> concept copyable = copy_constructible<T> && movable<T> && assignable_from<T&, T&> && assignable_from<T&, const T&> && assignable_from<T&, const T>; template<class T> concept semiregular = copyable<T> && default_initializable<T>; template<class T> concept regular = semiregular<T> && equality_comparable<T>;
[Note 1: 
The semiregular concept is modeled by types that behave similarly to fundamental types like int, except that they need not be comparable with ==.
— end note]
[Note 2: 
The regular concept is modeled by types that behave similarly to fundamental types like int and that are comparable with ==.
— end note]

18.7 Callable concepts [concepts.callable]

18.7.1 General [concepts.callable.general]

The concepts in [concepts.callable] describe the requirements on function objects ([function.objects]) and their arguments.

18.7.2 Concept invocable [concept.invocable]

The invocable concept specifies a relationship between a callable type ([func.def]) F and a set of argument types Args... which can be evaluated by the library function invoke ([func.invoke]).
template<class F, class... Args> concept invocable = requires(F&& f, Args&&... args) { invoke(std::forward<F>(f), std::forward<Args>(args)...); // not required to be equality-preserving };
[Example 1: 
A function that generates random numbers can model invocable, since the invoke function call expression is not required to be equality-preserving ([concepts.equality]).
— end example]

18.7.3 Concept regular_invocable [concept.regularinvocable]

template<class F, class... Args> concept regular_invocable = invocable<F, Args...>;
The invoke function call expression shall be equality-preserving ([concepts.equality]) and shall not modify the function object or the arguments.
[Note 1: 
This requirement supersedes the annotation in the definition of invocable.
— end note]
[Example 1: 
A random number generator does not model regular_invocable.
— end example]
[Note 2: 
The distinction between invocable and regular_invocable is purely semantic.
— end note]

18.7.4 Concept predicate [concept.predicate]

template<class F, class... Args> concept predicate = regular_invocable<F, Args...> && boolean-testable<invoke_result_t<F, Args...>>;

18.7.5 Concept relation [concept.relation]

template<class R, class T, class U> concept relation = predicate<R, T, T> && predicate<R, U, U> && predicate<R, T, U> && predicate<R, U, T>;

18.7.6 Concept equivalence_relation [concept.equiv]

template<class R, class T, class U> concept equivalence_relation = relation<R, T, U>;
A relation models equivalence_relation only if it imposes an equivalence relation on its arguments.

18.7.7 Concept strict_weak_order [concept.strictweakorder]

template<class R, class T, class U> concept strict_weak_order = relation<R, T, U>;
A relation models strict_weak_order only if it imposes a strict weak ordering on its arguments.
The term strict refers to the requirement of an irreflexive relation (!comp(x, x) for all x), and the term weak to requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering.
If we define equiv(a, b) as !comp(a, b) && !comp(b, a), then the requirements are that comp and equiv both be transitive relations:
  • comp(a, b) && comp(b, c) implies comp(a, c)
  • equiv(a, b) && equiv(b, c) implies equiv(a, c)
[Note 1: 
Under these conditions, it can be shown that
  • equiv is an equivalence relation,
  • comp induces a well-defined relation on the equivalence classes determined by equiv, and
  • the induced relation is a strict total ordering.
— end note]

19 Diagnostics library [diagnostics]

19.1 General [diagnostics.general]

This Clause describes components that C++ programs may use to detect and report error conditions.
The following subclauses describe components for reporting several kinds of exceptional conditions, documenting program assertions, obtaining stacktraces, and a global variable for error number codes, as summarized in Table 46.
Table 46 — Diagnostics library summary [tab:diagnostics.summary]
Subclause
Header
Exception classes
<stdexcept>
Assertions
<cassert>
Error numbers
<cerrno>
System error support
<system_error>
Stacktrace
<stacktrace>
Debugging
<debugging>

19.2 Exception classes [std.exceptions]

19.2.1 General [std.exceptions.general]

The C++ standard library provides classes to be used to report certain errors ([res.on.exception.handling]) in C++ programs.
In the error model reflected in these classes, errors are divided into two broad categories: logic errors and runtime errors.
The distinguishing characteristic of logic errors is that they are due to errors in the internal logic of the program.
In theory, they are preventable.
By contrast, runtime errors are due to events beyond the scope of the program.
They cannot be easily predicted in advance.
The header <stdexcept> defines several types of predefined exceptions for reporting errors in a C++ program.
These exceptions are related by inheritance.

19.2.2 Header <stdexcept> synopsis [stdexcept.syn]

namespace std { class logic_error; class domain_error; class invalid_argument; class length_error; class out_of_range; class runtime_error; class range_error; class overflow_error; class underflow_error; }

19.2.3 Class logic_error [logic.error]

namespace std { class logic_error : public exception { public: explicit logic_error(const string& what_arg); explicit logic_error(const char* what_arg); }; }
The class logic_error defines the type of objects thrown as exceptions to report errors presumably detectable before the program executes, such as violations of logical preconditions or class invariants.
logic_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
logic_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.4 Class domain_error [domain.error]

namespace std { class domain_error : public logic_error { public: explicit domain_error(const string& what_arg); explicit domain_error(const char* what_arg); }; }
The class domain_error defines the type of objects thrown as exceptions by the implementation to report domain errors.
domain_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
domain_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.5 Class invalid_argument [invalid.argument]

namespace std { class invalid_argument : public logic_error { public: explicit invalid_argument(const string& what_arg); explicit invalid_argument(const char* what_arg); }; }
The class invalid_argument defines the type of objects thrown as exceptions to report an invalid argument.
invalid_argument(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
invalid_argument(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.6 Class length_error [length.error]

namespace std { class length_error : public logic_error { public: explicit length_error(const string& what_arg); explicit length_error(const char* what_arg); }; }
The class length_error defines the type of objects thrown as exceptions to report an attempt to produce an object whose length exceeds its maximum allowable size.
length_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
length_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.7 Class out_of_range [out.of.range]

namespace std { class out_of_range : public logic_error { public: explicit out_of_range(const string& what_arg); explicit out_of_range(const char* what_arg); }; }
The class out_of_range defines the type of objects thrown as exceptions to report an argument value not in its expected range.
out_of_range(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
out_of_range(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.8 Class runtime_error [runtime.error]

namespace std { class runtime_error : public exception { public: explicit runtime_error(const string& what_arg); explicit runtime_error(const char* what_arg); }; }
The class runtime_error defines the type of objects thrown as exceptions to report errors presumably detectable only when the program executes.
runtime_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
runtime_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.9 Class range_error [range.error]

namespace std { class range_error : public runtime_error { public: explicit range_error(const string& what_arg); explicit range_error(const char* what_arg); }; }
The class range_error defines the type of objects thrown as exceptions to report range errors in internal computations.
range_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
range_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.10 Class overflow_error [overflow.error]

namespace std { class overflow_error : public runtime_error { public: explicit overflow_error(const string& what_arg); explicit overflow_error(const char* what_arg); }; }
The class overflow_error defines the type of objects thrown as exceptions to report an arithmetic overflow error.
overflow_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
overflow_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.2.11 Class underflow_error [underflow.error]

namespace std { class underflow_error : public runtime_error { public: explicit underflow_error(const string& what_arg); explicit underflow_error(const char* what_arg); }; }
The class underflow_error defines the type of objects thrown as exceptions to report an arithmetic underflow error.
underflow_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
underflow_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

19.3 Assertions [assertions]

19.3.1 General [assertions.general]

The header <cassert> provides a macro for documenting C++ program assertions and a mechanism for disabling the assertion checks through defining the macro NDEBUG.

19.3.2 Header <cassert> synopsis [cassert.syn]

#define assert(...) see below

19.3.3 The assert macro [assertions.assert]

If NDEBUG is defined as a macro name at the point in the source file where <cassert> is included, the assert macro is defined as #define assert(...) ((void)0)
Otherwise, the assert macro puts a diagnostic test into programs; it expands to an expression of type void which has the following effects:
  • __VA_ARGS__ is evaluated and contextually converted to bool.
  • If the evaluation yields true there are no further effects.
  • Otherwise, the assert macro's expression creates a diagnostic on the standard error stream in an implementation-defined format and calls abort().
    The diagnostic contains #__VA_ARGS__ and information on the name of the source file, the source line number, and the name of the enclosing function (such as provided by source_location​::​current()).
If __VA_ARGS__ does not expand to an assignment-expression, the program is ill-formed.
The macro assert is redefined according to the current state of NDEBUG each time that <cassert> is included.
An expression assert(E) is a constant subexpression, if

19.4 Error numbers [errno]

19.4.1 General [errno.general]

The contents of the header <cerrno> are the same as the POSIX header <errno.h>, except that errno shall be defined as a macro.
[Note 1: 
The intent is to remain in close alignment with the POSIX standard.
— end note]
A separate errno value is provided for each thread.

19.4.2 Header <cerrno> synopsis [cerrno.syn]

#define errno see below #define E2BIG see below // freestanding #define EACCES see below // freestanding #define EADDRINUSE see below // freestanding #define EADDRNOTAVAIL see below // freestanding #define EAFNOSUPPORT see below // freestanding #define EAGAIN see below // freestanding #define EALREADY see below // freestanding #define EBADF see below // freestanding #define EBADMSG see below // freestanding #define EBUSY see below // freestanding #define ECANCELED see below // freestanding #define ECHILD see below // freestanding #define ECONNABORTED see below // freestanding #define ECONNREFUSED see below // freestanding #define ECONNRESET see below // freestanding #define EDEADLK see below // freestanding #define EDESTADDRREQ see below // freestanding #define EDOM see below // freestanding #define EEXIST see below // freestanding #define EFAULT see below // freestanding #define EFBIG see below // freestanding #define EHOSTUNREACH see below // freestanding #define EIDRM see below // freestanding #define EILSEQ see below // freestanding #define EINPROGRESS see below // freestanding #define EINTR see below // freestanding #define EINVAL see below // freestanding #define EIO see below // freestanding #define EISCONN see below // freestanding #define EISDIR see below // freestanding #define ELOOP see below // freestanding #define EMFILE see below // freestanding #define EMLINK see below // freestanding #define EMSGSIZE see below // freestanding #define ENAMETOOLONG see below // freestanding #define ENETDOWN see below // freestanding #define ENETRESET see below // freestanding #define ENETUNREACH see below // freestanding #define ENFILE see below // freestanding #define ENOBUFS see below // freestanding #define ENODEV see below // freestanding #define ENOENT see below // freestanding #define ENOEXEC see below // freestanding #define ENOLCK see below // freestanding #define ENOLINK see below // freestanding #define ENOMEM see below // freestanding #define ENOMSG see below // freestanding #define ENOPROTOOPT see below // freestanding #define ENOSPC see below // freestanding #define ENOSYS see below // freestanding #define ENOTCONN see below // freestanding #define ENOTDIR see below // freestanding #define ENOTEMPTY see below // freestanding #define ENOTRECOVERABLE see below // freestanding #define ENOTSOCK see below // freestanding #define ENOTSUP see below // freestanding #define ENOTTY see below // freestanding #define ENXIO see below // freestanding #define EOPNOTSUPP see below // freestanding #define EOVERFLOW see below // freestanding #define EOWNERDEAD see below // freestanding #define EPERM see below // freestanding #define EPIPE see below // freestanding #define EPROTO see below // freestanding #define EPROTONOSUPPORT see below // freestanding #define EPROTOTYPE see below // freestanding #define ERANGE see below // freestanding #define EROFS see below // freestanding #define ESPIPE see below // freestanding #define ESRCH see below // freestanding #define ETIMEDOUT see below // freestanding #define ETXTBSY see below // freestanding #define EWOULDBLOCK see below // freestanding #define EXDEV see below // freestanding
The meaning of the macros in this header is defined by the POSIX standard.
See also: ISO/IEC 9899:2018, 7.5

19.5 System error support [syserr]

19.5.1 General [syserr.general]

Subclause [syserr] describes components that the standard library and C++ programs may use to report error conditions originating from the operating system or other low-level application program interfaces.
Components described in [syserr] do not change the value of errno ([errno]).
Recommended practice: Implementations should leave the error states provided by other libraries unchanged.

19.5.2 Header <system_error> synopsis [system.error.syn]

#include <compare> // see [compare.syn] namespace std { class error_category; const error_category& generic_category() noexcept; const error_category& system_category() noexcept; class error_code; class error_condition; class system_error; template<class T> struct is_error_code_enum : public false_type {}; template<class T> struct is_error_condition_enum : public false_type {}; enum class errc { // freestanding address_family_not_supported, // EAFNOSUPPORT address_in_use, // EADDRINUSE address_not_available, // EADDRNOTAVAIL already_connected, // EISCONN argument_list_too_long, // E2BIG argument_out_of_domain, // EDOM bad_address, // EFAULT bad_file_descriptor, // EBADF bad_message, // EBADMSG broken_pipe, // EPIPE connection_aborted, // ECONNABORTED connection_already_in_progress, // EALREADY connection_refused, // ECONNREFUSED connection_reset, // ECONNRESET cross_device_link, // EXDEV destination_address_required, // EDESTADDRREQ device_or_resource_busy, // EBUSY directory_not_empty, // ENOTEMPTY executable_format_error, // ENOEXEC file_exists, // EEXIST file_too_large, // EFBIG filename_too_long, // ENAMETOOLONG function_not_supported, // ENOSYS host_unreachable, // EHOSTUNREACH identifier_removed, // EIDRM illegal_byte_sequence, // EILSEQ inappropriate_io_control_operation, // ENOTTY interrupted, // EINTR invalid_argument, // EINVAL invalid_seek, // ESPIPE io_error, // EIO is_a_directory, // EISDIR message_size, // EMSGSIZE network_down, // ENETDOWN network_reset, // ENETRESET network_unreachable, // ENETUNREACH no_buffer_space, // ENOBUFS no_child_process, // ECHILD no_link, // ENOLINK no_lock_available, // ENOLCK no_message, // ENOMSG no_protocol_option, // ENOPROTOOPT no_space_on_device, // ENOSPC no_such_device_or_address, // ENXIO no_such_device, // ENODEV no_such_file_or_directory, // ENOENT no_such_process, // ESRCH not_a_directory, // ENOTDIR not_a_socket, // ENOTSOCK not_connected, // ENOTCONN not_enough_memory, // ENOMEM not_supported, // ENOTSUP operation_canceled, // ECANCELED operation_in_progress, // EINPROGRESS operation_not_permitted, // EPERM operation_not_supported, // EOPNOTSUPP operation_would_block, // EWOULDBLOCK owner_dead, // EOWNERDEAD permission_denied, // EACCES protocol_error, // EPROTO protocol_not_supported, // EPROTONOSUPPORT read_only_file_system, // EROFS resource_deadlock_would_occur, // EDEADLK resource_unavailable_try_again, // EAGAIN result_out_of_range, // ERANGE state_not_recoverable, // ENOTRECOVERABLE text_file_busy, // ETXTBSY timed_out, // ETIMEDOUT too_many_files_open_in_system, // ENFILE too_many_files_open, // EMFILE too_many_links, // EMLINK too_many_symbolic_link_levels, // ELOOP value_too_large, // EOVERFLOW wrong_protocol_type, // EPROTOTYPE }; template<> struct is_error_condition_enum<errc> : true_type {}; // [syserr.errcode.nonmembers], non-member functions error_code make_error_code(errc e) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const error_code& ec); // [syserr.errcondition.nonmembers], non-member functions error_condition make_error_condition(errc e) noexcept; // [syserr.compare], comparison operator functions bool operator==(const error_code& lhs, const error_code& rhs) noexcept; bool operator==(const error_code& lhs, const error_condition& rhs) noexcept; bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept; strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept; strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept; // [syserr.hash], hash support template<class T> struct hash; template<> struct hash<error_code>; template<> struct hash<error_condition>; // [syserr], system error support template<class T> constexpr bool is_error_code_enum_v = is_error_code_enum<T>::value; template<class T> constexpr bool is_error_condition_enum_v = is_error_condition_enum<T>::value; }
The value of each enum errc enumerator is the same as the value of the <cerrno> macro shown in the above synopsis.
Whether or not the <system_error> implementation exposes the <cerrno> macros is unspecified.
The is_error_code_enum and is_error_condition_enum templates may be specialized for program-defined types to indicate that such types are eligible for class error_code and class error_condition implicit conversions, respectively.

19.5.3 Class error_category [syserr.errcat]

19.5.3.1 Overview [syserr.errcat.overview]

The class error_category serves as a base class for types used to identify the source and encoding of a particular category of error code.
Classes may be derived from error_category to support categories of errors in addition to those defined in this document.
Such classes shall behave as specified in subclause [syserr.errcat].
[Note 1: 
error_category objects are passed by reference, and two such objects are equal if they have the same address.
If there is more than a single object of a custom error_category type, such equality comparisons can evaluate to false even for objects holding the same value.
— end note]
namespace std { class error_category { public: constexpr error_category() noexcept; virtual ~error_category(); error_category(const error_category&) = delete; error_category& operator=(const error_category&) = delete; virtual const char* name() const noexcept = 0; virtual error_condition default_error_condition(int ev) const noexcept; virtual bool equivalent(int code, const error_condition& condition) const noexcept; virtual bool equivalent(const error_code& code, int condition) const noexcept; virtual string message(int ev) const = 0; bool operator==(const error_category& rhs) const noexcept; strong_ordering operator<=>(const error_category& rhs) const noexcept; }; const error_category& generic_category() noexcept; const error_category& system_category() noexcept; }

19.5.3.2 Virtual members [syserr.errcat.virtuals]

virtual const char* name() const noexcept = 0;
Returns: A string naming the error category.
virtual error_condition default_error_condition(int ev) const noexcept;
Returns: error_condition(ev, *this).
virtual bool equivalent(int code, const error_condition& condition) const noexcept;
Returns: default_error_condition(code) == condition.
virtual bool equivalent(const error_code& code, int condition) const noexcept;
Returns: *this == code.category() && code.value() == condition.
virtual string message(int ev) const = 0;
Returns: A string that describes the error condition denoted by ev.

19.5.3.3 Non-virtual members [syserr.errcat.nonvirtuals]

bool operator==(const error_category& rhs) const noexcept;
Returns: this == &rhs.
strong_ordering operator<=>(const error_category& rhs) const noexcept;
Returns: compare_three_way()(this, &rhs).
[Note 1: 
compare_three_way ([comparisons.three.way]) provides a total ordering for pointers.
— end note]

19.5.3.4 Program-defined classes derived from error_category [syserr.errcat.derived]

virtual const char* name() const noexcept = 0;
Returns: A string naming the error category.
virtual error_condition default_error_condition(int ev) const noexcept;
Returns: An object of type error_condition that corresponds to ev.
virtual bool equivalent(int code, const error_condition& condition) const noexcept;
Returns: true if, for the category of error represented by *this, code is considered equivalent to condition; otherwise, false.
virtual bool equivalent(const error_code& code, int condition) const noexcept;
Returns: true if, for the category of error represented by *this, code is considered equivalent to condition; otherwise, false.

19.5.3.5 Error category objects [syserr.errcat.objects]

const error_category& generic_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
All calls to this function shall return references to the same object.
Remarks: The object's default_error_condition and equivalent virtual functions shall behave as specified for the class error_category.
The object's name virtual function shall return a pointer to the string "generic".
const error_category& system_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
All calls to this function shall return references to the same object.
Remarks: The object's equivalent virtual functions shall behave as specified for class error_category.
The object's name virtual function shall return a pointer to the string "system".
The object's default_error_condition virtual function shall behave as follows:
If the argument ev is equal to 0, the function returns error_condition(0, generic_category()).
Otherwise, if ev corresponds to a POSIX errno value pxv, the function returns error_condition(pxv, generic_category()).
Otherwise, the function returns error_condition(ev, system_category()).
What constitutes correspondence for any given operating system is unspecified.
[Note 1: 
The number of potential system error codes is large and unbounded, and some might not correspond to any POSIX errno value.
Thus implementations are given latitude in determining correspondence.
— end note]

19.5.4 Class error_code [syserr.errcode]

19.5.4.1 Overview [syserr.errcode.overview]

The class error_code describes an object used to hold error code values, such as those originating from the operating system or other low-level application program interfaces.
[Note 1: 
Class error_code is an adjunct to error reporting by exception.
— end note]
namespace std { class error_code { public: // [syserr.errcode.constructors], constructors error_code() noexcept; error_code(int val, const error_category& cat) noexcept; template<class ErrorCodeEnum> error_code(ErrorCodeEnum e) noexcept; // [syserr.errcode.modifiers], modifiers void assign(int val, const error_category& cat) noexcept; template<class ErrorCodeEnum> error_code& operator=(ErrorCodeEnum e) noexcept; void clear() noexcept; // [syserr.errcode.observers], observers int value() const noexcept; const error_category& category() const noexcept; error_condition default_error_condition() const noexcept; string message() const; explicit operator bool() const noexcept; private: int val_; // exposition only const error_category* cat_; // exposition only }; // [syserr.errcode.nonmembers], non-member functions error_code make_error_code(errc e) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const error_code& ec); }

19.5.4.2 Constructors [syserr.errcode.constructors]

error_code() noexcept;
Effects: Initializes val_ with 0 and cat_ with &system_category().
error_code(int val, const error_category& cat) noexcept;
Effects: Initializes val_ with val and cat_ with &cat.
template<class ErrorCodeEnum> error_code(ErrorCodeEnum e) noexcept;
Constraints: is_error_code_enum_v<ErrorCodeEnum> is true.
Effects: Equivalent to: error_code ec = make_error_code(e); assign(ec.value(), ec.category());

19.5.4.3 Modifiers [syserr.errcode.modifiers]

void assign(int val, const error_category& cat) noexcept;
Postconditions: val_ == val and cat_ == &cat.
template<class ErrorCodeEnum> error_code& operator=(ErrorCodeEnum e) noexcept;
Constraints: is_error_code_enum_v<ErrorCodeEnum> is true.
Effects: Equivalent to: error_code ec = make_error_code(e); assign(ec.value(), ec.category());
Returns: *this.
void clear() noexcept;
Postconditions: value() == 0 and category() == system_category().

19.5.4.4 Observers [syserr.errcode.observers]

int value() const noexcept;
Returns: val_.
const error_category& category() const noexcept;
Returns: *cat_.
error_condition default_error_condition() const noexcept;
Returns: category().default_error_condition(value()).
string message() const;
Returns: category().message(value()).
explicit operator bool() const noexcept;
Returns: value() != 0.

19.5.4.5 Non-member functions [syserr.errcode.nonmembers]

error_code make_error_code(errc e) noexcept;
Returns: error_code(static_cast<int>(e), generic_category()).
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const error_code& ec);
Effects: Equivalent to: return os << ec.category().name() << ':' << ec.value();

19.5.5 Class error_condition [syserr.errcondition]

19.5.5.1 Overview [syserr.errcondition.overview]

The class error_condition describes an object used to hold values identifying error conditions.
[Note 1: 
error_condition values are portable abstractions, while error_code values ([syserr.errcode]) are implementation specific.
— end note]
namespace std { class error_condition { public: // [syserr.errcondition.constructors], constructors error_condition() noexcept; error_condition(int val, const error_category& cat) noexcept; template<class ErrorConditionEnum> error_condition(ErrorConditionEnum e) noexcept; // [syserr.errcondition.modifiers], modifiers void assign(int val, const error_category& cat) noexcept; template<class ErrorConditionEnum> error_condition& operator=(ErrorConditionEnum e) noexcept; void clear() noexcept; // [syserr.errcondition.observers], observers int value() const noexcept; const error_category& category() const noexcept; string message() const; explicit operator bool() const noexcept; private: int val_; // exposition only const error_category* cat_; // exposition only }; }

19.5.5.2 Constructors [syserr.errcondition.constructors]

error_condition() noexcept;
Effects: Initializes val_ with 0 and cat_ with &generic_category().
error_condition(int val, const error_category& cat) noexcept;
Effects: Initializes val_ with val and cat_ with &cat.
template<class ErrorConditionEnum> error_condition(ErrorConditionEnum e) noexcept;
Constraints: is_error_condition_enum_v<ErrorConditionEnum> is true.
Effects: Equivalent to: error_condition ec = make_error_condition(e); assign(ec.value(), ec.category());

19.5.5.3 Modifiers [syserr.errcondition.modifiers]

void assign(int val, const error_category& cat) noexcept;
Postconditions: val_ == val and cat_ == &cat.
template<class ErrorConditionEnum> error_condition& operator=(ErrorConditionEnum e) noexcept;
Constraints: is_error_condition_enum_v<ErrorConditionEnum> is true.
Effects: Equivalent to: error_condition ec = make_error_condition(e); assign(ec.value(), ec.category());
Returns: *this.
void clear() noexcept;
Postconditions: value() == 0 and category() == generic_category().

19.5.5.4 Observers [syserr.errcondition.observers]

int value() const noexcept;
Returns: val_.
const error_category& category() const noexcept;
Returns: *cat_.
string message() const;
Returns: category().message(value()).
explicit operator bool() const noexcept;
Returns: value() != 0.

19.5.5.5 Non-member functions [syserr.errcondition.nonmembers]

error_condition make_error_condition(errc e) noexcept;
Returns: error_condition(static_cast<int>(e), generic_category()).

19.5.6 Comparison operator functions [syserr.compare]

bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
Returns: lhs.category() == rhs.category() && lhs.value() == rhs.value()
bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
Returns: lhs.category().equivalent(lhs.value(), rhs) || rhs.category().equivalent(lhs, rhs.value())
bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
Returns: lhs.category() == rhs.category() && lhs.value() == rhs.value()
strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept;
Effects: Equivalent to: if (auto c = lhs.category() <=> rhs.category(); c != 0) return c; return lhs.value() <=> rhs.value();
strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept;
Returns: if (auto c = lhs.category() <=> rhs.category(); c != 0) return c; return lhs.value() <=> rhs.value();

19.5.7 System error hash support [syserr.hash]

template<> struct hash<error_code>; template<> struct hash<error_condition>;
The specializations are enabled ([unord.hash]).

19.5.8 Class system_error [syserr.syserr]

19.5.8.1 Overview [syserr.syserr.overview]

The class system_error describes an exception object used to report error conditions that have an associated error code.
Such error conditions typically originate from the operating system or other low-level application program interfaces.
[Note 1: 
If an error represents an out-of-memory condition, implementations are encouraged to throw an exception object of type bad_alloc rather than system_error.
— end note]
namespace std { class system_error : public runtime_error { public: system_error(error_code ec, const string& what_arg); system_error(error_code ec, const char* what_arg); system_error(error_code ec); system_error(int ev, const error_category& ecat, const string& what_arg); system_error(int ev, const error_category& ecat, const char* what_arg); system_error(int ev, const error_category& ecat); const error_code& code() const noexcept; const char* what() const noexcept override; }; }

19.5.8.2 Members [syserr.syserr.members]

system_error(error_code ec, const string& what_arg);
Postconditions: code() == ec and
string_view(what()).find(what_arg.c_str()) != string_view​::​npos.
system_error(error_code ec, const char* what_arg);
Postconditions: code() == ec and string_view(what()).find(what_arg) != string_view​::​npos.
system_error(error_code ec);
Postconditions: code() == ec.
system_error(int ev, const error_category& ecat, const string& what_arg);
Postconditions: code() == error_code(ev, ecat) and
string_view(what()).find(what_arg.c_str()) != string_view​::​npos.
system_error(int ev, const error_category& ecat, const char* what_arg);
Postconditions: code() == error_code(ev, ecat) and
string_view(what()).find(what_arg) != string_view​::​npos.
system_error(int ev, const error_category& ecat);
Postconditions: code() == error_code(ev, ecat).
const error_code& code() const noexcept;
Returns: ec or error_code(ev, ecat), from the constructor, as appropriate.
const char* what() const noexcept override;
Returns: An ntbs incorporating the arguments supplied in the constructor.
[Note 1: 
The returned ntbs might be the contents of what_arg + ": " + code.message().
— end note]

19.6 Stacktrace [stacktrace]

19.6.1 General [stacktrace.general]

Subclause [stacktrace] describes components that C++ programs may use to store the stacktrace of the current thread of execution and query information about the stored stacktrace at runtime.
The invocation sequence of the current evaluation in the current thread of execution is a sequence of evaluations such that, for i  ≥ 0, is within the function invocation ([intro.execution]).
A stacktrace is an approximate representation of an invocation sequence and consists of stacktrace entries.
A stacktrace entry represents an evaluation in a stacktrace.

19.6.2 Header <stacktrace> synopsis [stacktrace.syn]

#include <compare> // see [compare.syn] namespace std { // [stacktrace.entry], class stacktrace_entry class stacktrace_entry; // [stacktrace.basic], class template basic_stacktrace template<class Allocator> class basic_stacktrace; // basic_stacktrace typedef-names using stacktrace = basic_stacktrace<allocator<stacktrace_entry>>; // [stacktrace.basic.nonmem], non-member functions template<class Allocator> void swap(basic_stacktrace<Allocator>& a, basic_stacktrace<Allocator>& b) noexcept(noexcept(a.swap(b))); string to_string(const stacktrace_entry& f); template<class Allocator> string to_string(const basic_stacktrace<Allocator>& st); ostream& operator<<(ostream& os, const stacktrace_entry& f); template<class Allocator> ostream& operator<<(ostream& os, const basic_stacktrace<Allocator>& st); // [stacktrace.format], formatting support template<> struct formatter<stacktrace_entry>; template<class Allocator> struct formatter<basic_stacktrace<Allocator>>; namespace pmr { using stacktrace = basic_stacktrace<polymorphic_allocator<stacktrace_entry>>; } // [stacktrace.basic.hash], hash support template<class T> struct hash; template<> struct hash<stacktrace_entry>; template<class Allocator> struct hash<basic_stacktrace<Allocator>>; }

19.6.3 Class stacktrace_entry [stacktrace.entry]

19.6.3.1 Overview [stacktrace.entry.overview]

namespace std { class stacktrace_entry { public: using native_handle_type = implementation-defined; // [stacktrace.entry.cons], constructors constexpr stacktrace_entry() noexcept; constexpr stacktrace_entry(const stacktrace_entry& other) noexcept; constexpr stacktrace_entry& operator=(const stacktrace_entry& other) noexcept; ~stacktrace_entry(); // [stacktrace.entry.obs], observers constexpr native_handle_type native_handle() const noexcept; constexpr explicit operator bool() const noexcept; // [stacktrace.entry.query], query string description() const; string source_file() const; uint_least32_t source_line() const; // [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; }; }
An object of type stacktrace_entry is either empty, or represents a stacktrace entry and provides operations for querying information about it.
The class stacktrace_entry models regular ([concepts.object]) and three_way_comparable<strong_ordering> ([cmp.concept]).

19.6.3.2 Constructors [stacktrace.entry.cons]

constexpr stacktrace_entry() noexcept;
Postconditions: *this is empty.

19.6.3.3 Observers [stacktrace.entry.obs]

constexpr native_handle_type native_handle() const noexcept;
The semantics of this function are implementation-defined.
Remarks: Successive invocations of the native_handle function for an unchanged stacktrace_entry object return identical values.
constexpr explicit operator bool() const noexcept;
Returns: false if and only if *this is empty.

19.6.3.4 Query [stacktrace.entry.query]

[Note 1: 
All the stacktrace_entry query functions treat errors other than memory allocation errors as “no information available” and do not throw in that case.
— end note]
string description() const;
Returns: A description of the evaluation represented by *this, or an empty string.
Throws: bad_alloc if memory for the internal data structures or the resulting string cannot be allocated.
string source_file() const;
Returns: The presumed or actual name of the source file ([cpp.predefined]) that lexically contains the expression or statement whose evaluation is represented by *this, or an empty string.
Throws: bad_alloc if memory for the internal data structures or the resulting string cannot be allocated.
uint_least32_t source_line() const;
Returns: 0, or a 1-based line number that lexically relates to the evaluation represented by *this.
If source_file returns the presumed name of the source file, returns the presumed line number; if source_file returns the actual name of the source file, returns the actual line number.
Throws: bad_alloc if memory for the internal data structures cannot be allocated.

19.6.3.5 Comparison [stacktrace.entry.cmp]

friend constexpr bool operator==(const stacktrace_entry& x, const stacktrace_entry& y) noexcept;
Returns: true if and only if x and y represent the same stacktrace entry or both x and y are empty.

19.6.4 Class template basic_stacktrace [stacktrace.basic]

19.6.4.1 Overview [stacktrace.basic.overview]

namespace std { template<class Allocator> class basic_stacktrace { public: using value_type = stacktrace_entry; using const_reference = const value_type&; using reference = value_type&; using const_iterator = implementation-defined; // see [stacktrace.basic.obs] using iterator = const_iterator; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using difference_type = implementation-defined; using size_type = implementation-defined; using allocator_type = Allocator; // [stacktrace.basic.cons], 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<allocator_type>); 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<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); ~basic_stacktrace(); // [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; 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; // [stacktrace.basic.cmp], comparisons template<class Allocator2> friend bool operator==(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept; template<class Allocator2> friend strong_ordering operator<=>(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept; // [stacktrace.basic.mod], modifiers void swap(basic_stacktrace& other) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value); private: vector<value_type, allocator_type> frames_; // exposition only }; }
The class template basic_stacktrace satisfies the requirements of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of a sequence container ([sequence.reqmts]), except that
  • only move, assignment, swap, and operations defined for const-qualified sequence containers are supported and,
  • the semantics of comparison functions are different from those required for a container.

19.6.4.2 Creation and assignment [stacktrace.basic.cons]

static basic_stacktrace current(const allocator_type& alloc = allocator_type()) noexcept;
Returns: A basic_stacktrace object with frames_ storing the stacktrace of the current evaluation in the current thread of execution, or an empty basic_stacktrace object if the initialization of frames_ failed.
alloc is passed to the constructor of the frames_ object.
[Note 1: 
If the stacktrace was successfully obtained, then frames_.front() is the stacktrace_entry representing approximately the current evaluation, and frames_.back() is the stacktrace_entry representing approximately the initial function of the current thread of execution.
— end note]
static basic_stacktrace current(size_type skip, const allocator_type& alloc = allocator_type()) noexcept;
Let t be a stacktrace as-if obtained via basic_stacktrace​::​current(alloc).
Let n be t.size().
Returns: A basic_stacktrace object where frames_ is direct-non-list-initialized from arguments t.begin() + min(n, skip), t.end(), and alloc, or an empty basic_stacktrace object if the initialization of frames_ failed.
static basic_stacktrace current(size_type skip, size_type max_depth, const allocator_type& alloc = allocator_type()) noexcept;
Let t be a stacktrace as-if obtained via basic_stacktrace​::​current(alloc).
Let n be t.size().
Preconditions: skip <= skip + max_depth is true.
Returns: A basic_stacktrace object where frames_ is direct-non-list-initialized from arguments t.begin() + min(n, skip), t.begin() + min(n, skip + max_depth), and alloc, or an empty basic_stacktrace object if the initialization of frames_ failed.
basic_stacktrace() noexcept(is_nothrow_default_constructible_v<allocator_type>);
Postconditions: empty() is true.
explicit basic_stacktrace(const allocator_type& alloc) noexcept;
Effects: alloc is passed to the frames_ constructor.
Postconditions: empty() is true.
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<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);
Remarks: Implementations may strengthen the exception specification for these functions ([res.on.exception.handling]) by ensuring that empty() is true on failed allocation.

19.6.4.3 Observers [stacktrace.basic.obs]

using const_iterator = implementation-defined;
The type models random_access_iterator ([iterator.concept.random.access]) and meets the Cpp17RandomAccessIterator requirements ([random.access.iterators]).
allocator_type get_allocator() const noexcept;
Returns: frames_.get_allocator().
const_iterator begin() const noexcept; const_iterator cbegin() const noexcept;
Returns: An iterator referring to the first element in frames_.
If empty() is true, then it returns the same value as end().
const_iterator end() const noexcept; const_iterator cend() const noexcept;
Returns: The end iterator.
const_reverse_iterator rbegin() const noexcept; const_reverse_iterator crbegin() const noexcept;
Returns: reverse_iterator(cend()).
const_reverse_iterator rend() const noexcept; const_reverse_iterator crend() const noexcept;
Returns: reverse_iterator(cbegin()).
bool empty() const noexcept;
Returns: frames_.empty().
size_type size() const noexcept;
Returns: frames_.size().
size_type max_size() const noexcept;
Returns: frames_.max_size().
const_reference operator[](size_type frame_no) const;
Preconditions: frame_no < size() is true.
Returns: frames_[frame_no].
Throws: Nothing.
const_reference at(size_type frame_no) const;
Returns: frames_[frame_no].
Throws: out_of_range if frame_no >= size().

19.6.4.4 Comparisons [stacktrace.basic.cmp]

template<class Allocator2> friend bool operator==(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept;
Returns: equal(x.begin(), x.end(), y.begin(), y.end()).
template<class Allocator2> friend strong_ordering operator<=>(const basic_stacktrace& x, const basic_stacktrace<Allocator2>& y) noexcept;
Returns: x.size() <=> y.size() if x.size() != y.size(); lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end()) otherwise.

19.6.4.5 Modifiers [stacktrace.basic.mod]

void swap(basic_stacktrace& other) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value);
Effects: Exchanges the contents of *this and other.

19.6.4.6 Non-member functions [stacktrace.basic.nonmem]

template<class Allocator> void swap(basic_stacktrace<Allocator>& a, basic_stacktrace<Allocator>& b) noexcept(noexcept(a.swap(b)));
Effects: Equivalent to a.swap(b).
string to_string(const stacktrace_entry& f);
Returns: A string with a description of f.
Recommended practice: The description should provide information about the contained evaluation, including information from f.source_file() and f.source_line().
template<class Allocator> string to_string(const basic_stacktrace<Allocator>& st);
Returns: A string with a description of st.
[Note 1: 
The number of lines is not guaranteed to be equal to st.size().
— end note]
ostream& operator<<(ostream& os, const stacktrace_entry& f);
Effects: Equivalent to: return os << to_string(f);
template<class Allocator> ostream& operator<<(ostream& os, const basic_stacktrace<Allocator>& st);
Effects: Equivalent to: return os << to_string(st);

19.6.5 Formatting support [stacktrace.format]

template<> struct formatter<stacktrace_entry>;
formatter<stacktrace_entry> interprets format-spec as a stacktrace-entry-format-spec.
The syntax of format specifications is as follows:
stacktrace-entry-format-spec:
fill-and-align width
[Note 1: 
The productions fill-and-align and width are described in [format.string.std].
— end note]
A stacktrace_entry object se is formatted as if by copying to_string(se) through the output iterator of the context with additional padding and adjustments as specified by the format specifiers.
template<class Allocator> struct formatter<basic_stacktrace<Allocator>>;
For formatter<basic_stacktrace<Allocator>>, format-spec is empty.
A basic_stacktrace<Allocator> object s is formatted as if by copying to_string(s) through the output iterator of the context.

19.6.6 Hash support [stacktrace.basic.hash]

template<> struct hash<stacktrace_entry>; template<class Allocator> struct hash<basic_stacktrace<Allocator>>;
The specializations are enabled ([unord.hash]).

19.7 Debugging [debugging]

19.7.1 General [debugging.general]

Subclause [debugging] describes functionality to introspect and interact with the execution of the program.
[Note 1: 
The facilities provided by the debugging functionality interact with a program that could be tracing the execution of a C++ program, such as a debugger.
— end note]

19.7.2 Header <debugging> synopsis [debugging.syn]

// all freestanding namespace std { // [debugging.utility], utility void breakpoint() noexcept; void breakpoint_if_debugging() noexcept; bool is_debugger_present() noexcept; }

19.7.3 Utility [debugging.utility]

void breakpoint() noexcept;
The semantics of this function are implementation-defined.
[Note 1: 
When invoked, the execution of the program temporarily halts and execution is handed to the debugger until such a time as: The program is terminated by the debugger, or the debugger resumes execution of the program as if the function was not invoked.
— end note]
void breakpoint_if_debugging() noexcept;
Effects: Equivalent to: if (is_debugger_present()) breakpoint();
bool is_debugger_present() noexcept;
Replaceable: A C++ program may define a function with this function signature, and thereby displace the default version defined by the C++ standard library.
Required behavior: This function has no preconditions.
Default behavior: implementation-defined.
[Note 2: 
When tracing the execution of a program with a debugger, an implementation returns true.
An implementation performs an immediate query, as needed, to determine if the program is traced by a debugger.
On Windows or equivalent systems, this can be achieved by calling the ​::​IsDebuggerPresent() Win32 function.
On POSIX, this can be achieved by checking for a tracer parent process, with best effort determination that such a tracer parent process is a debugger.
— end note]

20 Memory management library [mem]

20.1 General [mem.general]

This Clause describes components for memory management.
The following subclauses describe general memory management facilities, smart pointers, memory resources, and scoped allocators, as summarized in Table 47.
Table 47 — Memory management library summary [tab:mem.summary]
Subclause
Header
Memory
<cstdlib>, <memory>
Smart pointers
<memory>
Memory resources
<memory_resource>
Scoped allocators
<scoped_allocator>

20.2 Memory [memory]

20.2.1 General [memory.general]

Subclause [memory] describes the contents of the header <memory> and some of the contents of the header <cstdlib>.

20.2.2 Header <memory> synopsis [memory.syn]

The header <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 ([pointer.traits][specialized.addressof] and [specialized.algorithms]).
The header also defines the templates unique_ptr, shared_ptr, weak_ptr, out_ptr_t, inout_ptr_t, and various function templates that operate on objects of these types ([smartptr]).
Let POINTER_OF(T) denote a type that is
  • T​::​pointer if the qualified-id T​::​pointer is valid and denotes a type,
  • otherwise, T​::​element_type* if the qualified-id T​::​element_type is valid and denotes a type,
  • otherwise, pointer_traits<T>​::​element_type*.
Let POINTER_OF_OR(T, U) denote a type that is:
  • POINTER_OF(T) if POINTER_OF(T) is valid and denotes a type,
  • otherwise, U.
#include <compare> // see [compare.syn] namespace std { // [pointer.traits], pointer traits template<class Ptr> struct pointer_traits; // freestanding template<class T> struct pointer_traits<T*>; // freestanding // [pointer.conversion], pointer conversion template<class T> constexpr T* to_address(T* p) noexcept; // freestanding template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept; // freestanding // [ptr.align], pointer alignment void* align(size_t alignment, size_t size, void*& ptr, size_t& space); // freestanding template<size_t N, class T> constexpr T* assume_aligned(T* ptr); // freestanding template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr); // [obj.lifetime], explicit lifetime management template<class T> T* start_lifetime_as(void* p) noexcept; // freestanding template<class T> const T* start_lifetime_as(const void* p) noexcept; // freestanding template<class T> volatile T* start_lifetime_as(volatile void* p) noexcept; // freestanding template<class T> const volatile T* start_lifetime_as(const volatile void* p) noexcept; // freestanding template<class T> T* start_lifetime_as_array(void* p, size_t n) noexcept; // freestanding template<class T> const T* start_lifetime_as_array(const void* p, size_t n) noexcept; // freestanding template<class T> volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; // freestanding template<class T> const volatile T* start_lifetime_as_array(const volatile void* p, // freestanding size_t n) noexcept; // [allocator.tag], allocator argument tag struct allocator_arg_t { explicit allocator_arg_t() = default; }; // freestanding inline constexpr allocator_arg_t allocator_arg{}; // freestanding // [allocator.uses], uses_allocator template<class T, class Alloc> struct uses_allocator; // freestanding // [allocator.uses.trait], uses_allocator template<class T, class Alloc> constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; // freestanding // [allocator.uses.construction], uses-allocator construction template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding Args&&... args) noexcept; template<class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept; template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; // freestanding template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding U&& u, V&& v) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding pair<U, V>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding const pair<U, V>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding pair<U, V>&& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding const pair<U, V>&& pr) noexcept; template<class T, class Alloc, pair-like P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding P&& p) noexcept; template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, // freestanding U&& u) noexcept; template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); // freestanding template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, // freestanding const Alloc& alloc, Args&&... args); // [allocator.traits], allocator traits template<class Alloc> struct allocator_traits; // freestanding template<class Pointer, class SizeType = size_t> struct allocation_result { // freestanding Pointer ptr; SizeType count; }; // [default.allocator], the default allocator template<class T> class allocator; template<class T, class U> constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept; // [specialized.addressof], addressof template<class T> constexpr T* addressof(T& r) noexcept; // freestanding template<class T> const T* addressof(const T&&) = delete; // freestanding // [specialized.algorithms], specialized algorithms // [special.mem.concepts], special memory concepts template<class I> concept nothrow-input-iterator = see below; // exposition only template<class I> concept nothrow-forward-iterator = see below; // exposition only template<class S, class I> concept nothrow-sentinel-for = see below; // exposition only template<class R> concept nothrow-input-range = see below; // exposition only template<class R> concept nothrow-forward-range = see below; // exposition only template<class NoThrowForwardIterator> constexpr void uninitialized_default_construct(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last); template<class ExecutionPolicy, class NoThrowForwardIterator> void uninitialized_default_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, NoThrowForwardIterator last); template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n); // freestanding template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, Size n); namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct(I first, S last); // freestanding template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_default_construct(R&& r); // freestanding template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct_n(I first, // freestanding iter_difference_t<I> n); } template<class NoThrowForwardIterator> constexpr void uninitialized_value_construct(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last); template<class ExecutionPolicy, class NoThrowForwardIterator> void uninitialized_value_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, NoThrowForwardIterator last); template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n); // freestanding template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, Size n); namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct(I first, S last); // freestanding template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_value_construct(R&& r); // freestanding template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct_n(I first, // freestanding iter_difference_t<I> n); } template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, // freestanding InputIterator last, NoThrowForwardIterator result); template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result); template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, // freestanding Size n, NoThrowForwardIterator result); template<class ExecutionPolicy, class ForwardIterator, class Size, class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, NoThrowForwardIterator result); namespace ranges { template<class I, class O> using uninitialized_copy_result = in_out_result<I, O>; // freestanding template<input_iterator I, sentinel_for<I> S1, nothrow-forward-iterator O, nothrow-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> constexpr uninitialized_copy_result<I, O> uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<input_range IR, nothrow-forward-range OR> requires constructible_from<range_value_t<OR>, range_reference_t<IR>> constexpr uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_copy(IR&& in_range, OR&& out_range); // freestanding template<class I, class O> using uninitialized_copy_n_result = in_out_result<I, O>; // freestanding template<input_iterator I, nothrow-forward-iterator O, nothrow-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> constexpr uninitialized_copy_n_result<I, O> uninitialized_copy_n(I ifirst, iter_difference_t<I> n, // freestanding O ofirst, S olast); } template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding InputIterator last, NoThrowForwardIterator result); template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator> NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, NoThrowForwardIterator result); template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr pair<InputIterator, NoThrowForwardIterator> uninitialized_move_n(InputIterator first, Size n, // freestanding NoThrowForwardIterator result); template<class ExecutionPolicy, class ForwardIterator, class Size, class NoThrowForwardIterator> pair<ForwardIterator, NoThrowForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, NoThrowForwardIterator result); namespace ranges { template<class I, class O> using uninitialized_move_result = in_out_result<I, O>; // freestanding template<input_iterator I, sentinel_for<I> S1, nothrow-forward-iterator O, nothrow-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> constexpr uninitialized_move_result<I, O> uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding template<input_range IR, nothrow-forward-range OR> requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>> constexpr uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_move(IR&& in_range, OR&& out_range); // freestanding template<class I, class O> using uninitialized_move_n_result = in_out_result<I, O>; // freestanding template<input_iterator I, nothrow-forward-iterator O, nothrow-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> constexpr uninitialized_move_n_result<I, O> uninitialized_move_n(I ifirst, iter_difference_t<I> n, // freestanding O ofirst, S olast); } template<class NoThrowForwardIterator, class T> constexpr void uninitialized_fill(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last, const T& x); template<class ExecutionPolicy, class NoThrowForwardIterator, class T> void uninitialized_fill(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x); template<class NoThrowForwardIterator, class Size, class T> constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x); // freestanding template<class ExecutionPolicy, class NoThrowForwardIterator, class Size, class T> NoThrowForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, Size n, const T& x); namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S, class T> requires constructible_from<iter_value_t<I>, const T&> constexpr I uninitialized_fill(I first, S last, const T& x); // freestanding template<nothrow-forward-range R, class T> requires constructible_from<range_value_t<R>, const T&> constexpr borrowed_iterator_t<R> uninitialized_fill(R&& r, const T& x); // freestanding template<nothrow-forward-iterator I, class T> requires constructible_from<iter_value_t<I>, const T&> constexpr I uninitialized_fill_n(I first, // freestanding iter_difference_t<I> n, const T& x); } // [specialized.construct], construct_at template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); // freestanding namespace ranges { template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); // freestanding } // [specialized.destroy], destroy template<class T> constexpr void destroy_at(T* location); // freestanding template<class NoThrowForwardIterator> constexpr void destroy(NoThrowForwardIterator first, // freestanding NoThrowForwardIterator last); template<class ExecutionPolicy, class NoThrowForwardIterator> void destroy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, NoThrowForwardIterator last); template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, // freestanding Size n); template<class ExecutionPolicy, class NoThrowForwardIterator, class Size> NoThrowForwardIterator destroy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] NoThrowForwardIterator first, Size n); namespace ranges { template<destructible T> constexpr void destroy_at(T* location) noexcept; // freestanding template<nothrow-input-iterator I, nothrow-sentinel-for<I> S> requires destructible<iter_value_t<I>> constexpr I destroy(I first, S last) noexcept; // freestanding template<nothrow-input-range R> requires destructible<range_value_t<R>> constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept; // freestanding template<nothrow-input-iterator I> requires destructible<iter_value_t<I>> constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; // freestanding } // [unique.ptr], class template unique_ptr template<class T> struct default_delete; // freestanding template<class T> struct default_delete<T[]>; // freestanding template<class T, class D = default_delete<T>> class unique_ptr; // freestanding template<class T, class D> class unique_ptr<T[], D>; // freestanding template<class T, class... Args> constexpr unique_ptr<T> make_unique(Args&&... args); // T is not array template<class T> constexpr unique_ptr<T> make_unique(size_t n); // T is U[] template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // T is U[N] template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[] template<class T, class... Args> unspecified make_unique_for_overwrite(Args&&...) = delete; // T is U[N] template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; // freestanding template<class T1, class D1, class T2, class D2> constexpr bool operator==(const unique_ptr<T1, D1>& x, // freestanding const unique_ptr<T2, D2>& y); template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // freestanding template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // freestanding template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // freestanding template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // freestanding template<class T1, class D1, class T2, class D2> requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); // freestanding template<class T, class D> constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; // freestanding template<class T, class D> constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t); // freestanding template<class T, class D> constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& y); // freestanding template<class T, class D> constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t); // freestanding template<class T, class D> constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& y); // freestanding template<class T, class D> constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t); // freestanding template<class T, class D> constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& y); // freestanding template<class T, class D> constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t); // freestanding template<class T, class D> constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& y); // freestanding template<class T, class D> requires three_way_comparable<typename unique_ptr<T, D>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer> operator<=>(const unique_ptr<T, D>& x, nullptr_t); // freestanding template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p); // [util.smartptr.weak.bad], class bad_weak_ptr class bad_weak_ptr; // [util.smartptr.shared], class template shared_ptr template<class T> class shared_ptr; // [util.smartptr.shared.create], shared_ptr creation template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); // T is not array template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array template<class T> shared_ptr<T> make_shared(size_t N); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[] template<class T> shared_ptr<T> make_shared(); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a); // T is U[N] template<class T> shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[] template<class T> shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N] template<class T> shared_ptr<T> make_shared_for_overwrite(); // T is not U[] template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a); // T is not U[] template<class T> shared_ptr<T> make_shared_for_overwrite(size_t N); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N); // T is U[] // [util.smartptr.shared.cmp], shared_ptr comparisons template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T> bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; template<class T> strong_ordering operator<=>(const shared_ptr<T>& x, nullptr_t) noexcept; // [util.smartptr.shared.spec], shared_ptr specialized algorithms template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; // [util.smartptr.shared.cast], shared_ptr casts template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept; template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept; // [util.smartptr.getdeleter], shared_ptr get_deleter template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; // [util.smartptr.shared.io], shared_ptr I/O template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p); // [util.smartptr.weak], class template weak_ptr template<class T> class weak_ptr; // [util.smartptr.weak.spec], weak_ptr specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; // [util.smartptr.ownerless], class template owner_less template<class T = void> struct owner_less; // [util.smartptr.owner.hash], struct owner_hash struct owner_hash; // [util.smartptr.owner.equal], struct owner_equal struct owner_equal; // [util.smartptr.enab], class template enable_shared_from_this template<class T> class enable_shared_from_this; // [util.smartptr.hash], hash support template<class T> struct hash; // freestanding template<class T, class D> struct hash<unique_ptr<T, D>>; // freestanding template<class T> struct hash<shared_ptr<T>>; // [util.smartptr.atomic], atomic smart pointers template<class T> struct atomic; // freestanding template<class T> struct atomic<shared_ptr<T>>; template<class T> struct atomic<weak_ptr<T>>; // [out.ptr.t], class template out_ptr_t template<class Smart, class Pointer, class... Args> class out_ptr_t; // freestanding // [out.ptr], function template out_ptr template<class Pointer = void, class Smart, class... Args> auto out_ptr(Smart& s, Args&&... args); // freestanding // [inout.ptr.t], class template inout_ptr_t template<class Smart, class Pointer, class... Args> class inout_ptr_t; // freestanding // [inout.ptr], function template inout_ptr template<class Pointer = void, class Smart, class... Args> auto inout_ptr(Smart& s, Args&&... args); // freestanding }

20.2.3 Pointer traits [pointer.traits]

20.2.3.1 General [pointer.traits.general]

The class template pointer_traits supplies a uniform interface to certain attributes of pointer-like types.
namespace std { template<class Ptr> struct pointer_traits { see below; }; template<class T> struct pointer_traits<T*> { using pointer = T*; using element_type = T; using difference_type = ptrdiff_t; template<class U> using rebind = U*; static constexpr pointer pointer_to(see below r) noexcept; }; }

20.2.3.2 Member types [pointer.traits.types]

The definitions in this subclause make use of the following exposition-only class template and concept: template<class T> struct ptr-traits-elem // exposition only { }; template<class T> requires requires { typename T::element_type; } struct ptr-traits-elem<T> { using type = typename T::element_type; }; template<template<class...> class SomePointer, class T, class... Args> requires (!requires { typename SomePointer<T, Args...>::element_type; }) struct ptr-traits-elem<SomePointer<T, Args...>> { using type = T; }; template<class Ptr> concept has-elem-type = // exposition only requires { typename ptr-traits-elem<Ptr>::type; }
If Ptr satisfies has-elem-type, a specialization pointer_traits<Ptr> generated from the pointer_traits primary template has the following members as well as those described in [pointer.traits.functions]; otherwise, such a specialization has no members by any of those names.
using pointer = see below;
Type: Ptr.
using element_type = see below;
Type: typename ptr-traits-elem<Ptr>​::​type.
using difference_type = see below;
Type: Ptr​::​difference_type if the qualified-id Ptr​::​difference_type is valid and denotes a type ([temp.deduct]); otherwise, ptrdiff_t.
template<class U> using rebind = see below;
Alias template: Ptr​::​rebind<U> if the qualified-id Ptr​::​rebind<U> is valid and denotes a type ([temp.deduct]); otherwise, SomePointer<U, Args> if Ptr is a class template instantiation of the form SomePointer<T, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind is ill-formed.

20.2.3.3 Member functions [pointer.traits.functions]

static pointer pointer_traits::pointer_to(see below r); static constexpr pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
Mandates: For the first member function, Ptr​::​pointer_to(r) is well-formed.
Preconditions: For the first member function, Ptr​::​pointer_to(r) returns a pointer to r through which indirection is valid.
Returns: The first member function returns Ptr​::​pointer_to(r).
The second member function returns addressof(r).
Remarks: If element_type is cv void, the type of r is unspecified; otherwise, it is element_type&.

20.2.3.4 Optional members [pointer.traits.optmem]

Specializations of pointer_traits may define the member declared in this subclause to customize the behavior of the standard library.
A specialization generated from the pointer_traits primary template has no member by this name.
static element_type* to_address(pointer p) noexcept;
Returns: A pointer of type element_type* that references the same location as the argument p.
[Note 1: 
This function is intended to be the inverse of pointer_to.
If defined, it customizes the behavior of the non-member function to_address ([pointer.conversion]).
— end note]

20.2.4 Pointer conversion [pointer.conversion]

template<class T> constexpr T* to_address(T* p) noexcept;
Mandates: T is not a function type.
Returns: p.
template<class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
Returns: pointer_traits<Ptr>​::​to_address(p) if that expression is well-formed (see [pointer.traits.optmem]), otherwise to_address(p.operator->()).

20.2.5 Pointer alignment [ptr.align]

void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
Preconditions:
  • alignment is a power of two
  • ptr represents the address of contiguous storage of at least space bytes
Effects: If it is possible to fit size bytes of storage aligned by alignment into the buffer pointed to by ptr with length space, the function updates ptr to represent the first possible address of such storage and decreases space by the number of bytes used for alignment.
Otherwise, the function does nothing.
Returns: A null pointer if the requested aligned buffer would not fit into the available space, otherwise the adjusted value of ptr.
[Note 1: 
The function updates its ptr and space arguments so that it can be called repeatedly with possibly different alignment and size arguments for the same buffer.
— end note]
template<size_t N, class T> constexpr T* assume_aligned(T* ptr);
Mandates: N is a power of two.
Preconditions: ptr points to an object X of a type similar ([conv.qual]) to T, where X has alignment N ([basic.align]).
Returns: ptr.
Throws: Nothing.
[Note 2: 
The alignment assumption on an object X expressed by a call to 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 X that access X through the pointer returned by assume_aligned.
— end note]
template<size_t Alignment, class T> bool is_sufficiently_aligned(T* ptr);
Preconditions: p points to an object X of a type similar ([conv.qual]) to T.
Returns: true if X has alignment at least Alignment, otherwise false.
Throws: Nothing.

20.2.6 Explicit lifetime management [obj.lifetime]

template<class T> T* start_lifetime_as(void* p) noexcept; template<class T> const T* start_lifetime_as(const void* p) noexcept; template<class T> volatile T* start_lifetime_as(volatile void* p) noexcept; template<class T> const volatile T* start_lifetime_as(const volatile void* p) noexcept;
Mandates: T is an implicit-lifetime type ([basic.types.general]) and not an incomplete type ([basic.types.general]).
Preconditions: [p, (char*)p + sizeof(T)) denotes a region of allocated storage that is a subset of the region of storage reachable through ([basic.compound]) p and suitably aligned for the type T.
Effects: Implicitly creates objects ([intro.object]) within the denoted region consisting of an object a of type T whose address is p, and objects nested within a, as follows: The object representation of a is the contents of the storage prior to the call to start_lifetime_as.
The value of each created object o of trivially copyable type ([basic.types.general]) U is determined in the same manner as for a call to bit_cast<U>(E) ([bit.cast]), where E is an lvalue of type U denoting o, except that the storage is not accessed.
The value of any other created object is unspecified.
[Note 1: 
The unspecified value can be indeterminate.
— end note]
Returns: A pointer to the a defined in the Effects paragraph.
template<class T> T* start_lifetime_as_array(void* p, size_t n) noexcept; template<class T> const T* start_lifetime_as_array(const void* p, size_t n) noexcept; template<class T> volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; template<class T> const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept;
Mandates: T is a complete type.
Preconditions: p is suitably aligned for an array of T or is null.
n <= size_t(-1) / sizeof(T) is true.
If n > 0 is true, [(char*)p, (char*)p + (n * sizeof(T))) denotes a region of allocated storage that is a subset of the region of storage reachable through ([basic.compound]) p.
Effects: If n > 0 is true, equivalent to start_lifetime_as<U>(p) where U is the type “array of n T.
Otherwise, there are no effects.
Returns: A pointer to the first element of the created array, if any; otherwise, a pointer that compares equal to p ([expr.eq]).

20.2.7 Allocator argument tag [allocator.tag]

namespace std { struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; }
The allocator_arg_t struct is an empty class type used as a unique type to disambiguate constructor and function overloading.
Specifically, several types (see tuple [tuple]) have constructors with allocator_arg_t as the first argument, immediately followed by an argument of a type that meets the Cpp17Allocator requirements ([allocator.requirements.general]).

20.2.8 uses_allocator [allocator.uses]

20.2.8.1 uses_allocator trait [allocator.uses.trait]

template<class T, class Alloc> struct uses_allocator;
Remarks: Automatically detects whether T has a nested allocator_type that is convertible from Alloc.
Meets the Cpp17BinaryTypeTrait requirements ([meta.rqmts]).
The implementation shall provide a definition that is derived from true_type if the qualified-id T​::​allocator_type is valid and denotes a type ([temp.deduct]) and is_convertible_v<Alloc, T​::​allocator_type> != false, otherwise it shall be derived from false_type.
A program may specialize this template to derive from true_type for a program-defined type T that does not have a nested allocator_type but nonetheless can be constructed with an allocator where either:
  • the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or
  • the last argument of a constructor has type Alloc.

20.2.8.2 Uses-allocator construction [allocator.uses.construction]

Uses-allocator construction with allocator alloc and constructor arguments args... refers to the construction of an object of type T such that alloc is passed to the constructor of T if T uses an allocator type compatible with alloc.
When applied to the construction of an object of type T, it is equivalent to initializing it with the value of the expression make_obj_using_allocator<T>(alloc, args...), described below.
The following utility functions support three conventions for passing alloc to a constructor:
  • If T does not use an allocator compatible with alloc, then alloc is ignored.
  • Otherwise, if T has a constructor invocable as T(allocator_arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.
  • Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention), then uses-allocator construction chooses this constructor form.
The 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 pair such that uses-allocator construction is applied individually to the first and second data members.
The make_obj_using_allocator and uninitialized_construct_using_allocator function templates apply the modified constructor arguments to construct an object of type T as a return value or in-place, respectively.
[Note 1: 
For uses_allocator_construction_args and make_obj_using_allocator, type T is not deduced and must therefore be specified explicitly by the caller.
— end note]
template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept;
Constraints: remove_cv_t<T> is not a specialization of pair.
Returns: A tuple value determined as follows:
  • If uses_allocator_v<remove_cv_t<T>, Alloc> is false and is_constructible_v<T, Args...> is true, return forward_as_tuple(std​::​forward<Args>(args)...).
  • Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true and is_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true, return tuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)
  • Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true and is_constructible_v<T, Args..., const Alloc&> is true, return forward_as_tuple(std​::​forward<Args>(args)..., alloc).
  • Otherwise, the program is ill-formed.
[Note 2: 
This definition prevents a silent failure to pass the allocator to a constructor of a type for which uses_allocator_v<T, Alloc> is true.
— end note]
template<class T, class Alloc, class Tuple1, class Tuple2> constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t, Tuple1&& x, Tuple2&& y) noexcept;
Let T1 be T​::​first_type.
Let T2 be T​::​second_type.
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to: return make_tuple( piecewise_construct, apply([&alloc](auto&&... args1) { return uses_allocator_construction_args<T1>( alloc, std::forward<decltype(args1)>(args1)...); }, std::forward<Tuple1>(x)), apply([&alloc](auto&&... args2) { return uses_allocator_construction_args<T2>( alloc, std::forward<decltype(args2)>(args2)...); }, std::forward<Tuple2>(y)));
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to: return uses_allocator_construction_args<T>(alloc, piecewise_construct, tuple<>{}, tuple<>{});
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to: return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::forward<U>(u)), forward_as_tuple(std::forward<V>(v)));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to: return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>&& pr) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to: return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(get<0>(std::move(pr))), forward_as_tuple(get<1>(std::move(pr))));
template<class T, class Alloc, pair-like P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair and remove_cvref_t<P> is not a specialization of ranges​::​subrange.
Effects: Equivalent to: return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(get<0>(std::forward<P>(p))), forward_as_tuple(get<1>(std::forward<P>(p))));
template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
Let FUN be the function template: template<class A, class B> void FUN(const pair<A, B>&);
Constraints: remove_cv_t<T> is a specialization of pair, and either:
  • remove_cvref_t<U> is a specialization of ranges​::​subrange, or
  • U does not satisfy pair-like and the expression FUN(u) is not well-formed when considered as an unevaluated operand.
Let pair-constructor be an exposition-only class defined as follows: class pair-constructor { using pair-type = remove_cv_t<T>; // exposition only constexpr auto do-construct(const pair-type& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc_, p); } constexpr auto do-construct(pair-type&& p) const { // exposition only return make_obj_using_allocator<pair-type>(alloc_, std::move(p)); } const Alloc& alloc_; // exposition only U& u_; // exposition only public: constexpr operator pair-type() const { return do-construct(std::forward<U>(u_)); } };
Returns: make_tuple(pc), where pc is a pair-constructor object whose alloc_ member is initialized with alloc and whose u_ member is initialized with u.
template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
Effects: Equivalent to: return make_from_tuple<T>(uses_allocator_construction_args<T>( alloc, std::forward<Args>(args)...));
template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
Effects: Equivalent to: return apply([&]<class... U>(U&&... xs) { return construct_at(p, std::forward<U>(xs)...); }, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));

20.2.9 Allocator traits [allocator.traits]

20.2.9.1 General [allocator.traits.general]

The class template allocator_traits supplies a uniform interface to all allocator types.
An allocator cannot be a non-class type, however, even if allocator_traits supplies the entire required interface.
[Note 1: 
Thus, it is always possible to create a derived class from an allocator.
— end note]
If a program declares an explicit or partial specialization of allocator_traits, the program is ill-formed, no diagnostic required.
namespace std { template<class Alloc> struct allocator_traits { using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = see below; using const_pointer = see below; using void_pointer = see below; using const_void_pointer = see below; using difference_type = see below; using size_type = see below; using propagate_on_container_copy_assignment = see below; using propagate_on_container_move_assignment = see below; using propagate_on_container_swap = see below; using is_always_equal = see below; template<class T> using rebind_alloc = see below; template<class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static constexpr pointer allocate(Alloc& a, size_type n); static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n); static constexpr void deallocate(Alloc& a, pointer p, size_type n); template<class T, class... Args> static constexpr void construct(Alloc& a, T* p, Args&&... args); template<class T> 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); }; }

20.2.9.2 Member types [allocator.traits.types]

using pointer = see below;
Type: Alloc​::​pointer if the qualified-id Alloc​::​pointer is valid and denotes a type ([temp.deduct]); otherwise, value_type*.
using const_pointer = see below;
Type: Alloc​::​const_pointer if the qualified-id Alloc​::​const_pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_traits<pointer>​::​rebind<const value_type>.
using void_pointer = see below;
Type: Alloc​::​void_pointer if the qualified-id Alloc​::​void_pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_traits<pointer>​::​rebind<void>.
using const_void_pointer = see below;
Type: Alloc​::​const_void_pointer if the qualified-id Alloc​::​const_void_pointer is valid and denotes a type ([temp.deduct]); otherwise, pointer_traits<pointer>​::​​rebind<const void>.
using difference_type = see below;
Type: Alloc​::​difference_type if the qualified-id Alloc​::​difference_type is valid and denotes a type ([temp.deduct]); otherwise, pointer_traits<pointer>​::​difference_type.
using size_type = see below;
Type: Alloc​::​size_type if the qualified-id Alloc​::​size_type is valid and denotes a type ([temp.deduct]); otherwise, make_unsigned_t<difference_type>.
using propagate_on_container_copy_assignment = see below;
Type: Alloc​::​propagate_on_container_copy_assignment if the qualified-id Alloc​::​propagate_on_container_copy_assignment is valid and denotes a type ([temp.deduct]); otherwise false_type.
using propagate_on_container_move_assignment = see below;
Type: Alloc​::​propagate_on_container_move_assignment if the qualified-id Alloc​::​propagate_on_container_move_assignment is valid and denotes a type ([temp.deduct]); otherwise false_type.
using propagate_on_container_swap = see below;
Type: Alloc​::​propagate_on_container_swap if the qualified-id Alloc​::​propagate_on_container_swap is valid and denotes a type ([temp.deduct]); otherwise false_type.
using is_always_equal = see below;
Type: Alloc​::​is_always_equal if the qualified-id Alloc​::​is_always_equal is valid and denotes a type ([temp.deduct]); otherwise is_empty<Alloc>​::​type.
template<class T> using rebind_alloc = see below;
Alias template: Alloc​::​rebind<T>​::​other if the qualified-id Alloc​::​rebind<T>​::​other is valid and denotes a type ([temp.deduct]); otherwise, Alloc<T, Args> if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or more type arguments; otherwise, the instantiation of rebind_alloc is ill-formed.

20.2.9.3 Static member functions [allocator.traits.members]

static constexpr pointer allocate(Alloc& a, size_type n);
Returns: a.allocate(n).
static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
Returns: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n).
static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n);
Returns: a.allocate_at_least(n) if that expression is well-formed; otherwise, {a.allocate(n), n}.
static constexpr void deallocate(Alloc& a, pointer p, size_type n);
Effects: Calls a.deallocate(p, n).
Throws: Nothing.
template<class T, class... Args> static constexpr void construct(Alloc& a, T* p, Args&&... args);
Effects: Calls a.construct(p, std​::​forward<Args>(args)...) if that call is well-formed; otherwise, invokes construct_at(p, std​::​forward<Args>(args)...).
template<class T> static constexpr void destroy(Alloc& a, T* p);
Effects: Calls a.destroy(p) if that call is well-formed; otherwise, invokes destroy_at(p).
static constexpr size_type max_size(const Alloc& a) noexcept;
Returns: a.max_size() if that expression is well-formed; otherwise, numeric_limits<size_type>​::​​max()/sizeof(value_type).
static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
Returns: rhs.select_on_container_copy_construction() if that expression is well-formed; otherwise, rhs.

20.2.9.4 Other [allocator.traits.other]

The class template allocation_result has the template parameters, data members, and special members specified above.
It has no base classes or members other than those specified.

20.2.10 The default allocator [default.allocator]

20.2.10.1 General [default.allocator.general]

All specializations of the default allocator meet the allocator completeness requirements ([allocator.requirements.completeness]).
namespace std { template<class T> 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<class U> constexpr allocator(const allocator<U>&) noexcept; constexpr ~allocator(); constexpr allocator& operator=(const allocator&) = default; constexpr T* allocate(size_t n); constexpr allocation_result<T*> allocate_at_least(size_t n); constexpr void deallocate(T* p, size_t n); }; }
allocator_traits<allocator<T>>​::​is_always_equal​::​value is true for any T.

20.2.10.2 Members [allocator.members]

Except for the destructor, member functions of the default allocator shall not introduce data races ([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.
constexpr T* allocate(size_t n);
Mandates: T is not an incomplete type ([basic.types.general]).
Returns: A pointer to the initial element of an array of n T.
Throws: bad_array_new_length if numeric_limits<size_t>​::​max() / sizeof(T) < n, or bad_alloc if the storage cannot be obtained.
Remarks: The storage for the array is obtained by calling ​::​operator new ([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.
constexpr allocation_result<T*> allocate_at_least(size_t n);
Mandates: T is not an incomplete type ([basic.types.general]).
Returns: allocation_result<T*>{ptr, count}, where ptr is a pointer to the initial element of an array of count T and count  ≥ n.
Throws: bad_array_new_length if numeric_limits<size_t>​::​max() / sizeof(T) < n, or bad_alloc if the storage cannot be obtained.
Remarks: The storage for the array is obtained by calling ​::​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.
constexpr void deallocate(T* p, size_t n);
Preconditions:
  • If p is memory that was obtained by a call to allocate_at_least, let ret be the value returned and req be the value passed as the first argument to that call.
    p is equal to ret.ptr and n is a value such that req  ≤ n  ≤ ret.count.
  • Otherwise, p is a pointer value obtained from allocate.
    n equals the value passed as the first argument to the invocation of allocate which returned p.
Effects: Deallocates the storage referenced by p.
Remarks: Uses ​::​operator delete ([new.delete]), but it is unspecified when this function is called.

20.2.10.3 Operators [allocator.globals]

template<class T, class U> constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
Returns: true.

20.2.11 addressof [specialized.addressof]

template<class T> constexpr T* addressof(T& r) noexcept;
Returns: The actual address of the object or function referenced by r, even in the presence of an overloaded operator&.
Remarks: An expression addressof(E) is a constant subexpression ([defns.const.subexpr]) if E is an lvalue constant subexpression.

20.2.12 C library memory allocation [c.malloc]

[Note 1: 
The header <cstdlib> declares the functions described in this subclause.
— end note]
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);
Effects: These functions have the semantics specified in the C standard library.
Remarks: These functions do not attempt to allocate storage by calling ​::​operator new() ([new.delete]).
These functions implicitly create objects ([intro.object]) in the returned region of storage and return a pointer to a suitable created object.
In the case of calloc and realloc, the objects are created before the storage is zeroed or copied, respectively.
void free(void* ptr);
Effects: This function has the semantics specified in the C standard library.
Remarks: This function does not attempt to deallocate storage by calling ​::​operator delete().
See also: ISO/IEC 9899:2018, 7.22.3

20.3 Smart pointers [smartptr]

20.3.1 Unique-ownership pointers [unique.ptr]

20.3.1.1 General [unique.ptr.general]

A 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 u that stores a pointer to a second object p and will dispose of p when u is itself destroyed (e.g., when leaving block scope ([stmt.dcl])).
In this context, u is said to own p.
The mechanism by which u disposes of p is known as p's associated deleter, a function object whose correct invocation results in p's appropriate disposition (typically its deletion).
Let the notation u.p denote the pointer stored by u, and let u.d denote the associated deleter.
Upon request, u can reset (replace) u.p and u.d with another pointer and deleter, but properly disposes of its owned object via the associated deleter before such replacement is considered completed.
Each object of a type U instantiated from the unique_ptr template specified in [unique.ptr] has the strict ownership semantics, specified above, of a unique pointer.
In partial satisfaction of these semantics, each such U is Cpp17MoveConstructible and Cpp17MoveAssignable, but is not Cpp17CopyConstructible nor Cpp17CopyAssignable.
The template parameter T of unique_ptr may be an incomplete type.
[Note 1: 
The uses of 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]

20.3.1.2 Default deleters [unique.ptr.dltr]

20.3.1.2.1 General [unique.ptr.dltr.general]

The class template default_delete serves as the default deleter (destruction policy) for the class template unique_ptr.
The template parameter T of default_delete may be an incomplete type.

20.3.1.2.2 default_delete [unique.ptr.dltr.dflt]

namespace std { template<class T> struct default_delete { constexpr default_delete() noexcept = default; template<class U> constexpr default_delete(const default_delete<U>&) noexcept; constexpr void operator()(T*) const; }; }
template<class U> constexpr default_delete(const default_delete<U>& other) noexcept;
Constraints: U* is implicitly convertible to T*.
Effects: Constructs a default_delete object from another default_delete<U> object.
constexpr void operator()(T* ptr) const;
Mandates: T is a complete type.
Effects: Calls delete on ptr.

20.3.1.2.3 default_delete<T[]> [unique.ptr.dltr.dflt1]

namespace std { template<class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default; template<class U> constexpr default_delete(const default_delete<U[]>&) noexcept; template<class U> constexpr void operator()(U* ptr) const; }; }
template<class U> constexpr default_delete(const default_delete<U[]>& other) noexcept;
Constraints: U(*)[] is convertible to T(*)[].
Effects: Constructs a default_delete object from another default_delete<U[]> object.
template<class U> constexpr void operator()(U* ptr) const;
Constraints: U(*)[] is convertible to T(*)[].
Mandates: U is a complete type.
Effects: Calls delete[] on ptr.

20.3.1.3 unique_ptr for single objects [unique.ptr.single]

20.3.1.3.1 General [unique.ptr.single.general]

namespace std { template<class T, class D = default_delete<T>> class unique_ptr { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.single.ctor], constructors constexpr unique_ptr() noexcept; constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, see below d1) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, see below d2) noexcept; constexpr unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept; // [unique.ptr.single.dtor], destructor constexpr ~unique_ptr(); // [unique.ptr.single.asgn], assignment constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.single.observers], observers constexpr add_lvalue_reference_t<T> operator*() const noexcept(see below); 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; // [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; }; }
A program that instantiates the definition of unique_ptr<T, D> is ill-formed if T* is an invalid type.
[Note 1: 
This prevents the instantiation of specializations such as unique_ptr<T&, D> and unique_ptr<int() const, D>.
— end note]
The default type for the template parameter D is default_delete.
A client-supplied template argument D shall be a function object type ([function.objects]), lvalue reference to function, or lvalue reference to function object type for which, given a value d of type D and a value ptr of type unique_ptr<T, D>​::​pointer, the expression d(ptr) is valid and has the effect of disposing of the pointer as appropriate for that deleter.
If the deleter's type D is not a reference type, D shall meet the Cpp17Destructible requirements (Table 35).
If the qualified-id remove_reference_t<D>​::​pointer is valid and denotes a type ([temp.deduct]), then unique_ptr<T, D>​::​pointer shall be a synonym for remove_reference_t<D>​::​pointer.
Otherwise unique_ptr<T, D>​::​pointer shall be a synonym for element_type*.
The type unique_ptr<T, D>​::​pointer shall meet the Cpp17NullablePointer requirements (Table 36).
[Example 1: 
Given an allocator type X ([allocator.requirements.general]) and letting A be a synonym for allocator_traits<X>, the types A​::​pointer, A​::​const_pointer, A​::​void_pointer, and A​::​const_void_pointer may be used as unique_ptr<T, D>​::​pointer.
— end example]

20.3.1.3.2 Constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept; constexpr unique_ptr(nullptr_t) noexcept;
Constraints: is_pointer_v<deleter_type> is false and is_default_constructible_v<deleter_type> is true.
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 30), and that construction does not throw an exception.
Effects: Constructs a unique_ptr object that owns nothing, value-initializing the stored pointer and the stored deleter.
Postconditions: get() == nullptr.
get_deleter() returns a reference to the stored deleter.
constexpr explicit unique_ptr(type_identity_t<pointer> p) noexcept;
Constraints: is_pointer_v<deleter_type> is false and is_default_constructible_v<deleter_type> is true.
Preconditions: D meets the Cpp17DefaultConstructible requirements (Table 30), and that construction does not throw an exception.
Effects: Constructs a unique_ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter.
Postconditions: get() == p.
get_deleter() returns a reference to the stored deleter.
constexpr unique_ptr(type_identity_t<pointer> p, const D& d) noexcept; constexpr unique_ptr(type_identity_t<pointer> p, remove_reference_t<D>&& d) noexcept;
Constraints: is_constructible_v<D, decltype(d)> is true.
Preconditions: For the first constructor, if D is not a reference type, D meets the Cpp17CopyConstructible requirements and such construction does not exit via an exception.
For the second constructor, if D is not a reference type, D meets the Cpp17MoveConstructible requirements and such construction does not exit via an exception.
Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and initializing the deleter from std​::​forward<decltype(d)>(d).
Postconditions: get() == p.
get_deleter() returns a reference to the stored deleter.
If D is a reference type then get_deleter() returns a reference to the lvalue d.
Remarks: If D is a reference type, the second constructor is defined as deleted.
[Example 1: D d; unique_ptr<int, D> p1(new int, D()); // D must be Cpp17MoveConstructible unique_ptr<int, D> p2(new int, d); // D must be Cpp17CopyConstructible unique_ptr<int, D&> p3(new int, d); // p3 holds a reference to d unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined // with reference deleter type — end example]
constexpr unique_ptr(unique_ptr&& u) noexcept;
Constraints: is_move_constructible_v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveConstructible requirements (Table 31).
Construction of the deleter from an rvalue of type D does not throw an exception.
Effects: Constructs a unique_ptr from u.
If D is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
[Note 1: 
The construction of the deleter can be implemented with std​::​forward<D>.
— end note]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_deleter() returns a reference to the stored deleter that was constructed from u.get_deleter().
If D is a reference type then get_deleter() and u.get_deleter() both reference the same lvalue deleter.
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_ptr<U, E>​::​pointer is implicitly convertible to pointer,
  • U is not an array type, and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
Preconditions: If E is not a reference type, construction of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and construction of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Constructs a unique_ptr from u.
If E is a reference type, this deleter is copy constructed from u's deleter; otherwise, this deleter is move constructed from u's deleter.
[Note 2: 
The deleter constructor can be implemented with std​::​forward<E>.
— end note]
Postconditions: get() yields the value u.get() yielded before the construction.
u.get() == nullptr.
get_deleter() returns a reference to the stored deleter that was constructed from u.get_deleter().

20.3.1.3.3 Destructor [unique.ptr.single.dtor]

constexpr ~unique_ptr();
Effects: Equivalent to: if (get()) get_deleter()(get());
[Note 1: 
The use of default_delete requires T to be a complete type.
— end note]
Remarks: The behavior is undefined if the evaluation of get_deleter()(get()) throws an exception.

20.3.1.3.4 Assignment [unique.ptr.single.asgn]

constexpr unique_ptr& operator=(unique_ptr&& u) noexcept;
Constraints: is_move_assignable_v<D> is true.
Preconditions: If D is not a reference type, D meets the Cpp17MoveAssignable requirements (Table 33) and assignment of the deleter from an rvalue of type D does not throw an exception.
Otherwise, D is a reference type; remove_reference_t<D> meets the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of type D does not throw an exception.
Effects: Calls reset(u.release()) followed by get_deleter() = std​::​forward<D>(u.get_deleter()).
Postconditions: If this != addressof(u), u.get() == nullptr, otherwise u.get() is unchanged.
Returns: *this.
template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Constraints:
  • unique_ptr<U, E>​::​pointer is implicitly convertible to pointer, and
  • U is not an array type, and
  • is_assignable_v<D&, E&&> is true.
Preconditions: If E is not a reference type, assignment of the deleter from an rvalue of type E is well-formed and does not throw an exception.
Otherwise, E is a reference type and assignment of the deleter from an lvalue of type E is well-formed and does not throw an exception.
Effects: Calls reset(u.release()) followed by get_deleter() = std​::​forward<E>(u.get_deleter()).
Postconditions: u.get() == nullptr.
Returns: *this.
constexpr unique_ptr& operator=(nullptr_t) noexcept;
Effects: As if by reset().
Postconditions: get() == nullptr.
Returns: *this.

20.3.1.3.5 Observers [unique.ptr.single.observers]

constexpr add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*declval<pointer>()));
Mandates: reference_converts_from_temporary_v<add_lvalue_reference_t<T>, decltype(
*declval<pointer>())>
is false.
Preconditions: get() != nullptr is true.
Returns: *get().
constexpr pointer operator->() const noexcept;
Preconditions: get() != nullptr.
Returns: get().
[Note 1: 
The use of this function typically requires that T be a complete type.
— end note]
constexpr pointer get() const noexcept;
Returns: The stored pointer.
constexpr deleter_type& get_deleter() noexcept; constexpr const deleter_type& get_deleter() const noexcept;
Returns: A reference to the stored deleter.
constexpr explicit operator bool() const noexcept;
Returns: get() != nullptr.

20.3.1.3.6 Modifiers [unique.ptr.single.modifiers]

constexpr pointer release() noexcept;
Postconditions: get() == nullptr.
Returns: The value get() had at the start of the call to release.
constexpr void reset(pointer p = pointer()) noexcept;
Effects: Assigns p to the stored pointer, and then, with the old value of the stored pointer, old_p, evaluates if (old_p) get_deleter()(old_p);
[Note 1: 
The order of these operations is significant because the call to get_deleter() might destroy *this.
— end note]
Postconditions: get() == p.
[Note 2: 
The postcondition does not hold if the call to get_deleter() destroys *this since this->get() is no longer a valid expression.
— end note]
Remarks: The behavior is undefined if the evaluation of get_deleter()(old_p) throws an exception.
constexpr void swap(unique_ptr& u) noexcept;
Preconditions: get_deleter() is swappable ([swappable.requirements]) and does not throw an exception under swap.
Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u.

20.3.1.4 unique_ptr for array objects with a runtime length [unique.ptr.runtime]

20.3.1.4.1 General [unique.ptr.runtime.general]

namespace std { template<class T, class D> class unique_ptr<T[], D> { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.runtime.ctor], constructors constexpr unique_ptr() noexcept; template<class U> constexpr explicit unique_ptr(U p) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept; constexpr unique_ptr(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; // destructor constexpr ~unique_ptr(); // assignment constexpr unique_ptr& operator=(unique_ptr&& u) noexcept; template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr& operator=(nullptr_t) noexcept; // [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; // [unique.ptr.runtime.modifiers], modifiers constexpr pointer release() noexcept; template<class U> 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; }; }
A specialization for array types is provided with a slightly altered interface.
  • Conversions between different types of unique_ptr<T[], D> that would be disallowed for the corresponding pointer-to-array types, and conversions to or from the non-array forms of unique_ptr, produce an ill-formed program.
  • Pointers to types derived from T are rejected by the constructors, and by reset.
  • The observers operator* and operator-> are not provided.
  • The indexing observer operator[] is provided.
  • The default deleter will call delete[].
Descriptions are provided below only for members that differ from the primary template.
The template argument T shall be a complete type.

20.3.1.4.2 Constructors [unique.ptr.runtime.ctor]

template<class U> constexpr explicit unique_ptr(U p) noexcept;
This constructor behaves the same as the constructor in the primary template that takes a single parameter of type pointer.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].
template<class U> constexpr unique_ptr(U p, see below d) noexcept; template<class U> constexpr unique_ptr(U p, see below d) noexcept;
These constructors behave the same as the constructors in the primary template that take a parameter of type pointer and a second parameter.
Constraints:
  • U is the same type as pointer,
  • U is nullptr_t, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].
template<class U, class E> constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept;
This constructor behaves the same as in the primary template.
Constraints: Where UP is unique_ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_type*, and
  • UP​::​pointer is the same type as UP​::​element_type*, and
  • UP​::​element_type(*)[] is convertible to element_type(*)[], and
  • either D is a reference type and E is the same type as D, or D is not a reference type and E is implicitly convertible to D.
[Note 1: 
This replaces the Constraints: specification of the primary template.
— end note]

20.3.1.4.3 Assignment [unique.ptr.runtime.asgn]

template<class U, class E> constexpr unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
This operator behaves the same as in the primary template.
Constraints: Where UP is unique_ptr<U, E>:
  • U is an array type, and
  • pointer is the same type as element_type*, and
  • UP​::​pointer is the same type as UP​::​element_type*, and
  • UP​::​element_type(*)[] is convertible to element_type(*)[], and
  • is_assignable_v<D&, E&&> is true.
[Note 1: 
This replaces the Constraints: specification of the primary template.
— end note]

20.3.1.4.4 Observers [unique.ptr.runtime.observers]

constexpr T& operator[](size_t i) const;
Preconditions: i < the number of elements in the array to which the stored pointer points.
Returns: get()[i].

20.3.1.4.5 Modifiers [unique.ptr.runtime.modifiers]

constexpr void reset(nullptr_t p = nullptr) noexcept;
Effects: Equivalent to reset(pointer()).
template<class U> constexpr void reset(U p) noexcept;
This function behaves the same as the reset member of the primary template.
Constraints:
  • U is the same type as pointer, or
  • pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].

20.3.1.5 Creation [unique.ptr.create]

template<class T, class... Args> constexpr unique_ptr<T> make_unique(Args&&... args);
Constraints: T is not an array type.
Returns: unique_ptr<T>(new T(std​::​forward<Args>(args)...)).
template<class T> constexpr unique_ptr<T> make_unique(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_ptr<T>(new remove_extent_t<T>[n]()).
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
Constraints: T is an array of known bound.
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite();
Constraints: T is not an array type.
Returns: unique_ptr<T>(new T).
template<class T> constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);
Constraints: T is an array of unknown bound.
Returns: unique_ptr<T>(new remove_extent_t<T>[n]).
template<class T, class... Args> unspecified make_unique_for_overwrite(Args&&...) = delete;
Constraints: T is an array of known bound.

20.3.1.6 Specialized algorithms [unique.ptr.special]

template<class T, class D> constexpr void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Constraints: is_swappable_v<D> is true.
Effects: Calls x.swap(y).
template<class T1, class D1, class T2, class D2> constexpr bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: x.get() == y.get().
template<class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Let CT denote common_type_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>
Mandates:
  • unique_ptr<T1, D1>​::​pointer is implicitly convertible to CT and
  • unique_ptr<T2, D2>​::​pointer is implicitly convertible to CT.
Preconditions: The specialization less<CT> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: less<CT>()(x.get(), y.get()).
template<class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: y < x.
template<class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(y < x).
template<class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: !(x < y).
template<class T1, class D1, class T2, class D2> requires three_way_comparable_with<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> compare_three_way_result_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer> operator<=>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Returns: compare_three_way()(x.get(), y.get()).
template<class T, class D> constexpr bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
Returns: !x.
template<class T, class D> constexpr bool operator<(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Preconditions: The specialization less<unique_ptr<T, D>​::​pointer> is a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting]) on the pointer values.
Returns: The first function template returns less<unique_ptr<T, D>::pointer>()(x.get(), nullptr)
The second function template returns less<unique_ptr<T, D>::pointer>()(nullptr, x.get())
template<class T, class D> constexpr bool operator>(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns nullptr < x.
The second function template returns x < nullptr.
template<class T, class D> constexpr bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(nullptr < x).
The second function template returns !(x < nullptr).
template<class T, class D> constexpr bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template<class T, class D> constexpr bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
Returns: The first function template returns !(x < nullptr).
The second function template returns !(nullptr < x).
template<class T, class D> requires three_way_comparable<typename unique_ptr<T, D>::pointer> constexpr compare_three_way_result_t<typename unique_ptr<T, D>::pointer> operator<=>(const unique_ptr<T, D>& x, nullptr_t);
Returns: compare_three_way()(x.get(), static_cast<typename unique_ptr<T, D>::pointer>(nullptr)).

20.3.1.7 I/O [unique.ptr.io]

template<class E, class T, class Y, class D> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const unique_ptr<Y, D>& p);
Constraints: os << p.get() is a valid expression.
Effects: Equivalent to: os << p.get();
Returns: os.

20.3.2 Shared-ownership pointers [util.sharedptr]

20.3.2.1 Class bad_weak_ptr [util.smartptr.weak.bad]

namespace std { class bad_weak_ptr : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; }; }
An exception of type bad_weak_ptr is thrown by the shared_ptr constructor taking a weak_ptr.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

20.3.2.2 Class template shared_ptr [util.smartptr.shared]

20.3.2.2.1 General [util.smartptr.shared.general]

The shared_ptr class template stores a pointer, usually obtained via new.
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 shared_ptr is said to be empty if it does not own a pointer.
namespace std { template<class T> class shared_ptr { public: using element_type = remove_extent_t<T>; using weak_type = weak_ptr<T>; // [util.smartptr.shared.const], constructors constexpr shared_ptr() noexcept; constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } template<class Y> explicit shared_ptr(Y* p); template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a); template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept; shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept; shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept; template<class Y> explicit shared_ptr(const weak_ptr<Y>& r); template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); // [util.smartptr.shared.dest], destructor ~shared_ptr(); // [util.smartptr.shared.assign], assignment shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept; shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept; template<class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r); // [util.smartptr.shared.mod], modifiers void swap(shared_ptr& r) noexcept; void reset() noexcept; template<class Y> void reset(Y* p); template<class Y, class D> void reset(Y* p, D d); template<class Y, class D, class A> void reset(Y* p, D d, A a); // [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<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept; size_t owner_hash() const noexcept; template<class U> bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_equal(const weak_ptr<U>& b) const noexcept; }; template<class T> shared_ptr(weak_ptr<T>) -> shared_ptr<T>; template<class T, class D> shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>; }
Specializations of shared_ptr shall be Cpp17CopyConstructible, Cpp17CopyAssignable, and Cpp17LessThanComparable, allowing their use in standard containers.
Specializations of shared_ptr shall be contextually convertible to bool, allowing their use in boolean expressions and declarations in conditions.
The template parameter T of shared_ptr may be an incomplete type.
[Note 1: 
T can be a function type.
— end note]
[Example 1: if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) { // do something with px } — end example]
For purposes of determining the presence of a data race, member functions shall access and modify only the shared_ptr and weak_ptr objects themselves and not objects they refer to.
Changes in use_count() do not reflect modifications that can introduce data races.
For the purposes of [smartptr], a pointer type Y* is said to be compatible with a pointer type T* when either Y* is convertible to T* or Y is U[N] and T is cv U[].

20.3.2.2.2 Constructors [util.smartptr.shared.const]

In the constructor definitions below, enables shared_from_this with p, for a pointer p of type Y*, means that if Y has an unambiguous and accessible base class that is a specialization of enable_shared_from_this ([util.smartptr.enab]), then remove_cv_t<Y>* shall be implicitly convertible to T* and the constructor evaluates the statement: if (p != nullptr && p->weak_this.expired()) p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));
The assignment to the weak_this member is not atomic and conflicts with any potentially concurrent access to the same object ([intro.multithread]).
constexpr shared_ptr() noexcept;
Postconditions: use_count() == 0 && get() == nullptr.
template<class Y> explicit shared_ptr(Y* p);
Constraints: When T is an array type, the expression delete[] p is well-formed and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
When T is not an array type, the expression delete p is well-formed and Y* is convertible to T*.
Mandates: Y is a complete type.
Preconditions: The expression delete[] p, when T is an array type, or delete p, when T is not an array type, has well-defined behavior, and does not throw exceptions.
Effects: When T is not an array type, constructs a shared_ptr object that owns the pointer p.
Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] p.
When T is not an array type, enables shared_from_this with p.
If an exception is thrown, delete p is called when T is not an array type, delete[] p otherwise.
Postconditions: use_count() == 1 && get() == p.
Throws: bad_alloc, or an implementation-defined exception when a resource other than memory cannot be obtained.
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D> shared_ptr(nullptr_t p, D d); template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
Constraints: is_move_constructible_v<D> is true, and d(p) is a well-formed expression.
For the first two overloads:
  • If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*.
  • If T is not an array type, then Y* is convertible to T*.
Preconditions: Construction of d and a deleter of type D initialized with std​::​move(d) do not throw exceptions.
The expression d(p) has well-defined behavior and does not throw exceptions.
Effects: Constructs a shared_ptr object that owns the object p and the deleter d.
When T is not an array type, the first and second constructors enable shared_from_this with p.
The second and fourth constructors shall use a copy of a to allocate memory for internal use.
If an exception is thrown, d(p) is called.
Postconditions: use_count() == 1 && get() == p.
Throws: bad_alloc, or an implementation-defined exception when a resource other than memory cannot be obtained.
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept;
Effects: Constructs a shared_ptr instance that stores p and shares ownership with the initial value of r.
Postconditions: get() == p.
For the second overload, r is empty and r.get() == nullptr.
[Note 1: 
Use of this constructor leads to a dangling pointer unless p remains valid at least until the ownership group of r is destroyed.
— end note]
[Note 2: 
This constructor allows creation of an empty shared_ptr instance with a non-null stored pointer.
— end note]
shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r.
Postconditions: get() == r.get() && use_count() == r.use_count().
shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: Move constructs a shared_ptr instance from r.
Postconditions: *this contains the old value of r.
r is empty, and r.get() == nullptr.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
Constraints: Y* is compatible with T*.
Effects: Constructs a shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r.
If an exception is thrown, the constructor has no effect.
Postconditions: use_count() == r.use_count().
Throws: bad_weak_ptr when r.expired().
template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
Constraints: Y* is compatible with T* and unique_ptr<Y, D>​::​pointer is convertible to element_type*.
Effects: If r.get() == nullptr, equivalent to shared_ptr().
Otherwise, if D is not a reference type, equivalent to shared_ptr(r.release(), std​::​move(r.get_deleter())).
Otherwise, equivalent to shared_ptr(r.release(), ref(r.get_deleter())).
If an exception is thrown, the constructor has no effect.

20.3.2.2.3 Destructor [util.smartptr.shared.dest]

~shared_ptr();
Effects:
  • If *this is empty or shares ownership with another shared_ptr instance (use_count() > 1), there are no side effects.
  • Otherwise, if *this owns an object p and a deleter d, d(p) is called.
  • Otherwise, *this owns a pointer p, and delete p is called.
[Note 1: 
Since the destruction of *this decreases the number of instances that share ownership with *this by one, after *this has been destroyed all shared_ptr instances that shared ownership with *this will report a use_count() that is one less than its previous value.
— end note]

20.3.2.2.4 Assignment [util.smartptr.shared.assign]

shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to shared_ptr(r).swap(*this).
Returns: *this.
[Note 1: 
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: shared_ptr<int> p(new int); shared_ptr<void> q(p); p = p; q = p; both assignments can be no-ops.
— end note]
shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
Effects: Equivalent to shared_ptr(std​::​move(r)).swap(*this).
Returns: *this.
template<class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
Effects: Equivalent to shared_ptr(std​::​move(r)).swap(*this).
Returns: *this.

20.3.2.2.5 Modifiers [util.smartptr.shared.mod]

void swap(shared_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to shared_ptr().swap(*this).
template<class Y> void reset(Y* p);
Effects: Equivalent to shared_ptr(p).swap(*this).
template<class Y, class D> void reset(Y* p, D d);
Effects: Equivalent to shared_ptr(p, d).swap(*this).
template<class Y, class D, class A> void reset(Y* p, D d, A a);
Effects: Equivalent to shared_ptr(p, d, a).swap(*this).

20.3.2.2.6 Observers [util.smartptr.shared.obs]

element_type* get() const noexcept;
Returns: The stored pointer.
T& operator*() const noexcept;
Preconditions: get() != nullptr.
Returns: *get().
Remarks: When T is an array type or cv 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.
T* operator->() const noexcept;
Preconditions: get() != nullptr.
Returns: get().
Remarks: When 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.
element_type& operator[](ptrdiff_t i) const;
Preconditions: get() != nullptr && i >= 0.
If T is U[N], i < N.
Returns: get()[i].
Throws: Nothing.
Remarks: When 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.
long use_count() const noexcept;
Synchronization: None.
Returns: The number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.
[Note 1: 
get() == nullptr does not imply a specific return value of use_count().
— end note]
[Note 2: 
weak_ptr<T>​::​lock() can affect the return value of use_count().
— end note]
[Note 3: 
When multiple threads might affect the return value of use_count(), the result is approximate.
In particular, use_count() == 1 does not imply that accesses through a previously destroyed shared_ptr have in any sense completed.
— end note]
explicit operator bool() const noexcept;
Returns: get() != nullptr.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • owner_before(b) defines a strict weak ordering as defined in [alg.sorting];
  • !owner_before(b) && !b.owner_before(*this) is true if and only if owner_equal(b) is true.
size_t owner_hash() const noexcept;
Returns: An unspecified value such that, for any object x where owner_equal(x) is true, owner_hash() == x.owner_hash() is true.
template<class U> bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_equal(const weak_ptr<U>& b) const noexcept;
Returns: true if and only if *this and b share ownership or are both empty.
Otherwise returns false.
Remarks: owner_equal is an equivalence relation.

20.3.2.2.7 Creation [util.smartptr.shared.create]

The common requirements that apply to all make_shared, allocate_shared, make_shared_for_overwrite, and allocate_shared_for_overwrite overloads, unless specified otherwise, are described below.
template<class T, ...> shared_ptr<T> make_shared(args); template<class T, class A, ...> shared_ptr<T> allocate_shared(const A& a, args); template<class T, ...> shared_ptr<T> make_shared_for_overwrite(args); template<class T, class A, ...> shared_ptr<T> allocate_shared_for_overwrite(const A& a, args);
Preconditions: A meets the Cpp17Allocator requirements ([allocator.requirements.general]).
Effects: Allocates memory for an object of type T (or U[N] when T is U[], where N is determined from args as specified by the concrete overload).
The object is initialized from args as specified by the concrete overload.
The allocate_shared and allocate_shared_for_overwrite templates use a copy of a (rebound for an unspecified value_type) to allocate memory.
If an exception is thrown, the functions have no effect.
Postconditions: r.get() != nullptr && r.use_count() == 1, where r is the return value.
Returns: A shared_ptr instance that stores and owns the address of the newly constructed object.
Throws: bad_alloc, or an exception thrown from allocate or from the initialization of the object.
Remarks:
  • Implementations should perform no more than one memory allocation.
    [Note 1: 
    This provides efficiency equivalent to an intrusive smart pointer.
    — end note]
  • When an object of an array type U is specified to have an initial value of 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 u.
  • 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.
  • When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, make_shared shall initialize this (sub)object via the expression ​::​new(pv) U(v) or ​::​new(pv) U(l...) respectively, where pv has type void* and points to storage suitable to hold an object of type U.
  • When a (sub)object of a non-array type U is specified to have an initial value of v, or U(l...), where l... is a list of constructor arguments, allocate_shared shall initialize this (sub)object via the expression
    • allocator_traits<A2>​::​construct(a2, pu, v) or
    • allocator_traits<A2>​::​construct(a2, pu, l...)
    respectively, where pu is a pointer of type remove_cv_t<U>* pointing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared.
  • When a (sub)object of non-array type U is specified to have a default initial value, make_shared shall initialize this (sub)object via the expression ​::​new(pv) U(), where pv has type void* and points to storage suitable to hold an object of type U.
  • When a (sub)object of non-array type U is specified to have a default initial value, allocate_shared initializes this (sub)object via the expression allocator_traits<A2>​::​construct(a2, pu), where pu is a pointer of type remove_cv_t<U>* pointing to storage suitable to hold an object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared.
  • When a (sub)object of non-array type U is initialized by make_shared_for_overwrite or allocate_shared_for_overwrite, it is initialized via the expression ​::​new(pv) U, where pv has type void* and points to storage suitable to hold an object of type U.
  • Array elements are initialized in ascending order of their addresses.
  • 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.
  • When a (sub)object of non-array type U that was initialized by make_shared, make_shared_for_overwrite, or allocate_shared_for_overwrite is to be destroyed, it is destroyed via the expression pu->~U() where pu points to that object of type U.
  • When a (sub)object of non-array type U that was initialized by allocate_shared is to be destroyed, it is destroyed via the expression allocator_traits<A2>​::​destroy(a2, pu) where pu is a pointer of type remove_cv_t<U>* pointing to that object of type remove_cv_t<U> and a2 of type A2 is a potentially rebound copy of the allocator a passed to allocate_shared.
[Note 2: 
These functions will typically allocate more memory than sizeof(T) to allow for internal bookkeeping structures such as reference counts.
— end note]
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); // T is not array template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // T is not array
Constraints: T is not an array type.
Returns: A shared_ptr to an object of type T with an initial value T(std​::​forward<Args>(args)...).
Remarks: The shared_ptr constructors called by these functions enable shared_from_this with the address of the newly constructed object of type T.
[Example 1: shared_ptr<int> p = make_shared<int>(); // shared_ptr to int() shared_ptr<vector<int>> q = make_shared<vector<int>>(16, 1); // shared_ptr to vector of 16 elements with value 1 — end example]
template<class T> shared_ptr<T> make_shared(size_t N); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N); // T is U[]
Constraints: T is of the form U[].
Returns: A shared_ptr to an object of type U[N] with a default initial value, where U is remove_extent_t<T>.
[Example 2: shared_ptr<double[]> p = make_shared<double[]>(1024); // shared_ptr to a value-initialized double[1024] shared_ptr<double[][2][2]> q = make_shared<double[][2][2]>(6); // shared_ptr to a value-initialized double[6][2][2] — end example]
template<class T> shared_ptr<T> make_shared(); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a); // T is U[N]
Constraints: T is of the form U[N].
Returns: A shared_ptr to an object of type T with a default initial value.
[Example 3: shared_ptr<double[1024]> p = make_shared<double[1024]>(); // shared_ptr to a value-initialized double[1024] shared_ptr<double[6][2][2]> q = make_shared<double[6][2][2]>(); // shared_ptr to a value-initialized double[6][2][2] — end example]
template<class T> shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // T is U[] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, size_t N, const remove_extent_t<T>& u); // T is U[]
Constraints: T is of the form U[].
Returns: A shared_ptr to an object of type U[N], where U is remove_extent_t<T> and each array element has an initial value of u.
[Example 4: shared_ptr<double[]> p = make_shared<double[]>(1024, 1.0); // shared_ptr to a double[1024], where each element is 1.0 shared_ptr<double[][2]> q = make_shared<double[][2]>(6, {1.0, 0.0}); // shared_ptr to a double[6][2], where each double[2] element is {1.0, 0.0} shared_ptr<vector<int>[]> r = make_shared<vector<int>[]>(4, {1, 2}); // shared_ptr to a vector<int>[4], where each vector has contents {1, 2} — end example]
template<class T> shared_ptr<T> make_shared(const remove_extent_t<T>& u); // T is U[N] template<class T, class A> shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& u); // T is U[N]
Constraints: T is of the form U[N].
Returns: A shared_ptr to an object of type T, where each array element of type remove_extent_t<T> has an initial value of u.
[Example 5: shared_ptr<double[1024]> p = make_shared<double[1024]>(1.0); // shared_ptr to a double[1024], where each element is 1.0 shared_ptr<double[6][2]> q = make_shared<double[6][2]>({1.0, 0.0}); // shared_ptr to a double[6][2], where each double[2] element is {1.0, 0.0} shared_ptr<vector<int>[4]> r = make_shared<vector<int>[4]>({1, 2}); // shared_ptr to a vector<int>[4], where each vector has contents {1, 2} — end example]
template<class T> shared_ptr<T> make_shared_for_overwrite(); template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a);
Constraints: T is not an array of unknown bound.
Returns: A shared_ptr to an object of type T.
[Example 6: struct X { double data[1024]; }; shared_ptr<X> p = make_shared_for_overwrite<X>(); // shared_ptr to a default-initialized X, where each element in X​::​data has an indeterminate value shared_ptr<double[1024]> q = make_shared_for_overwrite<double[1024]>(); // shared_ptr to a default-initialized double[1024], where each element has an indeterminate value — end example]
template<class T> shared_ptr<T> make_shared_for_overwrite(size_t N); template<class T, class A> shared_ptr<T> allocate_shared_for_overwrite(const A& a, size_t N);
Constraints: T is an array of unknown bound.
Returns: A shared_ptr to an object of type U[N], where U is remove_extent_t<T>.
[Example 7: shared_ptr<double[]> p = make_shared_for_overwrite<double[]>(1024); // shared_ptr to a default-initialized double[1024], where each element has an indeterminate value — end example]

20.3.2.2.8 Comparison [util.smartptr.shared.cmp]

template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: a.get() == b.get().
template<class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
Returns: !a.
template<class T, class U> strong_ordering operator<=>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
Returns: compare_three_way()(a.get(), b.get()).
[Note 1: 
Defining a comparison operator function allows shared_ptr objects to be used as keys in associative containers.
— end note]
template<class T> strong_ordering operator<=>(const shared_ptr<T>& a, nullptr_t) noexcept;
Returns: compare_three_way()(a.get(), static_cast<typename shared_ptr<T>::element_type*>(nullptr))

20.3.2.2.9 Specialized algorithms [util.smartptr.shared.spec]

template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

20.3.2.2.10 Casts [util.smartptr.shared.cast]

template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression static_cast<T*>((U*)nullptr) is well-formed.
Returns: shared_ptr<T>(R, static_cast<typename shared_ptr<T>::element_type*>(r.get())) where R is r for the first overload, and std​::​move(r) for the second.
[Note 1: 
The seemingly equivalent expression shared_ptr<T>(static_cast<T*>(r.get())) can result in undefined behavior, attempting to delete the same object twice.
— end note]
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression dynamic_cast<T*>((U*)nullptr) is well-formed.
The expression dynamic_cast<typename shared_ptr<T>​::​element_type*>(r.get()) is well-formed.
Preconditions: The expression dynamic_cast<typename shared_ptr<T>​::​element_type*>(r.get()) has well-defined behavior.
Returns:
  • When dynamic_cast<typename shared_ptr<T>​::​element_type*>(r.get()) returns a non-null value p, shared_ptr<T>(R, p), where R is r for the first overload, and std​::​move(r) for the second.
  • Otherwise, shared_ptr<T>().
[Note 2: 
The seemingly equivalent expression shared_ptr<T>(dynamic_cast<T*>(r.get())) can result in undefined behavior, attempting to delete the same object twice.
— end note]
template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression const_cast<T*>((U*)nullptr) is well-formed.
Returns: shared_ptr<T>(R, const_cast<typename shared_ptr<T>::element_type*>(r.get())) where R is r for the first overload, and std​::​move(r) for the second.
[Note 3: 
The seemingly equivalent expression shared_ptr<T>(const_cast<T*>(r.get())) can result in undefined behavior, attempting to delete the same object twice.
— end note]
template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U>&& r) noexcept;
Mandates: The expression reinterpret_cast<T*>((U*)nullptr) is well-formed.
Returns: shared_ptr<T>(R, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get())) where R is r for the first overload, and std​::​move(r) for the second.
[Note 4: 
The seemingly equivalent expression shared_ptr<T>(reinterpret_cast<T*>(r.get())) can result in undefined behavior, attempting to delete the same object twice.
— end note]

20.3.2.2.11 get_deleter [util.smartptr.getdeleter]

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
Returns: If p owns a deleter d of type cv-unqualified D, returns addressof(d); otherwise returns nullptr.
The returned pointer remains valid as long as there exists a shared_ptr instance that owns d.
[Note 1: 
It is unspecified whether the pointer remains valid longer than that.
This can happen if the implementation doesn't destroy the deleter until all weak_ptr instances that share ownership with p have been destroyed.
— end note]

20.3.2.2.12 I/O [util.smartptr.shared.io]

template<class E, class T, class Y> basic_ostream<E, T>& operator<<(basic_ostream<E, T>& os, const shared_ptr<Y>& p);
Effects: As if by: os << p.get();
Returns: os.

20.3.2.3 Class template weak_ptr [util.smartptr.weak]

20.3.2.3.1 General [util.smartptr.weak.general]

The weak_ptr class template stores a weak reference to an object that is already managed by a shared_ptr.
To access the object, a weak_ptr can be converted to a shared_ptr using the member function lock.
namespace std { template<class T> class weak_ptr { public: using element_type = remove_extent_t<T>; // [util.smartptr.weak.const], constructors constexpr weak_ptr() noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept; weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.dest], destructor ~weak_ptr(); // [util.smartptr.weak.assign], assignment weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept; weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.mod], modifiers void swap(weak_ptr& r) noexcept; void reset() noexcept; // [util.smartptr.weak.obs], observers long use_count() const noexcept; bool expired() const noexcept; shared_ptr<T> lock() const noexcept; template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept; size_t owner_hash() const noexcept; template<class U> bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_equal(const weak_ptr<U>& b) const noexcept; }; template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>; }
Specializations of weak_ptr shall be Cpp17CopyConstructible and Cpp17CopyAssignable, allowing their use in standard containers.
The template parameter T of weak_ptr may be an incomplete type.

20.3.2.3.2 Constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;
Effects: Constructs an empty weak_ptr object that stores a null pointer value.
Postconditions: use_count() == 0.
weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Constraints: For the second and third constructors, Y* is compatible with T*.
Effects: If r is empty, constructs an empty weak_ptr object that stores a null pointer value; otherwise, constructs a weak_ptr object that shares ownership with r and stores a copy of the pointer stored in r.
Postconditions: use_count() == r.use_count().
weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Constraints: For the second constructor, Y* is compatible with T*.
Effects: Move constructs a weak_ptr instance from r.
Postconditions: *this contains the old value of r.
r is empty, stores a null pointer value, and r.use_count() == 0.

20.3.2.3.3 Destructor [util.smartptr.weak.dest]

~weak_ptr();
Effects: Destroys this weak_ptr object but has no effect on the object its stored pointer points to.

20.3.2.3.4 Assignment [util.smartptr.weak.assign]

weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Effects: Equivalent to weak_ptr(r).swap(*this).
Returns: *this.
Remarks: The implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary object.
weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
Effects: Equivalent to weak_ptr(std​::​move(r)).swap(*this).
Returns: *this.

20.3.2.3.5 Modifiers [util.smartptr.weak.mod]

void swap(weak_ptr& r) noexcept;
Effects: Exchanges the contents of *this and r.
void reset() noexcept;
Effects: Equivalent to weak_ptr().swap(*this).

20.3.2.3.6 Observers [util.smartptr.weak.obs]

long use_count() const noexcept;
Returns: 0 if *this is empty; otherwise, the number of shared_ptr instances that share ownership with *this.
bool expired() const noexcept;
Returns: use_count() == 0.
shared_ptr<T> lock() const noexcept;
Returns: expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed atomically.
template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
Returns: An unspecified value such that
  • owner_before(b) defines a strict weak ordering as defined in [alg.sorting];
  • !owner_before(b) && !b.owner_before(*this) is true if and only if owner_equal(b) is true.
size_t owner_hash() const noexcept;
Returns: An unspecified value such that, for any object x where owner_equal(x) is true, owner_hash() == x.owner_hash() is true.
template<class U> bool owner_equal(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_equal(const weak_ptr<U>& b) const noexcept;
Returns: true if and only if *this and b share ownership or are both empty.
Otherwise returns false.
Remarks: owner_equal is an equivalence relation.

20.3.2.3.7 Specialized algorithms [util.smartptr.weak.spec]

template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Effects: Equivalent to a.swap(b).

20.3.2.4 Class template owner_less [util.smartptr.ownerless]

The class template owner_less allows ownership-based mixed comparisons of shared and weak pointers.
namespace std { template<class T = void> struct owner_less; template<class T> struct owner_less<shared_ptr<T>> { bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept; bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept; bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept; }; template<class T> struct owner_less<weak_ptr<T>> { bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept; bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept; bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept; }; template<> struct owner_less<void> { template<class T, class U> bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept; using is_transparent = unspecified; }; }
operator()(x, y) returns x.owner_before(y).
[Note 1: 
Note that
  • operator() defines a strict weak ordering as defined in [alg.sorting];
  • !operator()(a, b) && !operator()(b, a) is true if and only if a.owner_equal(b) is true.
— end note]

20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]

The class owner_hash provides ownership-based hashing.
namespace std { struct owner_hash { template<class T> size_t operator()(const shared_ptr<T>&) const noexcept; template<class T> size_t operator()(const weak_ptr<T>&) const noexcept; using is_transparent = unspecified; }; }
template<class T> size_t operator()(const shared_ptr<T>& x) const noexcept; template<class T> size_t operator()(const weak_ptr<T>& x) const noexcept;
Returns: x.owner_hash().
[Note 1: 
For any object y where x.owner_equal(y) is true, x.owner_hash() == y.owner_hash() is true.
— end note]

20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]

The class owner_equal provides ownership-based mixed equality comparisons of shared and weak pointers.
namespace std { struct owner_equal { template<class T, class U> bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept; using is_transparent = unspecified; }; }
template<class T, class U> bool operator()(const shared_ptr<T>& x, const shared_ptr<U>& y) const noexcept; template<class T, class U> bool operator()(const shared_ptr<T>& x, const weak_ptr<U>& y) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>& x, const shared_ptr<U>& y) const noexcept; template<class T, class U> bool operator()(const weak_ptr<T>& x, const weak_ptr<U>& y) const noexcept;
Returns: x.owner_equal(y).
[Note 1: 
x.owner_equal(y) is true if and only if x and y share ownership or are both empty.
— end note]

20.3.2.7 Class template enable_shared_from_this [util.smartptr.enab]

A class T can inherit from enable_shared_from_this<T> to inherit the shared_from_this member functions that obtain a shared_ptr instance pointing to *this.
[Example 1: struct X: public enable_shared_from_this<X> { }; int main() { shared_ptr<X> p(new X); shared_ptr<X> q = p->shared_from_this(); assert(p == q); assert(p.owner_equal(q)); // p and q share ownership } — end example]
namespace std { template<class T> 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<T> shared_from_this(); shared_ptr<T const> shared_from_this() const; weak_ptr<T> weak_from_this() noexcept; weak_ptr<T const> weak_from_this() const noexcept; private: mutable weak_ptr<T> weak_this; // exposition only }; }
The template parameter T of enable_shared_from_this may be an incomplete type.
constexpr enable_shared_from_this() noexcept; enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
Effects: Value-initializes weak_this.
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
Returns: *this.
[Note 1: 
weak_this is not changed.
— end note]
shared_ptr<T> shared_from_this(); shared_ptr<T const> shared_from_this() const;
Returns: shared_ptr<T>(weak_this).
weak_ptr<T> weak_from_this() noexcept; weak_ptr<T const> weak_from_this() const noexcept;
Returns: weak_this.

20.3.3 Smart pointer hash support [util.smartptr.hash]

template<class T, class D> struct hash<unique_ptr<T, D>>;
Letting UP be unique_ptr<T, D>, the specialization hash<UP> is enabled ([unord.hash]) if and only if hash<typename UP​::​pointer> is enabled.
When enabled, for an object p of type UP, hash<UP>()(p) evaluates to the same value as hash<typename UP​::​pointer>()(p.get()).
The member functions are not guaranteed to be noexcept.
template<class T> struct hash<shared_ptr<T>>;
For an object p of type shared_ptr<T>, hash<shared_ptr<T>>()(p) evaluates to the same value as hash<typename shared_ptr<T>​::​element_type*>()(p.get()).

20.3.4 Smart pointer adaptors [smartptr.adapt]

20.3.4.1 Class template out_ptr_t [out.ptr.t]

out_ptr_t is a class template used to adapt types such as smart pointers ([smartptr]) for functions that use output pointer parameters.
[Example 1: 
#include <memory> #include <cstdio> 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<std::FILE, fclose_deleter> file_ptr; int err = fopen_s(std::out_ptr<std::FILE*>(file_ptr), file_name, "r+b"); if (err != 0) return 1; // *file_ptr is valid return 0; } unique_ptr can be used with 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]
namespace std { template<class Smart, class Pointer, class... Args> 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; // exposition only tuple<Args...> a; // exposition only Pointer p; // exposition only }; }
Pointer shall meet the Cpp17NullablePointer requirements.
If Smart is a specialization of shared_ptr and sizeof...(Args) == 0, the program is ill-formed.
[Note 1: 
It is typically a user error to reset a shared_ptr without specifying a deleter, as shared_ptr will replace a custom deleter upon usage of reset, as specified in [util.smartptr.shared.mod].
— end note]
Program-defined specializations of out_ptr_t that depend on at least one program-defined type need not meet the requirements for the primary template.
Evaluations of the conversion functions on the same object may conflict ([intro.races]).
explicit out_ptr_t(Smart& smart, Args... args);
Effects: Initializes s with smart, a with std​::​forward<Args>(args)..., and value-initializes p.
Then, equivalent to:
  • s.reset(); if the expression s.reset() is well-formed;
  • otherwise, s = Smart(); if is_constructible_v<Smart> is true;
  • otherwise, the program is ill-formed.
[Note 2: 
The constructor is not noexcept to allow for a variety of non-terminating and safe implementation strategies.
For example, an implementation can allocate a 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]
~out_ptr_t();
Let SP be POINTER_OF_OR(Smart, Pointer) ([memory.general]).
Effects: Equivalent to:
  • if (p) { apply([&](auto&&... args) { s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); } if the expression s.reset(static_cast<SP>(p), std​::​forward<Args>(args)...) is well-formed;
  • otherwise, if (p) { apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); } if is_constructible_v<Smart, SP, Args...> is true;
  • otherwise, the program is ill-formed.
operator Pointer*() const noexcept;
Preconditions: operator void**() has not been called on *this.
Returns: addressof(const_cast<Pointer&>(p)).
operator void**() const noexcept;
Constraints: is_same_v<Pointer, void*> is false.
Mandates: is_pointer_v<Pointer> is true.
Preconditions: operator Pointer*() has not been called on *this.
Returns: A pointer value v such that:
  • the initial value *v is equivalent to static_cast<void*>(p) and
  • any modification of *v that is not followed by a subsequent modification of *this affects the value of p during the destruction of *this, such that static_cast<void*>(p) == *v.
Remarks: Accessing *v outside the lifetime of *this has undefined behavior.
[Note 3: 
reinterpret_cast<void**>(static_cast<Pointer*>(*this)) can be a viable implementation strategy for some implementations.
— end note]

20.3.4.2 Function template out_ptr [out.ptr]

template<class Pointer = void, class Smart, class... Args> auto out_ptr(Smart& s, Args&&... args);
Let P be Pointer if is_void_v<Pointer> is false, otherwise POINTER_OF(Smart).
Returns: out_ptr_t<Smart, P, Args&&...>(s, std​::​forward<Args>(args)...)

20.3.4.3 Class template inout_ptr_t [inout.ptr.t]

inout_ptr_t is a class template used to adapt types such as smart pointers ([smartptr]) for functions that use output pointer parameters whose dereferenced values may first be deleted before being set to another allocated value.
[Example 1: #include <memory> 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<star_fish, star_fish_deleter>; 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; }
A unique_ptr can be used with 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]
namespace std { template<class Smart, class Pointer, class... Args> 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; // exposition only tuple<Args...> a; // exposition only Pointer p; // exposition only }; }
Pointer shall meet the Cpp17NullablePointer requirements.
If Smart is a specialization of shared_ptr, the program is ill-formed.
[Note 1: 
It is impossible to properly acquire unique ownership of the managed resource from a shared_ptr given its shared ownership model.
— end note]
Program-defined specializations of inout_ptr_t that depend on at least one program-defined type need not meet the requirements for the primary template.
Evaluations of the conversion functions on the same object may conflict ([intro.races]).
explicit inout_ptr_t(Smart& smart, Args... args);
Effects: Initializes s with smart, a with std​::​forward<Args>(args)..., and p to either
  • smart if is_pointer_v<Smart> is true,
  • otherwise, smart.get().
Remarks: An implementation can call s.release().
[Note 2: 
The constructor is not 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]
~inout_ptr_t();
Let SP be POINTER_OF_OR(Smart, Pointer) ([memory.general]).
Let release-statement be s.release(); if an implementation does not call s.release() in the constructor.
Otherwise, it is empty.
Effects: Equivalent to:
  • apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); if is_pointer_v<Smart> is true;
  • otherwise, release-statement; if (p) { apply([&](auto&&... args) { s.reset(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); } if the expression s.reset(static_cast<SP>(p), std​::​forward<Args>(args)...) is well-
    formed;
  • otherwise, release-statement; if (p) { apply([&](auto&&... args) { s = Smart(static_cast<SP>(p), std::forward<Args>(args)...); }, std::move(a)); } if is_constructible_v<Smart, SP, Args...> is true;
  • otherwise, the program is ill-formed.
operator Pointer*() const noexcept;
Preconditions: operator void**() has not been called on *this.
Returns: addressof(const_cast<Pointer&>(p)).
operator void**() const noexcept;
Constraints: is_same_v<Pointer, void*> is false.
Mandates: is_pointer_v<Pointer> is true.
Preconditions: operator Pointer*() has not been called on *this.
Returns: A pointer value v such that:
  • the initial value *v is equivalent to static_cast<void*>(p) and
  • any modification of *v that is not followed by subsequent modification of *this affects the value of p during the destruction of *this, such that static_cast<void*>(p) == *v.
Remarks: Accessing *v outside the lifetime of *this has undefined behavior.
[Note 3: 
reinterpret_cast<void**>(static_cast<Pointer*>(*this)) can be a viable implementation strategy for some implementations.
— end note]

20.3.4.4 Function template inout_ptr [inout.ptr]

template<class Pointer = void, class Smart, class... Args> auto inout_ptr(Smart& s, Args&&... args);
Let P be Pointer if is_void_v<Pointer> is false, otherwise POINTER_OF(Smart).
Returns: inout_ptr_t<Smart, P, Args&&...>(s, std​::​forward<Args>(args)...).

20.4 Memory resources [mem.res]

20.4.1 Header <memory_resource> synopsis [mem.res.syn]

namespace std::pmr { // [mem.res.class], class memory_resource class memory_resource; bool operator==(const memory_resource& a, const memory_resource& b) noexcept; // [mem.poly.allocator.class], class template polymorphic_allocator template<class Tp = byte> class polymorphic_allocator; template<class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept; // [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; // [mem.res.pool], pool resource classes struct pool_options; class synchronized_pool_resource; class unsynchronized_pool_resource; class monotonic_buffer_resource; }

20.4.2 Class memory_resource [mem.res.class]

20.4.2.1 General [mem.res.class.general]

The memory_resource class is an abstract interface to an unbounded set of classes encapsulating memory resources.
namespace std::pmr { class memory_resource { static constexpr size_t max_align = alignof(max_align_t); // exposition only public: memory_resource() = default; memory_resource(const memory_resource&) = default; virtual ~memory_resource(); memory_resource& operator=(const memory_resource&) = default; void* allocate(size_t bytes, size_t alignment = max_align); void deallocate(void* p, size_t bytes, size_t alignment = max_align); bool is_equal(const memory_resource& other) const noexcept; private: virtual void* do_allocate(size_t bytes, size_t alignment) = 0; virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; }; }

20.4.2.2 Public member functions [mem.res.public]

~memory_resource();
Effects: Destroys this memory_resource.
void* allocate(size_t bytes, size_t alignment = max_align);
Effects: Allocates storage by calling do_allocate(bytes, alignment) and implicitly creates objects within the allocated region of storage.
Returns: A pointer to a suitable created object ([intro.object]) in the allocated region of storage.
Throws: What and when the call to do_allocate throws.
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
Effects: Equivalent to do_deallocate(p, bytes, alignment).
bool is_equal(const memory_resource& other) const noexcept;
Effects: Equivalent to: return do_is_equal(other);

20.4.2.3 Private virtual member functions [mem.res.private]

virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
Preconditions: alignment is a power of two.
Returns: A derived class shall implement this function to return a pointer to allocated storage ([basic.stc.dynamic.allocation]) with a size of at least bytes, aligned to the specified alignment.
Throws: A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment.
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
Preconditions: p was returned from a prior call to allocate(bytes, alignment) on a memory resource equal to *this, and the storage at p has not yet been deallocated.
Effects: A derived class shall implement this function to dispose of allocated storage.
Throws: Nothing.
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
Returns: A derived class shall implement this function to return true if memory allocated from *this can be deallocated from other and vice-versa, otherwise false.
[Note 1: 
It is possible that the most-derived type of other does not match the type of *this.
For a derived class D, an implementation of this function can immediately return false if dynamic_cast<const D*>(&other) == nullptr.
— end note]

20.4.2.4 Equality [mem.res.eq]

bool operator==(const memory_resource& a, const memory_resource& b) noexcept;
Returns: &a == &b || a.is_equal(b).

20.4.3 Class template polymorphic_allocator [mem.poly.allocator.class]

20.4.3.1 General [mem.poly.allocator.class.general]

A specialization of class template pmr​::​polymorphic_allocator meets the Cpp17Allocator requirements ([allocator.requirements.general]) if its template argument is a cv-unqualified object type.
Constructed with different memory resources, different instances of the same specialization of pmr​::​polymorphic_allocator can exhibit entirely different allocation behavior.
This runtime polymorphism allows objects that use polymorphic_allocator to behave as if they used different allocator types at run time even though they use the same static allocator type.
A specialization of class template pmr​::​polymorphic_allocator meets the allocator completeness requirements ([allocator.requirements.completeness]) if its template argument is a cv-unqualified object type.
namespace std::pmr { template<class Tp = byte> class polymorphic_allocator { memory_resource* memory_rsrc; // exposition only public: using value_type = Tp; // [mem.poly.allocator.ctor], constructors polymorphic_allocator() noexcept; polymorphic_allocator(memory_resource* r); polymorphic_allocator(const polymorphic_allocator& other) = default; template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept; polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; // [mem.poly.allocator.mem], member functions Tp* allocate(size_t n); void deallocate(Tp* p, size_t n); 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<class T> T* allocate_object(size_t n = 1); template<class T> void deallocate_object(T* p, size_t n = 1); template<class T, class... CtorArgs> T* new_object(CtorArgs&&... ctor_args); template<class T> void delete_object(T* p); template<class T, class... Args> void construct(T* p, Args&&... args); template<class T> void destroy(T* p); polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; // friends friend bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept { return *a.resource() == *b.resource(); } }; }

20.4.3.2 Constructors [mem.poly.allocator.ctor]

polymorphic_allocator() noexcept;
Effects: Sets memory_rsrc to get_default_resource().
polymorphic_allocator(memory_resource* r);
Preconditions: r is non-null.
Effects: Sets memory_rsrc to r.
Throws: Nothing.
[Note 1: 
This constructor provides an implicit conversion from memory_resource*.
— end note]
template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
Effects: Sets memory_rsrc to other.resource().

20.4.3.3 Member functions [mem.poly.allocator.mem]

Tp* allocate(size_t n);
Effects: If numeric_limits<size_t>​::​max() / sizeof(Tp) < n, throws bad_array_new_length.
Otherwise equivalent to: return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
void deallocate(Tp* p, size_t n);
Preconditions: p was allocated from a memory resource x, equal to *memory_rsrc, using x.allocate(n * sizeof(Tp), alignof(Tp)).
Effects: Equivalent to memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp)).
Throws: Nothing.
void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
Effects: Equivalent to: return memory_rsrc->allocate(nbytes, alignment);
[Note 1: 
The return type is void* (rather than, e.g., byte*) to support conversion to an arbitrary pointer type U* by static_cast<U*>, thus facilitating construction of a U object in the allocated memory.
— end note]
void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
Effects: Equivalent to memory_rsrc->deallocate(p, nbytes, alignment).
template<class T> T* allocate_object(size_t n = 1);
Effects: Allocates memory suitable for holding an array of n objects of type T, as follows:
  • if numeric_limits<size_t>​::​max() / sizeof(T) < n, throws bad_array_new_length,
  • otherwise equivalent to: return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));
[Note 2: 
T is not deduced and must therefore be provided as a template argument.
— end note]
template<class T> void deallocate_object(T* p, size_t n = 1);
Effects: Equivalent to deallocate_bytes(p, n*sizeof(T), alignof(T)).
template<class T, class... CtorArgs> T* new_object(CtorArgs&&... ctor_args);
Effects: Allocates and constructs an object of type T, as follows.

Equivalent to: T* p = allocate_object<T>(); try { construct(p, std::forward<CtorArgs>(ctor_args)...); } catch (...) { deallocate_object(p); throw; } return p;
[Note 3: 
T is not deduced and must therefore be provided as a template argument.
— end note]
template<class T> void delete_object(T* p);
Effects: Equivalent to: destroy(p); deallocate_object(p);
template<class T, class... Args> void construct(T* p, Args&&... args);
Mandates: Uses-allocator construction of T with allocator *this (see [allocator.uses.construction]) and constructor arguments std​::​forward<Args>(args)... is well-formed.
Effects: Construct a T object in the storage whose address is represented by p by uses-allocator construction with allocator *this and constructor arguments std​::​forward<Args>(args)....
Throws: Nothing unless the constructor for T throws.
template<class T> void destroy(T* p);
Effects: Equivalent to p->~T().
polymorphic_allocator select_on_container_copy_construction() const;
Returns: polymorphic_allocator().
[Note 4: 
The memory resource is not propagated.
— end note]
memory_resource* resource() const;
Returns: memory_rsrc.

20.4.3.4 Equality [mem.poly.allocator.eq]

template<class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;
Returns: *a.resource() == *b.resource().

20.4.4 Access to program-wide memory_resource objects [mem.res.global]

memory_resource* new_delete_resource() noexcept;
Returns: A pointer to a static-duration object of a type derived from memory_resource that can serve as a resource for allocating memory using ​::​operator new and ​::​operator delete.
The same value is returned every time this function is called.
For a return value p and a memory resource r, p->is_equal(r) returns &r == p.
memory_resource* null_memory_resource() noexcept;
Returns: A pointer to a static-duration object of a type derived from memory_resource for which allocate() always throws bad_alloc and for which deallocate() has no effect.
The same value is returned every time this function is called.
For a return value p and a memory resource r, p->is_equal(r) returns &r == p.
The 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 new_delete_resource().
memory_resource* set_default_resource(memory_resource* r) noexcept;
Effects: If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
Returns: The previous value of the default memory resource pointer.
Remarks: Calling the set_default_resource and get_default_resource functions shall not incur a data race.
A call to the set_default_resource function shall synchronize with subsequent calls to the set_default_resource and get_default_resource functions.
memory_resource* get_default_resource() noexcept;
Returns: The current value of the default memory resource pointer.

20.4.5 Pool resource classes [mem.res.pool]

20.4.5.1 Classes synchronized_pool_resource and unsynchronized_pool_resource [mem.res.pool.overview]

The synchronized_pool_resource and unsynchronized_pool_resource classes (collectively called pool resource classes) are general-purpose memory resources having the following qualities:
  • Each resource frees its allocated memory on destruction, even if deallocate has not been called for some of the allocated blocks.
  • A pool resource consists of a collection of pools, serving requests for different block sizes.
    Each individual pool manages a collection of chunks that are in turn divided into blocks of uniform size, returned via calls to do_allocate.
    Each call to do_allocate(size, alignment) is dispatched to the pool serving the smallest blocks accommodating at least size bytes.
  • When a particular pool is exhausted, allocating a block from that pool results in the allocation of an additional chunk of memory from the upstream allocator (supplied at construction), thus replenishing the pool.
    With each successive replenishment, the chunk size obtained increases geometrically.
    [Note 1: 
    By allocating memory in chunks, the pooling strategy increases the chance that consecutive allocations will be close together in memory.
    — end note]
  • Allocation requests that exceed the largest block size of any pool are fulfilled directly from the upstream allocator.
  • A pool_options struct may be passed to the pool resource constructors to tune the largest block size and the maximum chunk size.
A synchronized_pool_resource may be accessed from multiple threads without external synchronization and may have thread-specific pools to reduce synchronization costs.
An unsynchronized_pool_resource class may not be accessed from multiple threads simultaneously and thus avoids the cost of synchronization entirely in single-threaded applications.
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; }; }

20.4.5.2 pool_options data members [mem.res.pool.options]

The members of pool_options comprise a set of constructor options for pool resources.
The effect of each option on the pool resource behavior is described below:
size_t max_blocks_per_chunk;
The maximum number of blocks that will be allocated at once from the upstream memory resource ([mem.res.monotonic.buffer]) to replenish a pool.
If the value of max_blocks_per_chunk is zero or is greater than an implementation-defined limit, that limit is used instead.
The implementation may choose to use a smaller value than is specified in this member and may use different values for different pools.
size_t largest_required_pool_block;
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 largest_required_pool_block is zero or is greater than an implementation-defined limit, that limit is used instead.
The implementation may choose a pass-through threshold larger than specified in this member.

20.4.5.3 Constructors and destructors [mem.res.pool.ctor]

synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
Preconditions: upstream is the address of a valid memory resource.
Effects: Constructs a pool resource object that will obtain memory from 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 upstream, but will not own the resource to which upstream points.
[Note 1: 
The intention is that calls to upstream->allocate() will be substantially fewer than calls to this->allocate() in most cases.
— end note]
The behavior of the pooling mechanism is tuned according to the value of the opts argument.
Throws: Nothing unless upstream->allocate() throws.
It is unspecified if, or under what conditions, this constructor calls upstream->allocate().
virtual ~synchronized_pool_resource(); virtual ~unsynchronized_pool_resource();
Effects: Calls release().

20.4.5.4 Members [mem.res.pool.mem]

void release();
Effects: Calls upstream_resource()->deallocate() as necessary to release all allocated memory.
[Note 1: 
The memory is released back to upstream_resource() even if deallocate has not been called for some of the allocated blocks.
— end note]
memory_resource* upstream_resource() const;
Returns: The value of the upstream argument provided to the constructor of this object.
pool_options options() const;
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 implementation-defined defaults, and sizes may be rounded to unspecified granularity.
void* do_allocate(size_t bytes, size_t alignment) override;
Effects: If the pool selected for a block of size bytes is unable to satisfy the memory request from its own internal data structures, it will call upstream_resource()->allocate() to obtain more memory.
If bytes is larger than that which the largest pool can handle, then memory will be allocated using upstream_resource()->allocate().
Returns: A pointer to allocated storage ([basic.stc.dynamic.allocation]) with a size of at least bytes.
The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource ([mem.res.class]).
Throws: Nothing unless upstream_resource()->allocate() throws.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Effects: Returns the memory at p to the pool.
It is unspecified if, or under what circumstances, this operation will result in a call to upstream_resource()->deallocate().
Throws: Nothing.
bool do_is_equal(const memory_resource& other) const noexcept override;
Returns: this == &other.

20.4.6 Class monotonic_buffer_resource [mem.res.monotonic.buffer]

20.4.6.1 General [mem.res.monotonic.buffer.general]

A 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.
namespace std::pmr { class monotonic_buffer_resource : public memory_resource { memory_resource* upstream_rsrc; // exposition only void* current_buffer; // exposition only size_t next_buffer_size; // exposition only 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; }; }

20.4.6.2 Constructors and destructor [mem.res.monotonic.buffer.ctor]

explicit monotonic_buffer_resource(memory_resource* upstream); monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
Preconditions: upstream is the address of a valid memory resource.
initial_size, if specified, is greater than zero.
Effects: Sets upstream_rsrc to upstream and current_buffer to nullptr.
If initial_size is specified, sets next_buffer_size to at least initial_size; otherwise sets next_buffer_size to an implementation-defined size.
monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
Preconditions: upstream is the address of a valid memory resource.
buffer_size is no larger than the number of bytes in buffer.
Effects: Sets upstream_rsrc to upstream, current_buffer to buffer, and next_buffer_size to buffer_size (but not less than 1), then increases next_buffer_size by an implementation-defined growth factor (which need not be integral).
~monotonic_buffer_resource();
Effects: Calls release().

20.4.6.3 Members [mem.res.monotonic.buffer.mem]

void release();
Effects: Calls upstream_rsrc->deallocate() as necessary to release all allocated memory.
Resets current_buffer and next_buffer_size to their initial values at construction.
[Note 1: 
The memory is released back to upstream_rsrc even if some blocks that were allocated from *this have not been deallocated from *this.
— end note]
memory_resource* upstream_resource() const;
Returns: The value of upstream_rsrc.
void* do_allocate(size_t bytes, size_t alignment) override;
Effects: If the unused space in current_buffer can fit a block with the specified bytes and alignment, then allocate the return block from current_buffer; otherwise set current_buffer to upstream_rsrc->allocate(n, m), where n is not less than max(bytes, next_buffer_size) and m is not less than alignment, and increase next_buffer_size by an implementation-defined growth factor (which need not be integral), then allocate the return block from the newly-allocated current_buffer.
Returns: A pointer to allocated storage ([basic.stc.dynamic.allocation]) with a size of at least bytes.
The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource ([mem.res.class]).
Throws: Nothing unless upstream_rsrc->allocate() throws.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Effects: None.
Throws: Nothing.
Remarks: Memory used by this resource increases monotonically until its destruction.
bool do_is_equal(const memory_resource& other) const noexcept override;
Returns: this == &other.

20.5 Class template scoped_allocator_adaptor [allocator.adaptor]

20.5.1 Header <scoped_allocator> synopsis [allocator.adaptor.syn]

namespace std { // class template scoped_allocator_adaptor template<class OuterAlloc, class... InnerAlloc> class scoped_allocator_adaptor; // [scoped.adaptor.operators], scoped allocator operators template<class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; }
The class template 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 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.
[Note 1: 
The 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]
namespace std { template<class OuterAlloc, class... InnerAllocs> class scoped_allocator_adaptor : public OuterAlloc { private: using OuterTraits = allocator_traits<OuterAlloc>; // exposition only scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only public: using outer_allocator_type = OuterAlloc; using inner_allocator_type = see below; 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 = see below; using propagate_on_container_move_assignment = see below; using propagate_on_container_swap = see below; using is_always_equal = see below; template<class Tp> struct rebind { using other = scoped_allocator_adaptor< OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>; }; scoped_allocator_adaptor(); template<class OuterA2> 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<class OuterA2> scoped_allocator_adaptor( const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; template<class OuterA2> scoped_allocator_adaptor( scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& 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; pointer allocate(size_type n); pointer allocate(size_type n, const_void_pointer hint); void deallocate(pointer p, size_type n); size_type max_size() const; template<class T, class... Args> void construct(T* p, Args&&... args); template<class T> void destroy(T* p); scoped_allocator_adaptor select_on_container_copy_construction() const; }; template<class OuterAlloc, class... InnerAllocs> scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>; }

20.5.2 Member types [allocator.adaptor.types]

using inner_allocator_type = see below;
Type: scoped_allocator_adaptor<OuterAlloc> if sizeof...(InnerAllocs) is zero; otherwise,
scoped_allocator_adaptor<InnerAllocs...>.
using propagate_on_container_copy_assignment = see below;
Type: true_type if allocator_traits<A>​::​propagate_on_container_copy_assignment​::​value is true for any A in the set of OuterAlloc and InnerAllocs...; otherwise, false_type.
using propagate_on_container_move_assignment = see below;
Type: true_type if allocator_traits<A>​::​propagate_on_container_move_assignment​::​value is true for any A in the set of OuterAlloc and InnerAllocs...; otherwise, false_type.
using propagate_on_container_swap = see below;
Type: true_type if allocator_traits<A>​::​propagate_on_container_swap​::​value is true for any A in the set of OuterAlloc and InnerAllocs...; otherwise, false_type.
using is_always_equal = see below;
Type: true_type if allocator_traits<A>​::​is_always_equal​::​value is true for every A in the set of OuterAlloc and InnerAllocs...; otherwise, false_type.

20.5.3 Constructors [allocator.adaptor.cnstr]

scoped_allocator_adaptor();
Effects: Value-initializes the OuterAlloc base class and the inner allocator object.
template<class OuterA2> scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
Constraints: is_constructible_v<OuterAlloc, OuterA2> is true.
Effects: Initializes the OuterAlloc base class with std​::​forward<OuterA2>(outerAlloc) and inner with innerAllocs... (hence recursively initializing each allocator within the adaptor with the corresponding allocator from the argument list).
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
Effects: Initializes each allocator within the adaptor with the corresponding allocator from other.
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
Effects: Move constructs each allocator within the adaptor with the corresponding allocator from other.
template<class OuterA2> scoped_allocator_adaptor( const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
Constraints: is_constructible_v<OuterAlloc, const OuterA2&> is true.
Effects: Initializes each allocator within the adaptor with the corresponding allocator from other.
template<class OuterA2> scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
Constraints: is_constructible_v<OuterAlloc, OuterA2> is true.
Effects: Initializes each allocator within the adaptor with the corresponding allocator rvalue from other.

20.5.4 Members [allocator.adaptor.members]

In the construct member functions, OUTERMOST(x) is OUTERMOST(x.outer_allocator()) if the expression x.outer_allocator() is valid ([temp.deduct]) and x otherwise; OUTERMOST_ALLOC_TRAITS(x) is allocator_traits<remove_reference_t<decltype(OUTERMOST(x))>>.
[Note 1: 
OUTERMOST(x) and OUTERMOST_ALLOC_TRAITS(x) are recursive operations.
It is incumbent upon the definition of outer_allocator() to ensure that the recursion terminates.
It will terminate for all instantiations of scoped_allocator_adaptor.
— end note]
inner_allocator_type& inner_allocator() noexcept; const inner_allocator_type& inner_allocator() const noexcept;
Returns: *this if sizeof...(InnerAllocs) is zero; otherwise, inner.
outer_allocator_type& outer_allocator() noexcept;
Returns: static_cast<OuterAlloc&>(*this).
const outer_allocator_type& outer_allocator() const noexcept;
Returns: static_cast<const OuterAlloc&>(*this).
pointer allocate(size_type n);
Returns: allocator_traits<OuterAlloc>​::​allocate(outer_allocator(), n).
pointer allocate(size_type n, const_void_pointer hint);
Returns: allocator_traits<OuterAlloc>​::​allocate(outer_allocator(), n, hint).
void deallocate(pointer p, size_type n) noexcept;
Effects: As if by: allocator_traits<OuterAlloc>​::​deallocate(outer_allocator(), p, n);
size_type max_size() const;
Returns: allocator_traits<OuterAlloc>​::​max_size(outer_allocator()).
template<class T, class... Args> void construct(T* p, Args&&... args);
Effects: Equivalent to: apply([p, this](auto&&... newargs) { OUTERMOST_ALLOC_TRAITS(*this)::construct( OUTERMOST(*this), p, std::forward<decltype(newargs)>(newargs)...); }, uses_allocator_construction_args<T>(inner_allocator(), std::forward<Args>(args)...));
template<class T> void destroy(T* p);
Effects: Calls OUTERMOST_ALLOC_TRAITS(*this)​::​destroy(OUTERMOST(*this), p).
scoped_allocator_adaptor select_on_container_copy_construction() const;
Returns: A new scoped_allocator_adaptor object where each allocator a1 within the adaptor is initialized with allocator_traits<A1>​::​select_on_container_copy_construction(a2), where A1 is the type of a1 and a2 is the corresponding allocator in *this.

20.5.5 Operators [scoped.adaptor.operators]

template<class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
Returns: If sizeof...(InnerAllocs) is zero, a.outer_allocator() == b.outer_allocator() otherwise a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()

21 Metaprogramming library [meta]

21.1 General [meta.general]

This Clause describes metaprogramming facilities.
These facilities are summarized in Table 48.
Table 48 — Metaprogramming library summary [tab:meta.summary]
Subclause
Header
Integer sequences
<utility>
Type traits
<type_traits>
Rational arithmetic
<ratio>

21.2 Compile-time integer sequences [intseq]

21.2.1 General [intseq.general]

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.
[Note 1: 
The index_sequence alias template is provided for the common case of an integer sequence of type size_t; see also [tuple.apply].
— end note]

21.2.2 Class template integer_sequence [intseq.intseq]

namespace std { template<class T, T... I> struct integer_sequence { using value_type = T; static constexpr size_t size() noexcept { return sizeof...(I); } }; }
Mandates: T is an integer type.

21.2.3 Alias template make_integer_sequence [intseq.make]

template<class T, T N> using make_integer_sequence = integer_sequence<T, see below>;
Mandates: N  ≥ 0.
The alias template make_integer_sequence denotes a specialization of integer_sequence with N non-type template arguments.
The type make_integer_sequence<T, N> is an alias for the type integer_sequence<T, 0, 1, ..., N-1>.
[Note 1: 
make_integer_sequence<int, 0> is an alias for the type integer_sequence<int>.
— end note]

21.3 Metaprogramming and type traits [type.traits]

21.3.1 General [type.traits.general]

Subclause [type.traits] describes components used by C++ 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 C++ 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.
All functions specified in [type.traits] are signal-safe ([support.signal]).

21.3.2 Requirements [meta.rqmts]

A Cpp17UnaryTypeTrait 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 Cpp17DefaultConstructible, Cpp17CopyConstructible, and publicly and unambiguously derived, directly or indirectly, from its base characteristic, which is a specialization of the template integral_constant, with the arguments to the template 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 Cpp17UnaryTypeTrait.
A Cpp17BinaryTypeTrait 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 Cpp17DefaultConstructible, Cpp17CopyConstructible, and publicly and unambiguously derived, directly or indirectly, from its base characteristic, which is a specialization of the template integral_constant, with the arguments to the template 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 Cpp17BinaryTypeTrait.
A Cpp17TransformationTrait 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 type, which shall be a synonym for the modified type.
Unless otherwise specified, the behavior of a program that adds specializations for any of the templates specified in [type.traits] is undefined.
Unless otherwise specified, an incomplete type may be used to instantiate a template specified in [type.traits].
The behavior of a program is undefined if
  • an instantiation of a template specified in [type.traits] directly or indirectly depends on an incompletely-defined object type T, and
  • that instantiation could yield a different result were T hypothetically completed.

21.3.3 Header <type_traits> synopsis [meta.type.synop]

// all freestanding namespace std { // [meta.help], helper class template<class T, T v> struct integral_constant; template<bool B> using bool_constant = integral_constant<bool, B>; using true_type = bool_constant<true>; using false_type = bool_constant<false>; // [meta.unary.cat], primary type categories template<class T> struct is_void; template<class T> struct is_null_pointer; template<class T> struct is_integral; template<class T> struct is_floating_point; template<class T> struct is_array; template<class T> struct is_pointer; template<class T> struct is_lvalue_reference; template<class T> struct is_rvalue_reference; template<class T> struct is_member_object_pointer; template<class T> struct is_member_function_pointer; template<class T> struct is_enum; template<class T> struct is_union; template<class T> struct is_class; template<class T> struct is_function; // [meta.unary.comp], composite type categories template<class T> struct is_reference; template<class T> struct is_arithmetic; template<class T> struct is_fundamental; template<class T> struct is_object; template<class T> struct is_scalar; template<class T> struct is_compound; template<class T> struct is_member_pointer; // [meta.unary.prop], type properties template<class T> struct is_const; template<class T> struct is_volatile; template<class T> struct is_trivially_copyable; template<class T> struct is_standard_layout; template<class T> struct is_empty; template<class T> struct is_polymorphic; template<class T> struct is_abstract; template<class T> struct is_final; template<class T> struct is_aggregate; template<class T> struct is_signed; template<class T> struct is_unsigned; template<class T> struct is_bounded_array; template<class T> struct is_unbounded_array; template<class T> struct is_scoped_enum; template<class T, class... Args> struct is_constructible; template<class T> struct is_default_constructible; template<class T> struct is_copy_constructible; template<class T> struct is_move_constructible; template<class T, class U> struct is_assignable; template<class T> struct is_copy_assignable; template<class T> struct is_move_assignable; template<class T, class U> struct is_swappable_with; template<class T> struct is_swappable; template<class T> struct is_destructible; template<class T, class... Args> struct is_trivially_constructible; template<class T> struct is_trivially_default_constructible; template<class T> struct is_trivially_copy_constructible; template<class T> struct is_trivially_move_constructible; template<class T, class U> struct is_trivially_assignable; template<class T> struct is_trivially_copy_assignable; template<class T> struct is_trivially_move_assignable; template<class T> struct is_trivially_destructible; template<class T, class... Args> struct is_nothrow_constructible; template<class T> struct is_nothrow_default_constructible; template<class T> struct is_nothrow_copy_constructible; template<class T> struct is_nothrow_move_constructible; template<class T, class U> struct is_nothrow_assignable; template<class T> struct is_nothrow_copy_assignable; template<class T> struct is_nothrow_move_assignable; template<class T, class U> struct is_nothrow_swappable_with; template<class T> struct is_nothrow_swappable; template<class T> struct is_nothrow_destructible; template<class T> struct is_implicit_lifetime; template<class T> struct has_virtual_destructor; template<class T> struct has_unique_object_representations; template<class T, class U> struct reference_constructs_from_temporary; template<class T, class U> struct reference_converts_from_temporary; // [meta.unary.prop.query], type property queries template<class T> struct alignment_of; template<class T> struct rank; template<class T, unsigned I = 0> struct extent; // [meta.rel], type relations template<class T, class U> struct is_same; template<class Base, class Derived> struct is_base_of; template<class Base, class Derived> struct is_virtual_base_of; template<class From, class To> struct is_convertible; template<class From, class To> struct is_nothrow_convertible; template<class T, class U> struct is_layout_compatible; template<class Base, class Derived> struct is_pointer_interconvertible_base_of; template<class Fn, class... ArgTypes> struct is_invocable; template<class R, class Fn, class... ArgTypes> struct is_invocable_r; template<class Fn, class... ArgTypes> struct is_nothrow_invocable; template<class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; // [meta.trans.cv], const-volatile modifications template<class T> struct remove_const; template<class T> struct remove_volatile; template<class T> struct remove_cv; template<class T> struct add_const; template<class T> struct add_volatile; template<class T> struct add_cv; template<class T> using remove_const_t = typename remove_const<T>::type; template<class T> using remove_volatile_t = typename remove_volatile<T>::type; template<class T> using remove_cv_t = typename remove_cv<T>::type; template<class T> using add_const_t = typename add_const<T>::type; template<class T> using add_volatile_t = typename add_volatile<T>::type; template<class T> using add_cv_t = typename add_cv<T>::type; // [meta.trans.ref], reference modifications template<class T> struct remove_reference; template<class T> struct add_lvalue_reference; template<class T> struct add_rvalue_reference; template<class T> using remove_reference_t = typename remove_reference<T>::type; template<class T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; template<class T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; // [meta.trans.sign], sign modifications template<class T> struct make_signed; template<class T> struct make_unsigned; template<class T> using make_signed_t = typename make_signed<T>::type; template<class T> using make_unsigned_t = typename make_unsigned<T>::type; // [meta.trans.arr], array modifications template<class T> struct remove_extent; template<class T> struct remove_all_extents; template<class T> using remove_extent_t = typename remove_extent<T>::type; template<class T> using remove_all_extents_t = typename remove_all_extents<T>::type; // [meta.trans.ptr], pointer modifications template<class T> struct remove_pointer; template<class T> struct add_pointer; template<class T> using remove_pointer_t = typename remove_pointer<T>::type; template<class T> using add_pointer_t = typename add_pointer<T>::type; // [meta.trans.other], other transformations template<class T> struct type_identity; template<class T> struct remove_cvref; template<class T> struct decay; template<bool, class T = void> struct enable_if; template<bool, class T, class F> struct conditional; template<class... T> struct common_type; template<class T, class U, template<class> class TQual, template<class> class UQual> struct basic_common_reference { }; template<class... T> struct common_reference; template<class T> struct underlying_type; template<class Fn, class... ArgTypes> struct invoke_result; template<class T> struct unwrap_reference; template<class T> struct unwrap_ref_decay; template<class T> using type_identity_t = typename type_identity<T>::type; template<class T> using remove_cvref_t = typename remove_cvref<T>::type; template<class T> using decay_t = typename decay<T>::type; template<bool B, class T = void> using enable_if_t = typename enable_if<B, T>::type; template<bool B, class T, class F> using conditional_t = typename conditional<B, T, F>::type; template<class... T> using common_type_t = typename common_type<T...>::type; template<class... T> using common_reference_t = typename common_reference<T...>::type; template<class T> using underlying_type_t = typename underlying_type<T>::type; template<class Fn, class... ArgTypes> using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type; template<class T> using unwrap_reference_t = typename unwrap_reference<T>::type; template<class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type; template<class...> using void_t = void; // [meta.logical], logical operator traits template<class... B> struct conjunction; template<class... B> struct disjunction; template<class B> struct negation; // [meta.unary.cat], primary type categories template<class T> constexpr bool is_void_v = is_void<T>::value; template<class T> constexpr bool is_null_pointer_v = is_null_pointer<T>::value; template<class T> constexpr bool is_integral_v = is_integral<T>::value; template<class T> constexpr bool is_floating_point_v = is_floating_point<T>::value; template<class T> constexpr bool is_array_v = is_array<T>::value; template<class T> constexpr bool is_pointer_v = is_pointer<T>::value; template<class T> constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value; template<class T> constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value; template<class T> constexpr bool is_member_object_pointer_v = is_member_object_pointer<T>::value; template<class T> constexpr bool is_member_function_pointer_v = is_member_function_pointer<T>::value; template<class T> constexpr bool is_enum_v = is_enum<T>::value; template<class T> constexpr bool is_union_v = is_union<T>::value; template<class T> constexpr bool is_class_v = is_class<T>::value; template<class T> constexpr bool is_function_v = is_function<T>::value; // [meta.unary.comp], composite type categories template<class T> constexpr bool is_reference_v = is_reference<T>::value; template<class T> constexpr bool is_arithmetic_v = is_arithmetic<T>::value; template<class T> constexpr bool is_fundamental_v = is_fundamental<T>::value; template<class T> constexpr bool is_object_v = is_object<T>::value; template<class T> constexpr bool is_scalar_v = is_scalar<T>::value; template<class T> constexpr bool is_compound_v = is_compound<T>::value; template<class T> constexpr bool is_member_pointer_v = is_member_pointer<T>::value; // [meta.unary.prop], type properties template<class T> constexpr bool is_const_v = is_const<T>::value; template<class T> constexpr bool is_volatile_v = is_volatile<T>::value; template<class T> constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value; template<class T> constexpr bool is_standard_layout_v = is_standard_layout<T>::value; template<class T> constexpr bool is_empty_v = is_empty<T>::value; template<class T> constexpr bool is_polymorphic_v = is_polymorphic<T>::value; template<class T> constexpr bool is_abstract_v = is_abstract<T>::value; template<class T> constexpr bool is_final_v = is_final<T>::value; template<class T> constexpr bool is_aggregate_v = is_aggregate<T>::value; template<class T> constexpr bool is_signed_v = is_signed<T>::value; template<class T> constexpr bool is_unsigned_v = is_unsigned<T>::value; template<class T> constexpr bool is_bounded_array_v = is_bounded_array<T>::value; template<class T> constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value; template<class T> constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value; template<class T, class... Args> constexpr bool is_constructible_v = is_constructible<T, Args...>::value; template<class T> constexpr bool is_default_constructible_v = is_default_constructible<T>::value; template<class T> constexpr bool is_copy_constructible_v = is_copy_constructible<T>::value; template<class T> constexpr bool is_move_constructible_v = is_move_constructible<T>::value; template<class T, class U> constexpr bool is_assignable_v = is_assignable<T, U>::value; template<class T> constexpr bool is_copy_assignable_v = is_copy_assignable<T>::value; template<class T> constexpr bool is_move_assignable_v = is_move_assignable<T>::value; template<class T, class U> constexpr bool is_swappable_with_v = is_swappable_with<T, U>::value; template<class T> constexpr bool is_swappable_v = is_swappable<T>::value; template<class T> constexpr bool is_destructible_v = is_destructible<T>::value; template<class T, class... Args> constexpr bool is_trivially_constructible_v = is_trivially_constructible<T, Args...>::value; template<class T> constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value; template<class T> constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<T>::value; template<class T> constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<T>::value; template<class T, class U> constexpr bool is_trivially_assignable_v = is_trivially_assignable<T, U>::value; template<class T> constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<T>::value; template<class T> constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<T>::value; template<class T> constexpr bool is_trivially_destructible_v = is_trivially_destructible<T>::value; template<class T, class... Args> constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<T, Args...>::value; template<class T> constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible<T>::value; template<class T> constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<T>::value; template<class T> constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<T>::value; template<class T, class U> constexpr bool is_nothrow_assignable_v = is_nothrow_assignable<T, U>::value; template<class T> constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<T>::value; template<class T> constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value; template<class T, class U> constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<T, U>::value; template<class T> constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<T>::value; template<class T> constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<T>::value; template<class T> constexpr bool is_implicit_lifetime_v = is_implicit_lifetime<T>::value; template<class T> constexpr bool has_virtual_destructor_v = has_virtual_destructor<T>::value; template<class T> constexpr bool has_unique_object_representations_v = has_unique_object_representations<T>::value; template<class T, class U> constexpr bool reference_constructs_from_temporary_v = reference_constructs_from_temporary<T, U>::value; template<class T, class U> constexpr bool reference_converts_from_temporary_v = reference_converts_from_temporary<T, U>::value; // [meta.unary.prop.query], type property queries template<class T> constexpr size_t alignment_of_v = alignment_of<T>::value; template<class T> constexpr size_t rank_v = rank<T>::value; template<class T, unsigned I = 0> constexpr size_t extent_v = extent<T, I>::value; // [meta.rel], type relations template<class T, class U> constexpr bool is_same_v = is_same<T, U>::value; template<class Base, class Derived> constexpr bool is_base_of_v = is_base_of<Base, Derived>::value; template<class Base, class Derived> constexpr bool is_virtual_base_of_v = is_virtual_base_of<Base, Derived>::value; template<class From, class To> constexpr bool is_convertible_v = is_convertible<From, To>::value; template<class From, class To> constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value; template<class T, class U> constexpr bool is_layout_compatible_v = is_layout_compatible<T, U>::value; template<class Base, class Derived> constexpr bool is_pointer_interconvertible_base_of_v = is_pointer_interconvertible_base_of<Base, Derived>::value; template<class Fn, class... ArgTypes> constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value; template<class R, class Fn, class... ArgTypes> constexpr bool is_invocable_r_v = is_invocable_r<R, Fn, ArgTypes...>::value; template<class Fn, class... ArgTypes> constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; template<class R, class Fn, class... ArgTypes> constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; // [meta.logical], logical operator traits template<class... B> constexpr bool conjunction_v = conjunction<B...>::value; template<class... B> constexpr bool disjunction_v = disjunction<B...>::value; template<class B> constexpr bool negation_v = negation<B>::value; // [meta.member], member relationships template<class S, class M> constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept; template<class S1, class S2, class M1, class M2> constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; // [meta.const.eval], constant evaluation context constexpr bool is_constant_evaluated() noexcept; consteval bool is_within_lifetime(const auto*) noexcept; }

21.3.4 Helper classes [meta.help]

namespace std { template<class T, T v> struct integral_constant { static constexpr T value = v; using value_type = T; using type = integral_constant<T, v>; constexpr operator value_type() const noexcept { return value; } constexpr value_type operator()() const noexcept { return value; } }; }
The class template integral_constant, alias template bool_constant, and its associated typedef-names true_type and false_type are used as base classes to define the interface for various type traits.

21.3.5 Unary type traits [meta.unary]

21.3.5.1 General [meta.unary.general]

Subclause [meta.unary] contains templates that may be used to query the properties of a type at compile time.
Each of these templates shall be a Cpp17UnaryTypeTrait with a base characteristic of true_type if the corresponding condition is true, otherwise false_type.

21.3.5.2 Primary type categories [meta.unary.cat]

The primary type categories specified in Table 49 correspond to the descriptions given in subclause [basic.types] of the C++ standard.
For any given type T, the result of applying one of these templates to T and to cv T shall yield the same result.
[Note 1: 
For any given type T, exactly one of the primary type categories has a value member that evaluates to true.
— end note]
Table 49 — Primary type category predicates [tab:meta.unary.cat]
Template
Condition
Comments
template<class T>
struct is_void;
T is void
template<class T>
struct is_null_pointer;
T is nullptr_t ([basic.fundamental])
template<class T>
struct is_integral;
T is an integral type ([basic.fundamental])
template<class T>
struct is_floating_point;
T is a floating-point type ([basic.fundamental])
template<class T>
struct is_array;
T is an array type ([basic.compound]) of known or unknown extent
Class template array ([array]) is not an array type.
template<class T>
struct is_pointer;
T is a pointer type ([basic.compound])
Includes pointers to functions but not pointers to non-static members.
template<class T>
struct is_lvalue_reference;
T is an lvalue reference type ([dcl.ref])
template<class T>
struct is_rvalue_reference;
T is an rvalue reference type ([dcl.ref])
template<class T>
struct is_member_object_pointer;
T is a pointer to data member
template<class T>
struct is_member_function_pointer;
T is a pointer to member function
template<class T>
struct is_enum;
T is an enumeration type ([basic.compound])
template<class T>
struct is_union;
T is a union type ([basic.compound])
template<class T>
struct is_class;
T is a non-union class type ([basic.compound])
template<class T>
struct is_function;
T is a function type ([basic.compound])

21.3.5.3 Composite type traits [meta.unary.comp]

The templates specified in Table 50 provide convenient compositions of the primary type categories, corresponding to the descriptions given in subclause [basic.types].
For any given type T, the result of applying one of these templates to T and to cv T shall yield the same result.
Table 50 — Composite type category predicates [tab:meta.unary.comp]
Template
Condition
Comments
template<class T>
struct is_reference;
T is an lvalue reference or an rvalue reference
template<class T>
struct is_arithmetic;
T is an arithmetic type ([basic.fundamental])
template<class T>
struct is_fundamental;
T is a fundamental type ([basic.fundamental])
template<class T>
struct is_object;
T is an object type ([basic.types.general])
template<class T>
struct is_scalar;
T is a scalar type ([basic.types.general])
template<class T>
struct is_compound;
T is a compound type ([basic.compound])
template<class T>
struct is_member_pointer;
T is a pointer-to-member type ([basic.compound])

21.3.5.4 Type properties [meta.unary.prop]

The templates specified in Table 51 provide access to some of the more important properties of types.
It is unspecified whether the library defines any full or partial specializations of any of these templates.
For all of the class templates 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 X require that the argument is a complete type.
For the purpose of defining the templates in this subclause, a function call expression declval<T>() for any type T is considered to be a trivial ([depr.meta.types], [special]) function call that is not an odr-use ([basic.def.odr]) of declval in the context of the corresponding definition notwithstanding the restrictions of [declval].
For the purpose of defining the templates in this subclause, let VAL<T> for some type T be an expression defined as follows:
  • If T is a reference or function type, VAL<T> is an expression with the same type and value category as declval<T>().
  • Otherwise, VAL<T> is a prvalue that initially has type T.
    [Note 1: 
    If T is cv-qualified, the cv-qualification is subject to adjustment ([expr.type]).
    — end note]
Table 51 — Type property predicates [tab:meta.unary.prop]
Template
Condition
Preconditions
template<class T>
struct is_const;
T is const-qualified ([basic.type.qualifier])
template<class T>
struct is_volatile;
T is volatile-qualified ([basic.type.qualifier])
template<class T>
struct is_trivially_copyable;
T is a trivially copyable type ([basic.types.general])
remove_all_extents_t<T> shall be a complete type or cv void.
template<class T>
struct is_standard_layout;
T is a standard-layout type ([basic.types.general])
remove_all_extents_t<T> shall be a complete type or cv void.
template<class T>
struct is_empty;
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 B for which is_empty_v<B> is false.
If T is a non-union class type, T shall be a complete type.
template<class T>
struct is_polymorphic;
T is a polymorphic class ([class.virtual])
If T is a non-union class type, T shall be a complete type.
template<class T>
struct is_abstract;
T is an abstract class ([class.abstract])
If T is a non-union class type, T shall be a complete type.
template<class T>
struct is_final;
T is a class type marked with the class-virt-specifier final ([class.pre]).
[Note 2: 
A union is a class type that can be marked with final.
— end note]
If T is a class type, T shall be a complete type.
template<class T>
struct is_aggregate;
T is an aggregate type ([dcl.init.aggr])
T shall be an array type, a complete type, or cv void.
template<class T>
struct is_signed;
If is_arithmetic_v<T> is true, the same result as T(-1) < T(0); otherwise, false
template<class T>
struct is_unsigned;
If is_arithmetic_v<T> is true, the same result as T(0) < T(-1); otherwise, false
template<class T>
struct is_bounded_array;
T is an array type of known bound ([dcl.array])
template<class T>
struct is_unbounded_array;
T is an array type of unknown bound ([dcl.array])
template<class T>
struct is_scoped_enum;
T is a scoped enumeration ([dcl.enum])
template<class T, class... Args>
struct is_constructible;
For a function type T or for a cv void type T, is_constructible_v<T, Args...> is false, otherwise see below
T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_default_constructible;
is_constructible_v<T> is true.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_copy_constructible;
For a referenceable type T ([defns.referenceable]), the same result as is_constructible_v<T, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_move_constructible;
For a referenceable type T, the same result as is_constructible_v<T, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class U>
struct is_assignable;
The expression declval<T>() = declval<U>() is well-formed when treated as an unevaluated operand ([expr.context]).
Access checking is performed as if in a context unrelated to T and U.
Only the validity of the immediate context of the assignment expression is considered.
[Note 3: 
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]
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_copy_assignable;
For a referenceable type T, the same result as is_assignable_v<T&, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_move_assignable;
For a referenceable type T, the same result as is_assignable_v<T&, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class U>
struct is_swappable_with;
The expressions swap(declval<T>(), declval<U>()) and swap(declval<U>(), declval<T>()) are each well-formed when treated as an unevaluated operand ([expr.context]) in an overload-resolution context for swappable values ([swappable.requirements]).
Access checking is performed as if in a context unrelated to T and U.
Only the validity of the immediate context of the swap expressions is considered.
[Note 4: 
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 note]
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_swappable;
For a referenceable type T, the same result as is_swappable_with_v<T&, T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_destructible;
Either T is a reference type, or T is a complete object type for which the expression declval<U&>().~U() is well-formed when treated as an unevaluated operand ([expr.context]), where U is remove_all_extents_t<T>.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class... Args>
struct
is_trivially_constructible;
is_constructible_v<T,
Args...> is true and the variable definition for is_constructible, as defined below, is known to call no operation that is not trivial ([depr.meta.types], [special]).
T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_trivially_default_constructible;
is_trivially_constructible_v<T> is true.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_trivially_copy_constructible;
For a referenceable type T, the same result as is_trivially_constructible_v<T, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_trivially_move_constructible;
For a referenceable type T, the same result as is_trivially_constructible_v<T, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class U>
struct is_trivially_assignable;
is_assignable_v<T, U> is true and the assignment, as defined by is_assignable, is known to call no operation that is not trivial ([depr.meta.types], [special]).
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_trivially_copy_assignable;
For a referenceable type T, the same result as is_trivially_assignable_v<T&, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_trivially_move_assignable;
For a referenceable type T, the same result as is_trivially_assignable_v<T&, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_trivially_destructible;
is_destructible_v<T> is true and remove_all_extents_t<T> is either a non-class type or a class type with a trivial destructor.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class... Args>
struct is_nothrow_constructible;
is_constructible_v<T, Args...> is true and the variable definition for is_constructible, as defined below, is known not to throw any exceptions ([expr.unary.noexcept]).
T and all types in the template parameter pack Args shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_nothrow_default_constructible;
is_nothrow_constructible_v<T> is true.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_nothrow_copy_constructible;
For a referenceable type T, the same result as is_nothrow_constructible_v<T, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_nothrow_move_constructible;
For a referenceable type T, the same result as is_nothrow_constructible_v<T, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class U>
struct is_nothrow_assignable;
is_assignable_v<T, U> is true and the assignment is known not to throw any exceptions ([expr.unary.noexcept]).
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_nothrow_copy_assignable;
For a referenceable type T, the same result as is_nothrow_assignable_v<T&, const T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_nothrow_move_assignable;
For a referenceable type T, the same result as is_nothrow_assignable_v<T&, T&&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T, class U>
struct is_nothrow_swappable_with;
is_swappable_with_v<T, U> is true and each swap expression of the definition of is_swappable_with<T, U> is known not to throw any exceptions ([expr.unary.noexcept]).
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T>
struct is_nothrow_swappable;
For a referenceable type T, the same result as is_nothrow_swappable_with_v<T&, T&>, otherwise false.
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_nothrow_destructible;
is_destructible_v<T> is true and the indicated destructor is known not to throw any exceptions ([expr.unary.noexcept]).
T shall be a complete type, cv void, or an array of unknown bound.
template<class T>
struct is_implicit_lifetime;
T is an implicit-lifetime type ([basic.types.general]).
T shall be an array type, a complete type, or cv void.
template<class T>
struct has_virtual_destructor;
T has a virtual destructor ([class.dtor])
If T is a non-union class type, T shall be a complete type.
template<class T>
struct has_unique_object_representations;
For an array type T, the same result as has_unique_object_representations_v<remove_all_extents_t<T>>, otherwise see below.
remove_all_extents_t<T> shall be a complete type or cv void.
template<class T, class U>
struct reference_constructs_from_temporary;
T is a reference type, and the initialization T t(VAL<U>); is well-formed and binds t to a temporary object whose lifetime is extended ([class.temporary]).
Access checking is performed as if in a context unrelated to T and U.
Only the validity of the immediate context of the variable initialization is considered.
[Note 5: 
The initialization can result in effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on.
Such effects are not in the “immediate context” and can result in the program being ill-formed.
— end note]
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class T, class U>
struct reference_converts_from_temporary;
T is a reference type, and the initialization T t = VAL<U>; is well-formed and binds t to a temporary object whose lifetime is extended ([class.temporary]).
Access checking is performed as if in a context unrelated to T and U.
Only the validity of the immediate context of the variable initialization is considered.
[Note 6: 
The initialization can result in effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on.
Such effects are not in the “immediate context” and can result in the program being ill-formed.
— end note]
T and U shall be complete types, cv void, or arrays of unknown bound.
[Example 1: is_const_v<const volatile int> // true is_const_v<const int*> // false is_const_v<const int&> // false is_const_v<int[3]> // false is_const_v<const int[3]> // true — end example]
[Example 2: remove_const_t<const volatile int> // volatile int remove_const_t<const int* const> // const int* remove_const_t<const int&> // const int& remove_const_t<const int[3]> // int[3] — end example]
[Example 3: // Given: struct P final { }; union U1 { }; union U2 final { }; // the following assertions hold: static_assert(!is_final_v<int>); static_assert(is_final_v<P>); static_assert(!is_final_v<U1>); static_assert(is_final_v<U2>); — end example]
The predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t:
T t(declval<Args>()...);
[Note 7: 
These tokens are never interpreted as a function declaration.
— end note]
Access checking is performed as if in a context unrelated to T and any of the Args.
Only the validity of the immediate context of the variable initialization is considered.
[Note 8: 
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]
The predicate condition for a template specialization has_unique_object_representations<T> shall be satisfied if and only if
  • T is trivially copyable, and
  • any two objects of type 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.
The set of scalar types for which this condition holds is implementation-defined.
[Note 9: 
If a type has padding bits, the condition does not hold; otherwise, the condition holds true for integral types.
— end note]

21.3.6 Type property queries [meta.unary.prop.query]

The templates specified in Table 52 may be used to query properties of types at compile time.
Table 52 — Type property queries [tab:meta.unary.prop.query]
Template
Value
template<class T>
struct alignment_of;
alignof(T).

Mandates: alignof(T) is a valid expression ([expr.alignof])
template<class T>
struct rank;
If T is an array type, an integer value representing the number of dimensions of T; otherwise, 0.
template<class T,
unsigned I = 0>
struct extent;
If T is not an array type, or if it has rank less than or equal to I, or if I is 0 and T has type “array of unknown bound of U”, then 0; otherwise, the bound ([dcl.array]) of the dimension of T, where indexing of I is zero-based
Each of these templates shall be a Cpp17UnaryTypeTrait ([meta.rqmts]) with a base characteristic of integral_constant<size_t, Value>.
[Example 1: // the following assertions hold: static_assert(rank_v<int> == 0); static_assert(rank_v<int[2]> == 1); static_assert(rank_v<int[][4]> == 2); — end example]
[Example 2: // the following assertions hold: static_assert(extent_v<int> == 0); static_assert(extent_v<int[2]> == 2); static_assert(extent_v<int[2][4]> == 2); static_assert(extent_v<int[][4]> == 0); static_assert(extent_v<int, 1> == 0); static_assert(extent_v<int[2], 1> == 0); static_assert(extent_v<int[2][4], 1> == 4); static_assert(extent_v<int[][4], 1> == 4); — end example]

21.3.7 Relationships between types [meta.rel]

The templates specified in Table 53 may be used to query relationships between types at compile time.
Each of these templates shall be a Cpp17BinaryTypeTrait ([meta.rqmts]) with a base characteristic of true_type if the corresponding condition is true, otherwise false_type.
Table 53 — Type relationship predicates [tab:meta.rel]
Template
Condition
Comments
template<class T, class U>
struct is_same;
T and U name the same type with the same cv-qualifications
template<class Base, class Derived>
struct is_base_of;
Base is a base class of Derived ([class.derived]) without regard to cv-qualifiers or Base and Derived are not unions and name the same class type without regard to cv-qualifiers
If Base and Derived are non-union class types and are not (possibly cv-qualified versions of) the same type, Derived shall be a complete type.
[Note 1: 
Base classes that are private, protected, or ambiguous are, nonetheless, base classes.
— end note]
template<class Base, class Derived>
struct is_virtual_base_of;
Base is a virtual base class of Derived ([class.mi]) without regard to cv-qualifiers.
If Base and Derived are non-union class types, Derived shall be a complete type.
[Note 2: 
Virtual base classes that are private, protected, or ambiguous are, nonetheless, virtual base classes.
— end note]
[Note 3: 
A class is never a virtual base class of itself.
— end note]
template<class From, class To>
struct is_convertible;
see below
From and To shall be complete types, cv void, or arrays of unknown bound.
template<class From, class To>
struct is_nothrow_convertible;
is_convertible_v<From, To> is true and the conversion, as defined by is_convertible, is known not to throw any exceptions ([expr.unary.noexcept])
From and To shall be complete types, cv void, or arrays of unknown bound.
template<class T, class U>
struct is_layout_compatible;
T and U are layout-compatible ([basic.types.general])
T and U shall be complete types, cv void, or arrays of unknown bound.
template<class Base, class Derived>
struct is_pointer_interconvertible_base_of;
Derived is unambiguously derived from Base without regard to cv-qualifiers, and each object of type Derived is pointer-interconvertible ([basic.compound]) with its Base subobject, or Base and Derived are not unions and name the same class type without regard to cv-qualifiers.
If Base and Derived are non-union class types and are not (possibly cv-qualified versions of) the same type, Derived shall be a complete type.
template<class Fn, class... ArgTypes>
struct is_invocable;
The expression INVOKE(declval<Fn>(), declval<ArgTypes>()...) ([func.require]) is well-formed when treated as an unevaluated operand ([expr.context])
Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
template<class R, class Fn, class... ArgTypes>
struct is_invocable_r;
The expression INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...) is well-formed when treated as an unevaluated operand
Fn, R, and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
template<class Fn, class... ArgTypes>
struct is_nothrow_invocable;
is_invocable_v<
Fn, ArgTypes...> is true and the expression INVOKE(declval<Fn>(), declval<ArgTypes>()...) is known not to throw any exceptions ([expr.unary.noexcept])
Fn and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
template<class R, class Fn, class... ArgTypes>
struct is_nothrow_invocable_r;
is_invocable_r_v<
R, Fn, ArgTypes...> is true and the expression INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...) is known not to throw any exceptions ([expr.unary.noexcept])
Fn, R, and all types in the template parameter pack ArgTypes shall be complete types, cv void, or arrays of unknown bound.
For the purpose of defining the templates in this subclause, a function call expression declval<T>() for any type T is considered to be a trivial ([depr.meta.types], [special]) function call that is not an odr-use ([basic.def.odr]) of declval in the context of the corresponding definition notwithstanding the restrictions of [declval].
[Example 1: struct B {}; struct B1 : B {}; struct B2 : B {}; struct D : private B1, private B2 {}; is_base_of_v<B, D> // true is_base_of_v<const B, D> // true is_base_of_v<B, const D> // true is_base_of_v<B, const B> // true is_base_of_v<D, B> // false is_base_of_v<B&, D&> // false is_base_of_v<B[3], D[3]> // false is_base_of_v<int, int> // false — end example]
The predicate condition for a template specialization is_convertible<From, To> 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: To test() { return declval<From>(); }
[Note 4: 
This requirement gives well-defined results for reference types, array types, function types, and cv void.
— end note]
Access checking is performed in a context unrelated to To and From.
Only the validity of the immediate context of the expression of the return statement ([stmt.return]) (including initialization of the returned object or reference) is considered.
[Note 5: 
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]

21.3.8 Transformations between types [meta.trans]

21.3.8.1 General [meta.trans.general]

Subclause [meta.trans] contains templates that may be used to transform one type to another following some predefined rule.
Each of the templates in [meta.trans] shall be a Cpp17TransformationTrait ([meta.rqmts]).

21.3.8.2 Const-volatile modifications [meta.trans.cv]

The templates specified in Table 54 add or remove cv-qualifications ([basic.type.qualifier]).
Table 54 — Const-volatile modifications [tab:meta.trans.cv]
Template
Comments
template<class T>
struct remove_const;
The member typedef type denotes the type formed by removing any top-level const-qualifier from T.
[Example 1: 
remove_const_t<const volatile int> evaluates to volatile int, whereas remove_const_t<const int*> evaluates to const int*.
— end example]
template<class T>
struct remove_volatile;
The member typedef type denotes the type formed by removing any top-level volatile-qualifier from T.
[Example 2: 
remove_volatile_t<const volatile int> evaluates to const int, whereas remove_volatile_t<volatile int*> evaluates to volatile int*.
— end example]
template<class T>
struct remove_cv;
The member typedef type denotes the type formed by removing any top-level cv-qualifiers from T.
[Example 3: 
remove_cv_t<const volatile int> evaluates to int, whereas remove_cv_t<const volatile int*> evaluates to const volatile int*.
— end example]
template<class T>
struct add_const;
If T is a reference, function, or top-level const-qualified type, then type denotes T, otherwise T const.
template<class T>
struct add_volatile;
If T is a reference, function, or top-level volatile-qualified type, then type denotes T, otherwise T volatile.
template<class T>
struct add_cv;
The member typedef type denotes add_const_t<add_volatile_t<T>>.

21.3.8.3 Reference modifications [meta.trans.ref]

The templates specified in Table 55 add or remove references.
Table 55 — Reference modifications [tab:meta.trans.ref]
Template
Comments
template<class T>
struct remove_reference;
If T has type “reference to T1” then the member typedef type denotes T1; otherwise, type denotes T.
template<class T>
struct add_lvalue_reference;
If T is a referenceable type ([defns.referenceable]) then the member typedef type denotes T&; otherwise, type denotes T.
[Note 1: 
This rule reflects the semantics of reference collapsing ([dcl.ref]).
— end note]
template<class T>
struct add_rvalue_reference;
If T is a referenceable type then the member typedef type denotes T&&; otherwise, type denotes T.
[Note 2: 
This rule reflects the semantics of reference collapsing ([dcl.ref]).
For example, when a type T is a reference type T1&, the type add_rvalue_reference_t<T> is not an rvalue reference.
— end note]

21.3.8.4 Sign modifications [meta.trans.sign]

The templates specified in Table 56 convert an integer type to its corresponding signed or unsigned type.
Table 56 — Sign modifications [tab:meta.trans.sign]
Template
Comments
template<class T>
struct make_signed;
If T is a (possibly cv-qualified) signed integer type ([basic.fundamental]) then the member typedef type denotes T; otherwise, if T is a (possibly cv-qualified) unsigned integer type then type denotes the corresponding signed integer type, with the same cv-qualifiers as T; otherwise, type denotes the signed integer type with smallest rank ([conv.rank]) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T.

Mandates: T is an integral or enumeration type other than cv bool.
template<class T>
struct make_unsigned;
If T is a (possibly cv-qualified) unsigned integer type ([basic.fundamental]) then the member typedef type denotes T; otherwise, if T is a (possibly cv-qualified) signed integer type then type denotes the corresponding unsigned integer type, with the same cv-qualifiers as T; otherwise, type denotes the unsigned integer type with smallest rank ([conv.rank]) for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T.

Mandates: T is an integral or enumeration type other than cv bool.

21.3.8.5 Array modifications [meta.trans.arr]

The templates specified in Table 57 modify array types.
Table 57 — Array modifications [tab:meta.trans.arr]
Template
Comments
template<class T>
struct remove_extent;
If T is a type “array of U”, the member typedef type denotes U, otherwise T.
[Note 1: 
For multidimensional arrays, only the first array dimension is removed.
For a type “array of const U”, the resulting type is const U.
— end note]
template<class T>
struct remove_all_extents;
If T is “multidimensional array of U”, the resulting member typedef type denotes U, otherwise T.
[Example 1: // the following assertions hold: static_assert(is_same_v<remove_extent_t<int>, int>); static_assert(is_same_v<remove_extent_t<int[2]>, int>); static_assert(is_same_v<remove_extent_t<int[2][3]>, int[3]>); static_assert(is_same_v<remove_extent_t<int[][3]>, int[3]>); — end example]
[Example 2: // the following assertions hold: static_assert(is_same_v<remove_all_extents_t<int>, int>); static_assert(is_same_v<remove_all_extents_t<int[2]>, int>); static_assert(is_same_v<remove_all_extents_t<int[2][3]>, int>); static_assert(is_same_v<remove_all_extents_t<int[][3]>, int>); — end example]

21.3.8.6 Pointer modifications [meta.trans.ptr]

The templates specified in Table 58 add or remove pointers.
Table 58 — Pointer modifications [tab:meta.trans.ptr]
Template
Comments
template<class T>
struct remove_pointer;
If T has type “(possibly cv-qualified) pointer to T1” then the member typedef type denotes T1; otherwise, it denotes T.
template<class T>
struct add_pointer;
If T is a referenceable type ([defns.referenceable]) or a cv void type then the member typedef type denotes remove_reference_t<T>*; otherwise, type denotes T.

21.3.8.7 Other transformations [meta.trans.other]

The templates specified in Table 59 perform other modifications of a type.
Table 59 — Other transformations [tab:meta.trans.other]
Template
Comments
template<class T>
struct type_identity;
The member typedef type denotes T.
template<class T>
struct remove_cvref;
The member typedef type denotes remove_cv_t<remove_reference_t<T>>.
template<class T>
struct decay;
If is_array_v<U> is true, the member typedef type denotes remove_extent_t<U>*.
If is_function_v<U> is true, the member typedef type denotes add_pointer_t<U>.
Otherwise the member typedef type denotes remove_cv_t<U>.
[Note 1: 
This behavior is similar to the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([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 note]
template<bool B, class T = void> struct enable_if;
If B is true, the member typedef type denotes T; otherwise, there shall be no member type.
template<bool B, class T, class F>
struct conditional;
If B is true, the member typedef type denotes T.
If B is false, the member typedef type denotes F.
template<class... T> struct common_type;
Unless this trait is specialized, the member type is defined or omitted as specified below.
If it is omitted, there shall be no member type.
Each type in the template parameter pack T shall be complete, cv void, or an array of unknown bound.
template<class, class, template<class> class, template<class> class> struct basic_common_reference;
Unless this trait is specialized, there shall be no member type.
template<class... T> struct common_reference;
The member typedef-name type is defined or omitted as specified below.
Each type in the parameter pack T shall be complete or cv void.
template<class T>
struct underlying_type;
If T is an enumeration type, the member typedef type denotes the underlying type of T ([dcl.enum]); otherwise, there is no member type.

Mandates: T is not an incomplete enumeration type.
template<class Fn,
class... ArgTypes>
struct invoke_result;
If the expression INVOKE(declval<Fn>(), declval<ArgTypes>()...) ([func.require]) is well-formed when treated as an unevaluated operand ([expr.context]), the member typedef type denotes the type decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)); otherwise, there shall be no member type.
Access checking is performed as if in a context unrelated to Fn and ArgTypes.
Only the validity of the immediate context of the expression is considered.
[Note 2: 
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]
Preconditions: Fn and all types in the template parameter pack ArgTypes are complete types, cv void, or arrays of unknown bound.
template<class T> struct unwrap_reference;
If T is a specialization reference_wrapper<X> for some type X, the member typedef type of unwrap_reference<T> denotes X&, otherwise type denotes T.
template<class T> unwrap_ref_decay;
The member typedef type of unwrap_ref_decay<T> denotes the type unwrap_reference_t<decay_t<T>>.
In addition to being available via inclusion of the <type_traits> header, the templates unwrap_reference, unwrap_ref_decay, unwrap_reference_t, and unwrap_ref_decay_t are available when the header <functional> ([functional.syn]) is included.
Let:
  • CREF(A) be add_lvalue_reference_t<const remove_reference_t<A>>,
  • XREF(A) denote a unary alias template T such that T<U> denotes the same type as U with the addition of A's cv and reference qualifiers, for a non-reference cv-unqualified type U,
  • COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's top-level cv-qualifiers,
    [Example 1: 
    COPYCV(const int, volatile short) is an alias for const volatile short.
    — end example]
  • COND-RES(X, Y) be decltype(false ? declval<X(&)()>()() : declval<Y(&)()>()()).
Given types A and B, let X be remove_reference_t<A>, let Y be remove_reference_t<B>, and let COMMON-​REF(A, B) be:
  • If A and B are both lvalue reference types, COMMON-REF(A, B) is COND-RES(COPYCV(X, Y) &, COPYCV(​Y, X) &) if that type exists and is a reference type.
  • Otherwise, let C be remove_reference_t<COMMON-REF(X&, Y&)>&&.
    If A and B are both rvalue reference types, C is well-formed, and is_convertible_v<A, C> && is_convertible_v<B, C> is true, then COMMON-REF(A, B) is C.
  • Otherwise, let D be COMMON-REF(const X&, Y&).
    If A is an rvalue reference and B is an lvalue reference and D is well-formed and is_convertible_v<A, D> is true, then COMMON-REF(A, B) is D.
  • Otherwise, if A is an lvalue reference and B is an rvalue reference, then COMMON-REF(A, B) is COMMON-REF(B, A).
  • Otherwise, COMMON-REF(A, B) is ill-formed.
If any of the types computed above is ill-formed, then COMMON-REF(A, B) is ill-formed.
For the common_type trait applied to a template parameter pack T of types, the member type shall be either defined or not present as follows:
  • If sizeof...(T) is zero, there shall be no member type.
  • If sizeof...(T) is one, let T0 denote the sole type constituting the pack T.
    The member typedef-name type shall denote the same type, if any, as common_type_t<T0, T0>; otherwise there shall be no member type.
  • If sizeof...(T) is two, let the first and second types constituting T be denoted by T1 and T2, respectively, and let D1 and D2 denote the same types as decay_t<T1> and decay_t<T2>, respectively.
    • If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C denote the same type, if any, as common_type_t<D1, D2>.
    • [Note 3: 
      None of the following will apply if there is a specialization common_type<D1, D2>.
      — end note]
    • Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())> denotes a valid type, let C denote that type.
    • Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, let C denote the type decay_t<COND-RES(CREF(D1), CREF(D2))>.
    In either case, the member typedef-name type shall denote the same type, if any, as C.
    Otherwise, there shall be no member type.
  • If sizeof...(T) is greater than two, let T1, T2, and R, respectively, denote the first, second, and (pack of) remaining types constituting T.
    Let C denote the same type, if any, as common_type_t<T1, T2>.
    If there is such a type C, the member typedef-name type shall denote the same type, if any, as common_type_t<C, R...>.
    Otherwise, there shall be no member type.
Notwithstanding the provisions of [meta.type.synop], and pursuant to [namespace.std], a program may specialize common_type<T1, T2> for types T1 and T2 such that is_same_v<T1, decay_t<T1>> and is_same_v<T2, decay_t<T2>> are each true.
[Note 4: 
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 type, but if it does, the qualified-id common_type<T1, T2>​::​type shall denote a cv-unqualified non-reference type to which each of the types T1 and T2 is explicitly convertible.
Moreover, common_type_t<T1, T2> shall denote the same type, if any, as does common_type_t<T2, T1>.
No diagnostic is required for a violation of this Note's rules.
For the common_reference trait applied to a parameter pack T of types, the member type shall be either defined or not present as follows:
  • If sizeof...(T) is zero, there shall be no member type.
  • Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the pack T.
    The member typedef type shall denote the same type as T0.
  • Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in the pack T.
    Then
    • Let R be COMMON-REF(T1, T2).
      If T1 and T2 are reference types, R is well-formed, and is_convertible_v<add_pointer_t<T1>, add_pointer_t<R>> && is_convertible_v<add_pointer_t<T2>, add_pointer_t<R>> is true, then the member typedef type denotes R.
    • Otherwise, if basic_common_reference<remove_cvref_t<T1>, remove_cvref_t<T2>, ​XREF(​T1), XREF(T2)>​::​type is well-formed, then the member typedef type denotes that type.
    • Otherwise, if COND-RES(T1, T2) is well-formed, then the member typedef type denotes that type.
    • Otherwise, if common_type_t<T1, T2> is well-formed, then the member typedef type denotes that type.
    • Otherwise, there shall be no member type.
  • Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest, respectively, denote the first, second, and (pack of) remaining types comprising T.
    Let C be the type common_reference_t<T1, T2>.
    Then:
    • If there is such a type C, the member typedef type shall denote the same type, if any, as common_reference_t<C, Rest...>.
    • Otherwise, there shall be no member type.
Notwithstanding the provisions of [meta.type.synop], and pursuant to [namespace.std], a program may partially specialize basic_common_reference<T, U, TQual, UQual> for types T and U such that is_same_v<T, decay_t<T>> and is_same_v<U, decay_t<U>> are each true.
[Note 5: 
Such specializations can be used to influence the result of 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 type, but if it does, the qualified-id basic_common_reference<T, U, TQual, UQual>​::​type shall denote a type to which each of the types TQual<T> and UQual<U> is convertible.
Moreover, basic_common_reference<T, U, TQual, UQual>​::​type shall denote the same type, if any, as does basic_common_reference<U, T, UQual, TQual>​::​type.
No diagnostic is required for a violation of these rules.
[Example 2: 
Given these definitions: 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::*; the following assertions will hold: static_assert(is_same_v<invoke_result_t<S, int>, short>); static_assert(is_same_v<invoke_result_t<S&, unsigned char, int&>, double>); static_assert(is_same_v<invoke_result_t<PF1>, bool>); static_assert(is_same_v<invoke_result_t<PMF, unique_ptr<S>, int>, void>); static_assert(is_same_v<invoke_result_t<PMD, S>, char&&>); static_assert(is_same_v<invoke_result_t<PMD, const S*>, const char&>);
— end example]

21.3.9 Logical operator traits [meta.logical]

This subclause describes type traits for applying logical operators to other type traits.
template<class... B> struct conjunction : see below { };
The class template conjunction forms the logical conjunction of its template type arguments.
For a specialization conjunction<, , >, if there is a template type argument for which bool(​::​value) is false, then instantiating conjunction<, , >​::​value does not require the instantiation of ​::​value for .
[Note 1: 
This is analogous to the short-circuiting behavior of the built-in operator &&.
— end note]
Every template type argument for which ​::​value is instantiated shall be usable as a base class and shall have a member value which is convertible to bool, is not hidden, and is unambiguously available in the type.
The specialization conjunction<, , > has a public and unambiguous base that is either
  • the first type in the list true_type, , , for which bool(​::​value) is false, or
  • if there is no such , the last type in the list.
[Note 2: 
This means a specialization of conjunction does not necessarily inherit from either true_type or false_type.
— end note]
The member names of the base class, other than conjunction and operator=, shall not be hidden and shall be unambiguously available in conjunction.
template<class... B> struct disjunction : see below { };
The class template disjunction forms the logical disjunction of its template type arguments.
For a specialization disjunction<, , >, if there is a template type argument for which bool(​::​value) is true, then instantiating disjunction<, , >​::​value does not require the instantiation of ​::​value for .
[Note 3: 
This is analogous to the short-circuiting behavior of the built-in operator ||.
— end note]
Every template type argument for which ​::​value is instantiated shall be usable as a base class and shall have a member value which is convertible to bool, is not hidden, and is unambiguously available in the type.
The specialization disjunction<, , > has a public and unambiguous base that is either
  • the first type in the list false_type, , , for which bool(​::​value) is true, or
  • if there is no such , the last type in the list.
[Note 4: 
This means a specialization of disjunction does not necessarily inherit from either true_type or false_type.
— end note]
The member names of the base class, other than disjunction and operator=, shall not be hidden and shall be unambiguously available in disjunction.
template<class B> struct negation : see below { };
The class template negation forms the logical negation of its template type argument.
The type negation<B> is a Cpp17UnaryTypeTrait with a base characteristic of bool_constant<!bool(B​::​​value)>.

21.3.10 Member relationships [meta.member]

template<class S, class M> constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept;
Mandates: S is a complete type.
Returns: true if and only if S is a standard-layout type, M is an object type, m is not null, and each object s of type S is pointer-interconvertible ([basic.compound]) with its subobject s.*m.
template<class S1, class S2, class M1, class M2> constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept;
Mandates: S1 and S2 are complete types.
Returns: true if and only if S1 and S2 are standard-layout struct ([class.prop]) types, M1 and M2 are object types, m1 and m2 are not null, and m1 and m2 point to corresponding members of the common initial sequence ([class.mem]) of S1 and S2.
[Note 1: 
The type of a pointer-to-member expression &C​::​b is not always a pointer to member of C, leading to potentially surprising results when using these functions in conjunction with inheritance.
[Example 1: 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, &C​::​b has type // “pointer to member of B of type int''. static_assert( is_pointer_interconvertible_with_class<C>( &C::b ) ); // Forces the use of class C, and fails. static_assert( is_corresponding_member( &C::a, &C::b ) ); // Succeeds because, despite its appearance, &C​::​a and &C​::​b have types // “pointer to member of A of type int'' and // “pointer to member of B of type int'', respectively. static_assert( is_corresponding_member<C, C>( &C::a, &C::b ) ); // Forces the use of class C, and fails. — end example]
— end note]

21.3.11 Constant evaluation context [meta.const.eval]

constexpr bool is_constant_evaluated() noexcept;
Effects: Equivalent to: if consteval { return true; } else { return false; }
[Example 1: 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<n; ++k) p[k] = 0; } else { memset(p, 0, n); // not a core constant expression } } — end example]
consteval bool is_within_lifetime(const auto* p) noexcept;
Returns: true if p is a pointer to an object that is within its lifetime ([basic.life]); otherwise, false.
Remarks: During the evaluation of an expression E as a core constant expression, a call to this function is ill-formed unless p points to an object that is usable in constant expressions or whose complete object's lifetime began within E.
[Example 2: struct OptBool { union { bool b; char c; }; // note: this assumes common implementation properties for bool and char: // * sizeof(bool) == sizeof(char), and // * the value representations for true and false are distinct // from the value representation for 2 constexpr OptBool() : c(2) { } constexpr OptBool(bool b) : b(b) { } constexpr auto has_value() const -> bool { if consteval { return std::is_within_lifetime(&b); // during constant evaluation, cannot read from c } else { return c != 2; // during runtime, must read from c } } constexpr auto operator*() const -> const bool& { return b; } }; constexpr OptBool disengaged; constexpr OptBool engaged(true); static_assert(!disengaged.has_value()); static_assert(engaged.has_value()); static_assert(*engaged); — end example]

21.4 Compile-time rational arithmetic [ratio]

21.4.1 General [ratio.general]

Subclause [ratio] describes the ratio library.
It provides a class template ratio which exactly represents any finite rational number with a numerator and denominator representable by compile-time constants of type intmax_t.
Throughout subclause [ratio], the names of template parameters are used to express type requirements.
If a template parameter is named R1 or R2, and the template argument is not a specialization of the ratio template, the program is ill-formed.

21.4.2 Header <ratio> synopsis [ratio.syn]

// all freestanding namespace std { // [ratio.ratio], class template ratio template<intmax_t N, intmax_t D = 1> class ratio; // [ratio.arithmetic], ratio arithmetic template<class R1, class R2> using ratio_add = see below; template<class R1, class R2> using ratio_subtract = see below; template<class R1, class R2> using ratio_multiply = see below; template<class R1, class R2> using ratio_divide = see below; // [ratio.comparison], ratio comparison template<class R1, class R2> struct ratio_equal; template<class R1, class R2> struct ratio_not_equal; template<class R1, class R2> struct ratio_less; template<class R1, class R2> struct ratio_less_equal; template<class R1, class R2> struct ratio_greater; template<class R1, class R2> struct ratio_greater_equal; template<class R1, class R2> constexpr bool ratio_equal_v = ratio_equal<R1, R2>::value; template<class R1, class R2> constexpr bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value; template<class R1, class R2> constexpr bool ratio_less_v = ratio_less<R1, R2>::value; template<class R1, class R2> constexpr bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value; template<class R1, class R2> constexpr bool ratio_greater_v = ratio_greater<R1, R2>::value; template<class R1, class R2> constexpr bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value; // [ratio.si], convenience SI typedefs using quecto = ratio<1, 1'000'000'000'000'000'000'000'000'000'000>; // see below using ronto = ratio<1, 1'000'000'000'000'000'000'000'000'000>; // see below using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below using atto = ratio<1, 1'000'000'000'000'000'000>; using femto = ratio<1, 1'000'000'000'000'000>; using pico = ratio<1, 1'000'000'000'000>; using nano = ratio<1, 1'000'000'000>; using micro = ratio<1, 1'000'000>; using milli = ratio<1, 1'000>; using centi = ratio<1, 100>; using deci = ratio<1, 10>; using deca = ratio< 10, 1>; using hecto = ratio< 100, 1>; using kilo = ratio< 1'000, 1>; using mega = ratio< 1'000'000, 1>; using giga = ratio< 1'000'000'000, 1>; using tera = ratio< 1'000'000'000'000, 1>; using peta = ratio< 1'000'000'000'000'000, 1>; using exa = ratio< 1'000'000'000'000'000'000, 1>; using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below using yotta = ratio< 1'000'000'000'000'000'000'000'000, 1>; // see below using ronna = ratio< 1'000'000'000'000'000'000'000'000'000, 1>; // see below using quetta = ratio<1'000'000'000'000'000'000'000'000'000'000, 1>; // see below }

21.4.3 Class template ratio [ratio.ratio]

namespace std { template<intmax_t N, intmax_t D = 1> class ratio { public: static constexpr intmax_t num; static constexpr intmax_t den; using type = ratio<num, den>; }; }
If the template argument D is zero or the absolute values of either of the template arguments N and D is not representable by type intmax_t, the program is ill-formed.
[Note 1: 
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]
The static data members num and den shall have the following values, where gcd represents the greatest common divisor of the absolute values of N and D:
  • num shall have the value sgn(N) * sgn(D) * abs(N) / gcd.
  • den shall have the value abs(D) / gcd.

21.4.4 Arithmetic on ratios [ratio.arithmetic]

Each of the alias templates ratio_add, ratio_subtract, ratio_multiply, and ratio_divide denotes the result of an arithmetic computation on two ratios R1 and R2.
With X and Y computed (in the absence of arithmetic overflow) as specified by Table 60, each alias denotes a ratio<U, V> such that U is the same as ratio<X, Y>​::​num and V is the same as ratio<X, Y>​::​den.
If it is not possible to represent U or V with intmax_t, the program is ill-formed.
Otherwise, an implementation should yield correct values of U and V.
If it is not possible to represent X or Y with intmax_t, the program is ill-formed unless the implementation yields correct values of U and V.
Table 60 — Expressions used to perform ratio arithmetic [tab:ratio.arithmetic]
Type
Value of X
Value of Y
ratio_add<R1, R2>
R1​::​num * R2​::​den +
R1​::​den * R2​::​den
R2​::​num * R1​::​den
ratio_subtract<R1, R2>
R1​::​num * R2​::​den -
R1​::​den * R2​::​den
R2​::​num * R1​::​den
ratio_multiply<R1, R2>
R1​::​num * R2​::​num
R1​::​den * R2​::​den
ratio_divide<R1, R2>
R1​::​num * R2​::​den
R1​::​den * R2​::​num
[Example 1: static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2"); static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2"); static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2"); static_assert(ratio_multiply<ratio<1, 3>, 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>, ratio<1, INT_MAX>>::num == 2, "1/MAX+1/MAX == 2/MAX"); static_assert(ratio_add<ratio<1, INT_MAX>, ratio<1, INT_MAX>>::den == INT_MAX, "1/MAX+1/MAX == 2/MAX"); static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::num == 1, "1/MAX * MAX/2 == 1/2"); static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::den == 2, "1/MAX * MAX/2 == 1/2"); — end example]

21.4.5 Comparison of ratios [ratio.comparison]

template<class R1, class R2> struct ratio_equal : bool_constant<R1::num == R2::num && R1::den == R2::den> { };
template<class R1, class R2> struct ratio_not_equal : bool_constant<!ratio_equal_v<R1, R2>> { };
template<class R1, class R2> struct ratio_less : bool_constant<see below> { };
If R1​::​num × R2​::​den is less than R2​::​num × R1​::​den, ratio_less<R1, R2> shall be derived from bool_constant<true>; otherwise it shall be derived from bool_constant<false>.
Implementations may use other algorithms to compute this relationship to avoid overflow.
If overflow occurs, the program is ill-formed.
template<class R1, class R2> struct ratio_less_equal : bool_constant<!ratio_less_v<R2, R1>> { };
template<class R1, class R2> struct ratio_greater : bool_constant<ratio_less_v<R2, R1>> { };
template<class R1, class R2> struct ratio_greater_equal : bool_constant<!ratio_less_v<R1, R2>> { };

21.4.6 SI types for ratio [ratio.si]

For each of the typedef-names quecto, ronto, yocto, zepto, zetta, yotta, ronna, and quetta, if both of the constants used in its specification are representable by intmax_t, the typedef is defined; if either of the constants is not representable by intmax_t, the typedef is not defined.

22 General utilities library [utilities]

22.1 General [utilities.general]

This Clause describes utilities that are generally useful in C++ programs; some of these utilities are used by other elements of the C++ standard library.
These utilities are summarized in Table 61.
Table 61 — General utilities library summary [tab:utilities.summary]
Subclause
Header
Utility components
<utility>
Pairs
Tuples
<tuple>
Optional objects
<optional>
Variants
<variant>
Storage for any type
<any>
Expected objects
<expected>
Fixed-size sequences of bits
<bitset>
Function objects
<functional>
Bit manipulation
<bit>

22.2 Utility components [utility]

22.2.1 Header <utility> synopsis [utility.syn]

The header <utility> contains some basic function and class templates that are used throughout the rest of the library.
// all freestanding #include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [utility.swap], swap template<class T> constexpr void swap(T& a, T& b) noexcept(see below); template<class T, size_t N> constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>); // [utility.exchange], exchange template<class T, class U = T> constexpr T exchange(T& obj, U&& new_val) noexcept(see below); // [forward], forward/move template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept; template<class T, class U> constexpr auto forward_like(U&& x) noexcept -> see below; template<class T> constexpr remove_reference_t<T>&& move(T&&) noexcept; template<class T> constexpr conditional_t< !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept; // [utility.as.const], as_const template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept; template<class T> void as_const(const T&&) = delete; // [declval], declval template<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand // [utility.intcmp], integer comparison functions template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept; template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept; template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept; template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept; template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept; template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept; template<class R, class T> constexpr bool in_range(T t) noexcept; // [utility.underlying], to_underlying template<class T> constexpr underlying_type_t<T> to_underlying(T value) noexcept; // [utility.unreachable], unreachable [[noreturn]] void unreachable(); // [intseq], compile-time integer sequences template<class T, T...> struct integer_sequence; template<size_t... I> using index_sequence = integer_sequence<size_t, I...>; template<class T, T N> using make_integer_sequence = integer_sequence<T, see below>; template<size_t N> using make_index_sequence = make_integer_sequence<size_t, N>; template<class... T> using index_sequence_for = make_index_sequence<sizeof...(T)>; // [pairs], class template pair template<class T1, class T2> struct pair; template<class T1, class T2, class U1, class U2, template<class> class TQual, template<class> class UQual> requires requires { typename pair<common_reference_t<TQual<T1>, UQual<U1>>, common_reference_t<TQual<T2>, UQual<U2>>>; } struct basic_common_reference<pair<T1, T2>, pair<U1, U2>, TQual, UQual> { using type = pair<common_reference_t<TQual<T1>, UQual<U1>>, common_reference_t<TQual<T2>, UQual<U2>>>; }; template<class T1, class T2, class U1, class U2> requires requires { typename pair<common_type_t<T1, U1>, common_type_t<T2, U2>>; } struct common_type<pair<T1, T2>, pair<U1, U2>> { using type = pair<common_type_t<T1, U1>, common_type_t<T2, U2>>; }; // [pairs.spec], pair specialized algorithms template<class T1, class T2, class U1, class U2> constexpr bool operator==(const pair<T1, T2>&, const pair<U1, U2>&); template<class T1, class T2, class U1, class U2> constexpr common_comparison_category_t<synth-three-way-result<T1, U1>, synth-three-way-result<T2, U2>> operator<=>(const pair<T1, T2>&, const pair<U1, U2>&); template<class T1, class T2> constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template<class T1, class T2> constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template<class T1, class T2> constexpr see below make_pair(T1&&, T2&&); // [pair.astuple], tuple-like access to pair template<class T> struct tuple_size; template<size_t I, class T> struct tuple_element; template<class T1, class T2> struct tuple_size<pair<T1, T2>>; template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>>; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&&) noexcept; template<class T1, class T2> constexpr T1& get(pair<T1, T2>& p) noexcept; template<class T1, class T2> constexpr const T1& get(const pair<T1, T2>& p) noexcept; template<class T1, class T2> constexpr T1&& get(pair<T1, T2>&& p) noexcept; template<class T1, class T2> constexpr const T1&& get(const pair<T1, T2>&& p) noexcept; template<class T2, class T1> constexpr T2& get(pair<T1, T2>& p) noexcept; template<class T2, class T1> constexpr const T2& get(const pair<T1, T2>& p) noexcept; template<class T2, class T1> constexpr T2&& get(pair<T1, T2>&& p) noexcept; template<class T2, class T1> constexpr const T2&& get(const pair<T1, T2>&& p) noexcept; // [pair.piecewise], pair piecewise construction struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{}; template<class... Types> class tuple; // defined in <tuple> // in-place construction struct in_place_t { explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; template<class T> struct in_place_type_t { explicit in_place_type_t() = default; }; template<class T> constexpr in_place_type_t<T> in_place_type{}; template<size_t I> struct in_place_index_t { explicit in_place_index_t() = default; }; template<size_t I> constexpr in_place_index_t<I> in_place_index{}; // nontype argument tag template<auto V> struct nontype_t { explicit nontype_t() = default; }; template<auto V> constexpr nontype_t<V> nontype{}; }

22.2.2 swap [utility.swap]

template<class T> constexpr void swap(T& a, T& b) noexcept(see below);
Constraints: is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.
Preconditions: Type T meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Exchanges values stored in two locations.
Remarks: The exception specification is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
template<class T, size_t N> constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
Constraints: is_swappable_v<T> is true.
Preconditions: a[i] is swappable with ([swappable.requirements]) b[i] for all i in the range [0, N).
Effects: As if by swap_ranges(a, a + N, b).

22.2.3 exchange [utility.exchange]

template<class T, class U = T> constexpr T exchange(T& obj, U&& new_val) noexcept(see below);
Effects: Equivalent to: T old_val = std::move(obj); obj = std::forward<U>(new_val); return old_val;
Remarks: The exception specification is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_assignable_v<T&, U>

22.2.4 Forward/move helpers [forward]

The library provides templated helper functions to simplify applying move semantics to an lvalue and to simplify the implementation of forwarding functions.
All functions specified in this subclause are signal-safe.
template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Mandates: For the second overload, is_lvalue_reference_v<T> is false.
Returns: static_cast<T&&>(t).
[Example 1: template<class T, class A1, class A2> shared_ptr<T> factory(A1&& a1, A2&& a2) { return shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2))); } struct A { A(int&, const double&); }; void g() { shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int& int i = 2; shared_ptr<A> sp2 = factory<A>(i, 1.414); // OK }
In the first call to factory, A1 is deduced as int, so 2 is forwarded to A's constructor as an rvalue.
In the second call to factory, A1 is deduced as int&, so i is forwarded to A's constructor as an lvalue.
In both cases, A2 is deduced as double, so 1.414 is forwarded to A's constructor as an rvalue.
— end example]
template<class T, class U> constexpr auto forward_like(U&& x) noexcept -> see below;
Mandates: T is a referenceable type ([defns.referenceable]).
  • Let COPY_CONST(A, B) be const B if A is a const type, otherwise B.
  • Let OVERRIDE_REF(A, B) be remove_reference_t<B>&& if A is an rvalue reference type, otherwise B&.
  • Let V be OVERRIDE_REF(T&&, COPY_CONST(remove_reference_t<T>, remove_reference_t<U>))
Returns: static_cast<V>(x).
Remarks: The return type is V.
[Example 2: struct accessor { vector<string>* container; decltype(auto) operator[](this auto&& self, size_t i) { return std::forward_like<decltype(self)>((*container)[i]); } }; void g() { vector v{"a"s, "b"s}; accessor a{&v}; string& x = a[0]; // OK, binds to lvalue reference string&& y = std::move(a)[0]; // OK, is rvalue reference string const&& z = std::move(as_const(a))[1]; // OK, is const&& string& w = as_const(a)[1]; // error: will not bind to non-const } — end example]
template<class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
Returns: static_cast<remove_reference_t<T>&&>(t).
[Example 3: template<class T, class A1> shared_ptr<T> factory(A1&& a1) { return shared_ptr<T>(new T(std::forward<A1>(a1))); } struct A { A(); A(const A&); // copies from lvalues A(A&&); // moves from rvalues }; void g() { A a; shared_ptr<A> sp1 = factory<A>(a); // “a'' binds to A(const A&) shared_ptr<A> sp2 = factory<A>(std::move(a)); // “a'' binds to A(A&&) }
In the first call to factory, A1 is deduced as A&, so a is forwarded as a non-const lvalue.
This binds to the constructor A(const A&), which copies the value from a.
In the second call to factory, because of the call std​::​move(a), A1 is deduced as A, so a is forwarded as an rvalue.
This binds to the constructor A(A&&), which moves the value from a.
— end example]
template<class T> constexpr conditional_t< !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept;
Returns: std​::​move(x).

22.2.5 Function template as_const [utility.as.const]

template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept;
Returns: t.

22.2.6 Function template declval [declval]

The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
template<class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
Mandates: This function is not odr-used ([basic.def.odr]).
Remarks: The template parameter T of declval may be an incomplete type.
[Example 1: 
template<class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&); declares a function template convert which only participates in overload resolution if the type From can be explicitly converted to type To.
For another example see class template common_type ([meta.trans.other]).
— end example]

22.2.7 Integer comparison functions [utility.intcmp]

template<class T, class U> constexpr bool cmp_equal(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to: using UT = make_unsigned_t<T>; using UU = make_unsigned_t<U>; if constexpr (is_signed_v<T> == is_signed_v<U>) return t == u; else if constexpr (is_signed_v<T>) return t < 0 ? false : UT(t) == u; else return u < 0 ? false : t == UU(u);
template<class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_equal(t, u);
template<class T, class U> constexpr bool cmp_less(T t, U u) noexcept;
Mandates: Both T and U are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to: using UT = make_unsigned_t<T>; using UU = make_unsigned_t<U>; if constexpr (is_signed_v<T> == is_signed_v<U>) return t < u; else if constexpr (is_signed_v<T>) return t < 0 ? true : UT(t) < u; else return u < 0 ? false : t < UU(u);
template<class T, class U> constexpr bool cmp_greater(T t, U u) noexcept;
Effects: Equivalent to: return cmp_less(u, t);
template<class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_greater(t, u);
template<class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_less(t, u);
template<class R, class T> constexpr bool in_range(T t) noexcept;
Mandates: Both T and R are standard integer types or extended integer types ([basic.fundamental]).
Effects: Equivalent to: return cmp_greater_equal(t, numeric_limits<R>::min()) && cmp_less_equal(t, numeric_limits<R>::max());
[Note 1: 
These function templates cannot be used to compare byte, char, char8_t, char16_t, char32_t, wchar_t, and bool.
— end note]

22.2.8 Function template to_underlying [utility.underlying]

template<class T> constexpr underlying_type_t<T> to_underlying(T value) noexcept;
Returns: static_cast<underlying_type_t<T>>(value).

22.2.9 Function unreachable [utility.unreachable]

[[noreturn]] void unreachable();
Preconditions: false is true.
[Note 1: 
This precondition cannot be satisfied, thus the behavior of calling unreachable is undefined.
— end note]
[Example 1: int f(int x) { switch (x) { case 0: case 1: return x; default: std::unreachable(); } } int a = f(1); // OK, a has value 1 int b = f(3); // undefined behavior — end example]

22.3 Pairs [pairs]

22.3.1 General [pairs.general]

The library provides a template for heterogeneous pairs of values.
The library also provides a matching function template to simplify their construction and several templates that provide access to pair objects as if they were tuple objects (see [tuple.helper] and [tuple.elem]).

22.3.2 Class template pair [pairs.pair]

namespace std { template<class T1, class T2> struct pair { using first_type = T1; using second_type = T2; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; constexpr explicit(see below) pair(); constexpr explicit(see below) pair(const T1& x, const T2& y); template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y); template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p); template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p); template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p); template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p); template<pair-like P> constexpr explicit(see below) pair(P&& p); template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args); constexpr pair& operator=(const pair& p); constexpr const pair& operator=(const pair& p) const; template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p); template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const; constexpr pair& operator=(pair&& p) noexcept(see below); constexpr const pair& operator=(pair&& p) const; template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p); template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const; template<pair-like P> constexpr pair& operator=(P&& p); template<pair-like P> constexpr const pair& operator=(P&& p) const; constexpr void swap(pair& p) noexcept(see below); constexpr void swap(const pair& p) const noexcept(see below); }; template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>; }
Constructors and member functions of pair do not throw exceptions unless one of the element-wise operations specified to be called for that operation throws an exception.
The defaulted move and copy constructor, respectively, of pair is a constexpr function if and only if all required element-wise initializations for move and copy, respectively, would be constexpr-suitable ([dcl.constexpr]).
If (is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>) is true, then the destructor of pair is trivial.
pair<T, U> is a structural type ([temp.param]) if T and U are both structural types.
Two values p1 and p2 of type pair<T, U> are template-argument-equivalent ([temp.type]) if and only if p1.first and p2.first are template-argument-equivalent and p1.second and p2.second are template-argument-equivalent.
constexpr explicit(see below) pair();
Constraints:
  • is_default_constructible_v<T1> is true and
  • is_default_constructible_v<T2> is true.
Effects: Value-initializes first and second.
Remarks: The expression inside explicit evaluates to true if and only if either T1 or T2 is not implicitly default-constructible.
[Note 1: 
This behavior can be implemented with a trait that checks whether a const T1& or a const T2& can be initialized with {}.
— end note]
constexpr explicit(see below) pair(const T1& x, const T2& y);
Constraints:
  • is_copy_constructible_v<T1> is true and
  • is_copy_constructible_v<T2> is true.
Effects: Initializes first with x and second with y.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const T1&, T1> || !is_convertible_v<const T2&, T2>
template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y);
Constraints:
  • is_constructible_v<T1, U1> is true and
  • is_constructible_v<T2, U2> is true.
Effects: Initializes first with std​::​forward<U1>(x) and second with std​::​forward<U2>(y).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U1, T1> || !is_convertible_v<U2, T2>
This constructor is defined as deleted if reference_constructs_from_temporary_v<first_type, U1&&> is true or reference_constructs_from_temporary_v<second_type, U2&&> is true.
template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p); template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p); template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p); template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p); template<pair-like P> constexpr explicit(see below) pair(P&& p);
Let FWD(u) be static_cast<decltype(u)>(u).
Constraints:
  • For the last overload, remove_cvref_t<P> is not a specialization of ranges​::​subrange,
  • is_constructible_v<T1, decltype(get<0>(FWD(p)))> is true, and
  • is_constructible_v<T2, decltype(get<1>(FWD(p)))> is true.
Effects: Initializes first with get<0>(FWD(p)) and second with get<1>(FWD(p)).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<decltype(get<0>(FWD(p))), T1> || !is_convertible_v<decltype(get<1>(FWD(p))), T2>
The constructor is defined as deleted if reference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> || reference_constructs_from_temporary_v<second_type, decltype(get<1>(FWD(p)))> is true.
template<class... Args1, class... Args2> constexpr pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Mandates:
  • is_constructible_v<T1, Args1...> is true and
  • is_constructible_v<T2, Args2...> is true.
Effects: Initializes first with arguments of types Args1... obtained by forwarding the elements of first_args and initializes second with arguments of types Args2... obtained by forwarding the elements of second_args.
(Here, forwarding an element x of type U within a tuple object means calling std​::​forward<U>(x).)
This form of construction, whereby constructor arguments for first and second are each provided in a separate tuple object, is called piecewise construction.
[Note 2: 
If a data member of pair is of reference type and its initialization binds it to a temporary object, the program is ill-formed ([class.base.init]).
— end note]
constexpr pair& operator=(const pair& p);
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
Remarks: This operator is defined as deleted unless is_copy_assignable_v<T1> is true and is_copy_assignable_v<T2> is true.
constexpr const pair& operator=(const pair& p) const;
Constraints:
  • is_copy_assignable_v<const T1> is true and
  • is_copy_assignable_v<const T2> is true.
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
Constraints:
  • is_assignable_v<T1&, const U1&> is true and
  • is_assignable_v<T2&, const U2&> is true.
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const;
Constraints:
  • is_assignable_v<const T1&, const U1&> is true, and
  • is_assignable_v<const T2&, const U2&> is true.
Effects: Assigns p.first to first and p.second to second.
Returns: *this.
constexpr pair& operator=(pair&& p) noexcept(see below);
Constraints:
  • is_move_assignable_v<T1> is true and
  • is_move_assignable_v<T2> is true.
Effects: Assigns std​::​forward<T1>(p.first) to first and std​::​forward<T2>(p.second) to second.
Returns: *this.
Remarks: The exception specification is equivalent to: is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
constexpr const pair& operator=(pair&& p) const;
Constraints:
  • is_assignable_v<const T1&, T1> is true and
  • is_assignable_v<const T2&, T2> is true.
Effects: Assigns std​::​forward<T1>(p.first) to first and std​::​forward<T2>(p.second) to second.
Returns: *this.
template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
Constraints:
  • is_assignable_v<T1&, U1> is true and
  • is_assignable_v<T2&, U2> is true.
Effects: Assigns std​::​forward<U1>(p.first) first and std​::​forward<U2>(p.second) to second.
Returns: *this.
template<pair-like P> constexpr pair& operator=(P&& p);
Constraints:
Effects: Assigns get<0>(std​::​forward<P>(p)) to first and get<1>(std​::​forward<P>(p)) to second.
Returns: *this.
template<pair-like P> constexpr const pair& operator=(P&& p) const;
Constraints:
  • different-from<P, pair> ([range.utility.helpers]) is true,
  • remove_cvref_t<P> is not a specialization of ranges​::​subrange,
  • is_assignable_v<const T1&, decltype(get<0>(std​::​forward<P>(p)))> is true, and
  • is_assignable_v<const T2&, decltype(get<1>(std​::​forward<P>(p)))> is true.
Effects: Assigns get<0>(std​::​forward<P>(p)) to first and get<1>(std​::​forward<P>(p)) to second.
Returns: *this.
template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const;
Constraints:
  • is_assignable_v<const T1&, U1> is true, and
  • is_assignable_v<const T2&, U2> is true.
Effects: Assigns std​::​forward<U1>(p.first) to first and std​::​forward<U2>(u.second) to second.
Returns: *this.
constexpr void swap(pair& p) noexcept(see below); constexpr void swap(const pair& p) const noexcept(see below);
Mandates:
  • For the first overload, is_swappable_v<T1> is true and is_swappable_v<T2> is true.
  • For the second overload, is_swappable_v<const T1> is true and is_swappable_v<const T2> is true.
Preconditions: first is swappable with ([swappable.requirements]) p.first and second is swappable with p.second.
Effects: Swaps first with p.first and second with p.second.
Remarks: The exception specification is equivalent to:
  • is_nothrow_swappable_v<T1> && is_nothrow_swappable_v<T2> for the first overload, and
  • is_nothrow_swappable_v<const T1> && is_nothrow_swappable_v<const T2> for the second overload.

22.3.3 Specialized algorithms [pairs.spec]

template<class T1, class T2, class U1, class U2> constexpr bool operator==(const pair<T1, T2>& x, const pair<U1, U2>& y);
Constraints: x.first == y.first and x.second == y.second are valid expressions and each of decltype(x.first == y.first) and decltype(x.second == y.second) models boolean-
testable
.
Returns: x.first == y.first && x.second == y.second.
template<class T1, class T2, class U1, class U2> constexpr common_comparison_category_t<synth-three-way-result<T1, U1>, synth-three-way-result<T2, U2>> operator<=>(const pair<T1, T2>& x, const pair<U1, U2>& y);
Effects: Equivalent to: if (auto c = synth-three-way(x.first, y.first); c != 0) return c; return synth-three-way(x.second, y.second);
template<class T1, class T2> constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template<class T1, class T2> constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
Constraints:
  • For the first overload, is_swappable_v<T1> is true and is_swappable_v<T2> is true.
  • For the second overload, is_swappable_v<const T1> is true and is_swappable_v<const T2> is true.
Effects: Equivalent to x.swap(y).
template<class T1, class T2> constexpr pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>> make_pair(T1&& x, T2&& y);
Returns: pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>>(std::forward<T1>(x), std::forward<T2>(y))
[Example 1: 
In place of: return pair<int, double>(5, 3.1415926); // explicit types a C++ program may contain: return make_pair(5, 3.1415926); // types are deduced
— end example]

22.3.4 Tuple-like access to pair [pair.astuple]

template<class T1, class T2> struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>> { using type = see below ; };
Mandates: .
Type: The type T1 if I is 0, otherwise the type T2.
template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;
Mandates: .
Returns:
  • If I is 0, returns a reference to p.first.
  • If I is 1, returns a reference to p.second.
template<class T1, class T2> constexpr T1& get(pair<T1, T2>& p) noexcept; template<class T1, class T2> constexpr const T1& get(const pair<T1, T2>& p) noexcept; template<class T1, class T2> constexpr T1&& get(pair<T1, T2>&& p) noexcept; template<class T1, class T2> constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
Mandates: T1 and T2 are distinct types.
Returns: A reference to p.first.
template<class T2, class T1> constexpr T2& get(pair<T1, T2>& p) noexcept; template<class T2, class T1> constexpr const T2& get(const pair<T1, T2>& p) noexcept; template<class T2, class T1> constexpr T2&& get(pair<T1, T2>&& p) noexcept; template<class T2, class T1> constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;
Mandates: T1 and T2 are distinct types.
Returns: A reference to p.second.

22.3.5 Piecewise construction [pair.piecewise]

struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{};
The struct piecewise_construct_t is an empty class type used as a unique type to disambiguate constructor and function overloading.
Specifically, pair has a constructor with piecewise_construct_t as the first argument, immediately followed by two tuple arguments used for piecewise construction of the elements of the pair object.

22.4 Tuples [tuple]

22.4.1 General [tuple.general]

Subclause [tuple] describes the tuple library that provides a tuple type as the class template tuple that can be instantiated with any number of arguments.
Each template argument specifies the type of an element in the tuple.
Consequently, tuples are heterogeneous, fixed-size collections of values.
An instantiation of tuple with two arguments is similar to an instantiation of pair with the same two arguments.
In addition to being available via inclusion of the <tuple> header, ignore ([tuple.syn]) is available when <utility> ([utility]) is included.

22.4.2 Header <tuple> synopsis [tuple.syn]

// all freestanding #include <compare> // see [compare.syn] namespace std { // [tuple.tuple], class template tuple template<class... Types> class tuple; // [tuple.like], concept tuple-like template<class T> concept tuple-like = see below; // exposition only template<class T> concept pair-like = // exposition only tuple-like<T> && tuple_size_v<remove_cvref_t<T>> == 2; // [tuple.common.ref], common_reference related specializations template<tuple-like TTuple, tuple-like UTuple, template<class> class TQual, template<class> class UQual> struct basic_common_reference<TTuple, UTuple, TQual, UQual>; template<tuple-like TTuple, tuple-like UTuple> struct common_type<TTuple, UTuple>; // ignore struct ignore-type { // exposition only constexpr const ignore-type operator=(const auto &) const noexcept { return *this; } }; inline constexpr ignore-type ignore; // [tuple.creation], tuple creation functions template<class... TTypes> constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...); template<class... TTypes> constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept; template<class... TTypes> constexpr tuple<TTypes&...> tie(TTypes&...) noexcept; template<tuple-like... Tuples> constexpr tuple<CTypes...> tuple_cat(Tuples&&...); // [tuple.apply], calling a function with a tuple of arguments template<class F, tuple-like Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(see below); template<class T, tuple-like Tuple> constexpr T make_from_tuple(Tuple&& t); // [tuple.helper], tuple helper classes template<class T> struct tuple_size; // not defined template<class T> struct tuple_size<const T>; template<class... Types> struct tuple_size<tuple<Types...>>; template<size_t I, class T> struct tuple_element; // not defined template<size_t I, class T> struct tuple_element<I, const T>; template<size_t I, class... Types> struct tuple_element<I, tuple<Types...>>; template<size_t I, class T> using tuple_element_t = typename tuple_element<I, T>::type; // [tuple.elem], element access template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept; template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept; template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept; template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&&) noexcept; template<class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template<class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept; // [tuple.rel], relational operators template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, tuple-like UTuple> constexpr bool operator==(const tuple<TTypes...>&, const UTuple&); template<class... TTypes, class... UTypes> constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...> operator<=>(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, tuple-like UTuple> constexpr see below operator<=>(const tuple<TTypes...>&, const UTuple&); // [tuple.traits], allocator-related traits template<class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc>; // [tuple.special], specialized algorithms template<class... Types> constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below); template<class... Types> constexpr void swap(const tuple<Types...>& x, const tuple<Types...>& y) noexcept(see below); // [tuple.helper], tuple helper classes template<class T> constexpr size_t tuple_size_v = tuple_size<T>::value; }

22.4.3 Concept tuple-like [tuple.like]

template<class T> concept tuple-like = see below; // exposition only
A type T models and satisfies the exposition-only concept tuple-like if remove_cvref_t<T> is a specialization of array, complex, pair, tuple, or ranges​::​subrange.

22.4.4 Class template tuple [tuple.tuple]

22.4.4.1 General [tuple.tuple.general]

namespace std { template<class... Types> class tuple { public: // [tuple.cnstr], tuple construction constexpr explicit(see below) tuple(); constexpr explicit(see below) tuple(const Types&...); // only if sizeof...(Types) >= 1 template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&...); // only if sizeof...(Types) >= 1 tuple(const tuple&) = default; tuple(tuple&&) = default; template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&); template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&); template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&&); template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&&); template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&&); // only if sizeof...(Types) == 2 template<tuple-like UTuple> constexpr explicit(see below) tuple(UTuple&&); // allocator-extended constructors template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a); template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&); template<class Alloc, tuple-like UTuple> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTuple&&); // [tuple.assign], tuple assignment constexpr tuple& operator=(const tuple&); constexpr const tuple& operator=(const tuple&) const; constexpr tuple& operator=(tuple&&) noexcept(see below); constexpr const tuple& operator=(tuple&&) const; template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>&); template<class... UTypes> constexpr const tuple& operator=(const tuple<UTypes...>&) const; template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&&); template<class... UTypes> constexpr const tuple& operator=(tuple<UTypes...>&&) const; template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr const tuple& operator=(const pair<U1, U2>&) const; // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2 template<class U1, class U2> constexpr const tuple& operator=(pair<U1, U2>&&) const; // only if sizeof...(Types) == 2 template<tuple-like UTuple> constexpr tuple& operator=(UTuple&&); template<tuple-like UTuple> constexpr const tuple& operator=(UTuple&&) const; // [tuple.swap], tuple swap constexpr void swap(tuple&) noexcept(see below); constexpr void swap(const tuple&) const noexcept(see below); }; template<class... UTypes> tuple(UTypes...) -> tuple<UTypes...>; template<class T1, class T2> tuple(pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>; template<class Alloc, class T1, class T2> tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>; }
If a program declares an explicit or partial specialization of tuple, the program is ill-formed, no diagnostic required.

22.4.4.2 Construction [tuple.cnstr]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, be the type in Types, and be the type in a template parameter pack named UTypes, where indexing is zero-based.
For each tuple constructor, an exception is thrown only if the construction of one of the types in Types throws an exception.
The defaulted move and copy constructor, respectively, of tuple is a constexpr function if and only if all required element-wise initializations for move and copy, respectively, would be constexpr-suitable ([dcl.constexpr]).
The defaulted move and copy constructor of tuple<> are constexpr functions.
If is_trivially_destructible_v<> is true for all , then the destructor of tuple is trivial.
The default constructor of tuple<> is trivial.
constexpr explicit(see below) tuple();
Constraints: is_default_constructible_v<> is true for all i.
Effects: Value-initializes each element.
Remarks: The expression inside explicit evaluates to true if and only if is not copy-list-initializable from an empty list for at least one i.
[Note 1: 
This behavior can be implemented with a trait that checks whether a const & can be initialized with {}.
— end note]
constexpr explicit(see below) tuple(const Types&...);
Constraints: sizeof...(Types)  ≥ 1 and is_copy_constructible_v<> is true for all i.
Effects: Initializes each element with the value of the corresponding parameter.
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<const Types&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
Let disambiguating-constraint be:
  • negation<is_same<remove_cvref_t<>, tuple>> if sizeof...(Types) is 1;
  • otherwise, bool_constant<!is_same_v<remove_cvref_t<>, allocator_arg_t> || is_-
    same_v<remove_cvref_t<>, allocator_arg_t>>
    if sizeof...(Types) is 2 or 3;
  • otherwise, true_type.
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes),
  • sizeof...(Types)  ≥ 1, and
  • conjunction_v<disambiguating-constraint, is_constructible<Types, UTypes>...> is
    true.
Effects: Initializes the elements in the tuple with the corresponding value in std​::​forward<UTypes>(u).
Remarks: The expression inside explicit is equivalent to: !conjunction_v<is_convertible<UTypes, Types>...>
This constructor is defined as deleted if (reference_constructs_from_temporary_v<Types, UTypes&&> || ...) is true.
tuple(const tuple& u) = default;
Mandates: is_copy_constructible_v<> is true for all i.
Effects: Initializes each element of *this with the corresponding element of u.
tuple(tuple&& u) = default;
Constraints: is_move_constructible_v<> is true for all i.
Effects: For all i, initializes the element of *this with std​::​forward<>(get<i>(u)).
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>& u); template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u); template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u); template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&& u);
Let I be the pack 0, 1, ..., (sizeof...(Types) - 1).

Let FWD(u) be static_cast<decltype(u)>(u).
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes), and
  • (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...) is true, and
  • either sizeof...(Types) is not 1, or (when Types... expands to T and UTypes... expands to U) is_convertible_v<decltype(u), T>, is_constructible_v<T, decltype(u)>, and is_same_v<T, U> are all false.
Effects: For all i, initializes the element of *this with get<i>(FWD(u)).
Remarks: The expression inside explicit is equivalent to: !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)
The constructor is defined as deleted if (reference_constructs_from_temporary_v<Types, decltype(get<I>(FWD(u)))> || ...) is true.
template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>& u); template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u); template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u); template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&& u);
Let FWD(u) be static_cast<decltype(u)>(u).
Constraints:
  • sizeof...(Types) is 2,
  • is_constructible_v<, decltype(get<0>(FWD(u)))> is true, and
  • is_constructible_v<, decltype(get<1>(FWD(u)))> is true.
Effects: Initializes the first element with get<0>(FWD(u)) and the second element with get<1>(FWD(​u)).
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<decltype(get<0>(FWD(u))), > || !is_convertible_v<decltype(get<1>(FWD(u))), >
The constructor is defined as deleted if reference_constructs_from_temporary_v<, decltype(get<0>(FWD(u)))> || reference_constructs_from_temporary_v<, decltype(get<1>(FWD(u)))> is true.
template<tuple-like UTuple> constexpr explicit(see below) tuple(UTuple&& u);
Let I be the pack 0, 1, …, (sizeof...(Types) - 1).
Constraints:
  • different-from<UTuple, tuple> ([range.utility.helpers]) is true,
  • remove_cvref_t<UTuple> is not a specialization of ranges​::​subrange,
  • sizeof...(Types) equals tuple_size_v<remove_cvref_t<UTuple>>,
  • (is_constructible_v<Types, decltype(get<I>(std​::​forward<UTuple>(u)))> && ...) is true, and
  • either sizeof...(Types) is not 1, or (when Types... expands to T) is_convertible_v<UTuple, T> and is_constructible_v<T, UTuple> are both false.
Effects: For all i, initializes the element of *this with get<i>(std​::​forward<UTuple>(u)).
Remarks: The expression inside explicit is equivalent to: !(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)
The constructor is defined as deleted if (reference_constructs_from_temporary_v<Types, decltype(get<I>(std::forward<UTuple>(u)))> || ...) is true.
template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a); template<class Alloc> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const Types&...); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template<class Alloc> constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template<class Alloc, class... UTypes> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); template<class Alloc, class U1, class U2> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&); template<class Alloc, tuple-like UTuple> constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTuple&&);
Preconditions: Alloc meets the Cpp17Allocator requirements ([allocator.requirements.general]).
Effects: Equivalent to the preceding constructors except that each element is constructed with uses-allocator construction.

22.4.4.3 Assignment [tuple.assign]

For each tuple assignment operator, an exception is thrown only if the assignment of one of the types in Types throws an exception.
In the function descriptions that follow, let i be in the range [0, sizeof...(Types)) in order, be the type in Types, and be the type in a template parameter pack named UTypes, where indexing is zero-based.
constexpr tuple& operator=(const tuple& u);
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
Remarks: This operator is defined as deleted unless is_copy_assignable_v<> is true for all i.
constexpr const tuple& operator=(const tuple& u) const;
Constraints: (is_copy_assignable_v<const Types> && ...) is true.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
constexpr tuple& operator=(tuple&& u) noexcept(see below);
Constraints: is_move_assignable_v<> is true for all i.
Effects: For all i, assigns std​::​forward<>(get<i>(u)) to get<i>(*this).
Returns: *this.
Remarks: The exception specification is equivalent to the logical and of the following expressions: is_nothrow_move_assignable_v<> where is the type in Types.
constexpr const tuple& operator=(tuple&& u) const;
Constraints: (is_assignable_v<const Types&, Types> && ...) is true.
Effects: For all i, assigns std​::​forward<T>(get<i>(u)) to get<i>(*this).
Returns: *this.
template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • is_assignable_v<&, const &> is true for all i.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
template<class... UTypes> constexpr const tuple& operator=(const tuple<UTypes...>& u) const;
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • (is_assignable_v<const Types&, const UTypes&> && ...) is true.
Effects: Assigns each element of u to the corresponding element of *this.
Returns: *this.
template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • is_assignable_v<&, > is true for all i.
Effects: For all i, assigns std​::​forward<>(get<i>(u)) to get<i>(*this).
Returns: *this.
template<class... UTypes> constexpr const tuple& operator=(tuple<UTypes...>&& u) const;
Constraints:
  • sizeof...(Types) equals sizeof...(UTypes) and
  • (is_assignable_v<const Types&, UTypes> && ...) is true.
Effects: For all i, assigns std​::​forward<U>(get<i>(u)) to get<i>(*this).
Returns: *this.
template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
Constraints:
  • sizeof...(Types) is 2 and
  • is_assignable_v<&, const U1&> is true, and
  • is_assignable_v<&, const U2&> is true.
Effects: Assigns u.first to the first element of *this and u.second to the second element of *this.
Returns: *this.
template<class U1, class U2> constexpr const tuple& operator=(const pair<U1, U2>& u) const;
Constraints:
  • sizeof...(Types) is 2,
  • is_assignable_v<const &, const U1&> is true, and
  • is_assignable_v<const &, const U2&> is true.
Effects: Assigns u.first to the first element and u.second to the second element.
Returns: *this.
template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
Constraints:
  • sizeof...(Types) is 2 and
  • is_assignable_v<&, U1> is true, and
  • is_assignable_v<&, U2> is true.
Effects: Assigns std​::​forward<U1>(u.first) to the first element of *this and
std​::​forward<U2>(u.second) to the second element of *this.
Returns: *this.
template<class U1, class U2> constexpr const tuple& operator=(pair<U1, U2>&& u) const;
Constraints:
  • sizeof...(Types) is 2,
  • is_assignable_v<const &, U1> is true, and
  • is_assignable_v<const &, U2> is true.
Effects: Assigns std​::​forward<U1>(u.first) to the first element and
std​::​forward<U2>(u.second) to the second element.
Returns: *this.
template<tuple-like UTuple> constexpr tuple& operator=(UTuple&& u);
Constraints:
  • different-from<UTuple, tuple> ([range.utility.helpers]) is true,
  • remove_cvref_t<UTuple> is not a specialization of ranges​::​subrange,
  • sizeof...(Types) equals tuple_size_v<remove_cvref_t<UTuple>>, and,
  • is_assignable_v<&, decltype(get<i>(std​::​forward<UTuple>(u)))> is true for all i.
Effects: For all i, assigns get<i>(std​::​forward<UTuple>(u)) to get<i>(*this).
Returns: *this.
template<tuple-like UTuple> constexpr const tuple& operator=(UTuple&& u) const;
Constraints:
  • different-from<UTuple, tuple> ([range.utility.helpers]) is true,
  • remove_cvref_t<UTuple> is not a specialization of ranges​::​subrange,
  • sizeof...(Types) equals tuple_size_v<remove_cvref_t<UTuple>>, and,
  • is_assignable_v<const &, decltype(get<i>(std​::​forward<UTuple>(u)))> is true for all i.
Effects: For all i, assigns get<i>(std​::​forward<UTuple>(u)) to get<i>(*this).
Returns: *this.

22.4.4.4 swap [tuple.swap]

constexpr void swap(tuple& rhs) noexcept(see below); constexpr void swap(const tuple& rhs) const noexcept(see below);
Let i be in the range [0, sizeof...(Types)) in order.
Mandates:
  • For the first overload, (is_swappable_v<Types> && ...) is true.
  • For the second overload, (is_swappable_v<const Types> && ...) is true.
Preconditions: For all i, get<i>(*this) is swappable with ([swappable.requirements]) get<i>(rhs).
Effects: For each i, calls swap for get<i>(*this) and get<i>(rhs).
Throws: Nothing unless one of the element-wise swap calls throws an exception.
Remarks: The exception specification is equivalent to
  • (is_nothrow_swappable_v<Types> && ...) for the first overload and
  • (is_nothrow_swappable_v<const Types> && ...) for the second overload.

22.4.5 Tuple creation functions [tuple.creation]

template<class... TTypes> constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... t);
Returns: tuple<unwrap_ref_decay_t<TTypes>...>(std​::​forward<TTypes>(t)...).
[Example 1: 
int i; float j; make_tuple(1, ref(i), cref(j)); creates a tuple of type tuple<int, int&, const float&>.
— end example]
template<class... TTypes> constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
Effects: Constructs a tuple of references to the arguments in t suitable for forwarding as arguments to a function.
Because the result may contain references to temporary objects, a program shall ensure that the return value of this function does not outlive any of its arguments (e.g., the program should typically not store the result in a named variable).
Returns: tuple<TTypes&&...>(std​::​forward<TTypes>(t)...).
template<class... TTypes> constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
Returns: tuple<TTypes&...>(t...).
[Example 2: 
tie functions allow one to create tuples that unpack tuples into variables.
ignore can be used for elements that are not needed: int i; std::string s; tie(i, ignore, s) = make_tuple(42, 3.14, "C++"); // i == 42, s == "C++"
— end example]
template<tuple-like... Tuples> constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
Let n be sizeof...(Tuples).
For every integer :
  • Let be the type in Tuples.
  • Let be remove_cvref_t<>.
  • Let be the element in the function parameter pack tpls.
  • Let be tuple_size_v<>.
  • Let be tuple_element_t<k, >.
  • Let be get<k>(std​::​forward<>()).
  • Let be a pack of the types .
  • Let be a pack of the expressions .
The types in CTypes are equal to the ordered sequence of the expanded packs of types ..., ..., …, ....
Let celems be the ordered sequence of the expanded packs of expressions ..., …, ....
Mandates: (is_constructible_v<CTypes, decltype(celems)> && ...) is true.
Returns: tuple<CTypes...>(celems...).

22.4.6 Calling a function with a tuple of arguments [tuple.apply]

template<class F, tuple-like Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(see below);
Effects: Given the exposition-only function template: namespace std { template<class F, tuple-like Tuple, size_t... I> constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) { // exposition only return INVOKE(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...); // see [func.require] } }
Equivalent to: return apply-impl(std::forward<F>(f), std::forward<Tuple>(t), make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
Remarks: Let I be the pack 0, 1, ..., (tuple_size_v<remove_reference_t<Tuple>> - 1).
The exception specification is equivalent to: noexcept(invoke(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...))
template<class T, tuple-like Tuple> constexpr T make_from_tuple(Tuple&& t);
Mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
Effects: Given the exposition-only function template: namespace std { template<class T, tuple-like Tuple, size_t... I> requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...> constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) { // exposition only return T(get<I>(std::forward<Tuple>(t))...); } }
Equivalent to: return make-from-tuple-impl<T>( std::forward<Tuple>(t), make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
[Note 1: 
The type of T must be supplied as an explicit template parameter, as it cannot be deduced from the argument list.
— end note]

22.4.7 Tuple helper classes [tuple.helper]

template<class T> struct tuple_size;
Except where specified otherwise, all specializations of tuple_size meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, N> for some N.
template<class... Types> struct tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types> struct tuple_element<I, tuple<Types...>> { using type = TI; };
Mandates: I < sizeof...(Types).
Type: TI is the type of the element of Types, where indexing is zero-based.
template<class T> struct tuple_size<const T>;
Let TS denote tuple_size<T> of the cv-unqualified type T.
If the expression TS​::​value is well-formed when treated as an unevaluated operand, then each specialization of the template meets the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, TS::value>
Otherwise, it has no member value.
Access checking is performed as if in a context unrelated to TS and T.
Only the validity of the immediate context of the expression is considered.
[Note 1: 
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]
In addition to being available via inclusion of the <tuple> header, the template is available when any of the headers <array>, <ranges>, or <utility> are included.
template<size_t I, class T> struct tuple_element<I, const T>;
Let TE denote tuple_element_t<I, T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the type add_const_t<TE>.
In addition to being available via inclusion of the <tuple> header, the template is available when any of the headers <array>, <ranges>, or <utility> are included.

22.4.8 Element access [tuple.elem]

template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>& t) noexcept; template<size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&& t) noexcept; // #1 template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>& t) noexcept; // #2 template<size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Mandates: I < sizeof...(Types).
Returns: A reference to the element of t, where indexing is zero-based.
[Note 1: 
For the overload marked #1, if a type T in Types is some reference type X&, the return type is X&, not X&&.
However, if the element type is a non-reference type T, the return type is T&&.
— end note]
[Note 2: 
Constness is shallow.
For the overload marked #2, if a type T in Types is some reference type X&, the return type is X&, not const X&.
However, if the element type is a non-reference type T, the return type is const T&.
This is consistent with how constness is defined to work for non-static data members of reference type.
— end note]
template<class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template<class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template<class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: A reference to the element of t corresponding to the type T in Types.
[Example 1: const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6); const int& i1 = get<int>(t); // OK, i1 has value 1 const int& i2 = get<const int>(t); // OK, i2 has value 2 const double& d = get<double>(t); // error: type double is not unique within t — end example]
[Note 3: 
The reason get is a non-member function is that if this functionality had been provided as a member function, code where the type depended on a template parameter would have required using the template keyword.
— end note]

22.4.9 Relational operators [tuple.rel]

template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u); template<class... TTypes, tuple-like UTuple> constexpr bool operator==(const tuple<TTypes...>& t, const UTuple& u);
For the first overload let UTuple be tuple<UTypes...>.
Constraints: For all i, where 0  ≤ i < sizeof...(TTypes), get<i>(t) == get<i>(u) is a valid expression and decltype(get<i>(t) == get<i>(u)) models boolean-testable.
sizeof...(TTypes) equals tuple_size_v<UTuple>.
Returns: true if get<i>(t) == get<i>(u) for all i, otherwise false.
[Note 1: 
If sizeof...(TTypes) equals zero, returns true.
— end note]
Remarks:
  • The elementary comparisons are performed in order from the zeroth index upwards.
    No comparisons or element accesses are performed after the first equality comparison that evaluates to false.
  • The second overload is to be found via argument-dependent lookup ([basic.lookup.argdep]) only.
template<class... TTypes, class... UTypes> constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...> operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u); template<class... TTypes, tuple-like UTuple> constexpr common_comparison_category_t<synth-three-way-result<TTypes, Elems>...> operator<=>(const tuple<TTypes...>& t, const UTuple& u);
For the second overload, Elems denotes the pack of types tuple_element_t<0, UTuple>, tuple_element_t<1, UTuple>, …, tuple_element_t<tuple_size_v<UTuple> - 1, UTuple>.
Effects: Performs a lexicographical comparison between t and u.
If sizeof...(TTypes) equals zero, returns strong_ordering​::​equal.
Otherwise, equivalent to: if (auto c = synth-three-way(get<0>(t), get<0>(u)); c != 0) return c; return <=> ; where for some r is a tuple containing all but the first element of r.
Remarks: The second overload is to be found via argument-dependent lookup ([basic.lookup.argdep]) only.
[Note 2: 
The above definition does not require t (or u) to be constructed.
It might not even be possible, as t and u are not required to be copy constructible.
Also, all comparison operator functions are short circuited; they do not perform element accesses beyond what is needed to determine the result of the comparison.
— end note]

22.4.10 common_reference related specializations [tuple.common.ref]

In the descriptions that follow:
  • Let TTypes be a pack formed by the sequence of tuple_element_t<i, TTuple> for every integer .
  • Let UTypes be a pack formed by the sequence of tuple_element_t<i, UTuple> for every integer .
template<tuple-like TTuple, tuple-like UTuple, template<class> class TQual, template<class> class UQual> struct basic_common_reference<TTuple, UTuple, TQual, UQual> { using type = see below; };
Constraints:
  • TTuple is a specialization of tuple or UTuple is a specialization of tuple.
  • is_same_v<TTuple, decay_t<TTuple>> is true.
  • is_same_v<UTuple, decay_t<UTuple>> is true.
  • tuple_size_v<TTuple> equals tuple_size_v<UTuple>.
  • tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...> denotes a type.
The member typedef-name type denotes the type tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>.
template<tuple-like TTuple, tuple-like UTuple> struct common_type<TTuple, UTuple> { using type = see below; };
Constraints:
  • TTuple is a specialization of tuple or UTuple is a specialization of tuple.
  • is_same_v<TTuple, decay_t<TTuple>> is true.
  • is_same_v<UTuple, decay_t<UTuple>> is true.
  • tuple_size_v<TTuple> equals tuple_size_v<UTuple>.
  • tuple<common_type_t<TTypes, UTypes>...> denotes a type.
The member typedef-name type denotes the type tuple<common_type_t<TTypes, UTypes>...>.

22.4.11 Tuple traits [tuple.traits]

template<class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
Preconditions: Alloc meets the Cpp17Allocator requirements ([allocator.requirements.general]).
[Note 1: 
Specialization of this trait informs other library components that tuple can be constructed with an allocator, even though it does not have a nested allocator_type.
— end note]

22.4.12 Tuple specialized algorithms [tuple.special]

template<class... Types> constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below); template<class... Types> constexpr void swap(const tuple<Types...>& x, const tuple<Types...>& y) noexcept(see below);
Constraints:
  • For the first overload, (is_swappable_v<Types> && ...) is true.
  • For the second overload, (is_swappable_v<const Types> && ...) is true.
Effects: As if by x.swap(y).
Remarks: The exception specification is equivalent to: noexcept(x.swap(y))

22.5 Optional objects [optional]

22.5.1 General [optional.general]

Subclause [optional] describes class template optional that represents optional objects.
An optional object is an object that contains the storage for another object and manages the lifetime of this contained object, if any.
The contained object may be initialized after the optional object has been initialized, and may be destroyed before the optional object has been destroyed.
The initialization state of the contained object is tracked by the optional object.

22.5.2 Header <optional> synopsis [optional.syn]

// mostly freestanding #include <compare> // see [compare.syn] namespace std { // [optional.optional], class template optional template<class T> class optional; // partially freestanding template<class T> constexpr bool ranges::enable_view<optional<T>> = true; template<class T> constexpr auto format_kind<optional<T>> = range_format::disabled; template<class T> concept is-derived-from-optional = requires(const T& t) { // exposition only []<class U>(const optional<U>&){ }(t); }; // [optional.nullopt], no-value state indicator struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified); // [optional.bad.access], class bad_optional_access class bad_optional_access; // [optional.relops], relational operators template<class T, class U> constexpr bool operator==(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const optional<U>&); template<class T, three_way_comparable_with<T> U> constexpr compare_three_way_result_t<T, U> operator<=>(const optional<T>&, const optional<U>&); // [optional.nullops], comparison with nullopt template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; template<class T> constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // [optional.comp.with.t], comparison with T template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); template<class T, class U> requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U> constexpr compare_three_way_result_t<T, U> operator<=>(const optional<T>&, const U&); // [optional.specalg], specialized algorithms template<class T> constexpr void swap(optional<T>&, optional<T>&) noexcept(see below); template<class T> constexpr optional<decay_t<T>> make_optional(T&&); template<class T, class... Args> constexpr optional<T> make_optional(Args&&... args); template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); // [optional.hash], hash support template<class T> struct hash; template<class T> struct hash<optional<T>>; }

22.5.3 Class template optional [optional.optional]

22.5.3.1 General [optional.optional.general]

namespace std { template<class T> class optional { public: using value_type = T; using iterator = implementation-defined; // see [optional.iterators] using const_iterator = implementation-defined; // see [optional.iterators] // [optional.ctor], constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional&); constexpr optional(optional&&) noexcept(see below); template<class... Args> constexpr explicit optional(in_place_t, Args&&...); template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...); template<class U = remove_cv_t<T>> constexpr explicit(see below) optional(U&&); template<class U> constexpr explicit(see below) optional(const optional<U>&); template<class U> constexpr explicit(see below) optional(optional<U>&&); // [optional.dtor], destructor constexpr ~optional(); // [optional.assign], assignment constexpr optional& operator=(nullopt_t) noexcept; constexpr optional& operator=(const optional&); constexpr optional& operator=(optional&&) noexcept(see below); template<class U = remove_cv_t<T>> constexpr optional& operator=(U&&); template<class U> constexpr optional& operator=(const optional<U>&); template<class U> constexpr optional& operator=(optional<U>&&); template<class... Args> constexpr T& emplace(Args&&...); template<class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...); // [optional.swap], swap constexpr void swap(optional&) noexcept(see below); // [optional.iterators], iterator support constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; // [optional.observe], observers constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept; constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; constexpr T&& operator*() && noexcept; constexpr const T&& operator*() const && noexcept; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr const T& value() const &; // freestanding-deleted constexpr T& value() &; // freestanding-deleted constexpr T&& value() &&; // freestanding-deleted constexpr const T&& value() const &&; // freestanding-deleted template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&; // [optional.monadic], monadic operations template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &; template<class F> constexpr auto and_then(F&& f) const &&; template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &; template<class F> constexpr auto transform(F&& f) const &&; template<class F> constexpr optional or_else(F&& f) &&; template<class F> constexpr optional or_else(F&& f) const &; // [optional.mod], modifiers constexpr void reset() noexcept; private: T* val; // exposition only }; template<class T> optional(T) -> optional<T>; }
Any instance of optional<T> at any given time either contains a value or does not contain a value.
When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object's contained value, is nested within ([intro.object]) the optional object.
When an object of type optional<T> is contextually converted to bool, the conversion returns true if the object contains a value; otherwise the conversion returns false.
When an optional<T> object contains a value, member val points to the contained value.
T shall be a type other than cv in_place_t or cv nullopt_t that meets the Cpp17Destructible requirements (Table 35).

22.5.3.2 Constructors [optional.ctor]

The exposition-only variable template converts-from-any-cvref is used by some constructors for optional.
template<class T, class W> constexpr bool converts-from-any-cvref = // exposition only disjunction_v<is_constructible<T, W&>, is_convertible<W&, T>, is_constructible<T, W>, is_convertible<W, T>, is_constructible<T, const W&>, is_convertible<const W&, T>, is_constructible<T, const W>, is_convertible<const W, T>>;
constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;
Postconditions: *this does not contain a value.
Remarks: No contained value is initialized.
For every object type T these constructors are constexpr constructors ([dcl.constexpr]).
constexpr optional(const optional& rhs);
Effects: If rhs contains a value, direct-non-list-initializes the contained value with *rhs.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: This constructor is defined as deleted unless is_copy_constructible_v<T> is true.
If is_trivially_copy_constructible_v<T> is true, this constructor is trivial.
constexpr optional(optional&& rhs) noexcept(see below);
Constraints: is_move_constructible_v<T> is true.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with std​::​move(*rhs).
rhs.has_value() is unchanged.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<T>.
If is_trivially_move_constructible_v<T> is true, this constructor is trivial.
template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Constraints: is_constructible_v<T, Args...> is true.
Effects: Direct-non-list-initializes the contained value with std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value with il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor.
template<class U = remove_cv_t<T>> constexpr explicit(see below) optional(U&& v);
Constraints:
  • is_constructible_v<T, U> is true,
  • is_same_v<remove_cvref_t<U>, in_place_t> is false,
  • is_same_v<remove_cvref_t<U>, optional> is false, and
  • if T is cv bool, remove_cvref_t<U> is not a specialization of optional.
Effects: Direct-non-list-initializes the contained value with std​::​forward<U>(v).
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
The expression inside explicit is equivalent to: !is_convertible_v<U, T>
template<class U> constexpr explicit(see below) optional(const optional<U>& rhs);
Constraints:
  • is_constructible_v<T, const U&> is true, and
  • if T is not cv bool, converts-from-any-cvref<T, optional<U>> is false.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with *rhs.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const U&, T>
template<class U> constexpr explicit(see below) optional(optional<U>&& rhs);
Constraints:
  • is_constructible_v<T, U> is true, and
  • if T is not cv bool, converts-from-any-cvref<T, optional<U>> is false.
Effects: If rhs contains a value, direct-non-list-initializes the contained value with std​::​move(*rhs).
rhs.has_value() is unchanged.
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the selected constructor of T.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<U, T>

22.5.3.3 Destructor [optional.dtor]

constexpr ~optional();
Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls val->T::~T()
Remarks: If is_trivially_destructible_v<T> is true, then this destructor is trivial.

22.5.3.4 Assignment [optional.assign]

constexpr optional<T>& operator=(nullopt_t) noexcept;
Effects: If *this contains a value, calls val->T​::​~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.
Returns: *this.
constexpr optional<T>& operator=(const optional& rhs);
Effects: See Table 62.
Table 62optional​::​operator=(const optional&) effects [tab:optional.assign.copy]
*this contains a value
*this does not contain a value
rhs contains a value
assigns *rhs to the contained value
direct-non-list-initializes the contained value with *rhs
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: rhs.has_value() == this->has_value().
Returns: *this.
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's copy constructor, no effect.
If an exception is thrown during the call to T's copy assignment, the state of its contained value is as defined by the exception safety guarantee of T's copy assignment.
This operator is defined as deleted unless is_copy_constructible_v<T> is true and is_copy_assignable_v<T> is true.
If is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T> && is_trivially_destructible_v<T> is true, this assignment operator is trivial.
constexpr optional& operator=(optional&& rhs) noexcept(see below);
Constraints: is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.
Effects: See Table 63.
The result of the expression rhs.has_value() remains unchanged.
Table 63optional​::​operator=(optional&&) effects [tab:optional.assign.move]
*this contains a value
*this does not contain a value
rhs contains a value
assigns std​::​move(*rhs) to the contained value
direct-non-list-initializes the contained value with std​::​move(*rhs)
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: rhs.has_value() == this->has_value().
Returns: *this.
Remarks: The exception specification is equivalent to: is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's move constructor, the state of *rhs.val is determined by the exception safety guarantee of T's move constructor.
If an exception is thrown during the call to T's move assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move assignment.
If is_trivially_move_constructible_v<T> && is_trivially_move_assignable_v<T> && is_trivially_destructible_v<T> is true, this assignment operator is trivial.
template<class U = remove_cv_t<T>> constexpr optional& operator=(U&& v);
Constraints:
  • is_same_v<remove_cvref_t<U>, optional> is false,
  • conjunction_v<is_scalar<T>, is_same<T, decay_t<U>>> is false,
  • is_constructible_v<T, U> is true, and
  • is_assignable_v<T&, U> is true.
Effects: If *this contains a value, assigns std​::​forward<U>(v) to the contained value; otherwise direct-non-list-initializes the contained value with std​::​forward<U>(v).
Postconditions: *this contains a value.
Returns: *this.
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of v is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and v is determined by the exception safety guarantee of T's assignment.
template<class U> constexpr optional<T>& operator=(const optional<U>& rhs);
Constraints:
  • is_constructible_v<T, const U&> is true,
  • is_assignable_v<T&, const U&> is true,
  • converts-from-any-cvref<T, optional<U>> is false,
  • is_assignable_v<T&, optional<U>&> is false,
  • is_assignable_v<T&, optional<U>&&> is false,
  • is_assignable_v<T&, const optional<U>&> is false, and
  • is_assignable_v<T&, const optional<U>&&> is false.
Effects: See Table 64.
Table 64optional​::​operator=(const optional<U>&) effects [tab:optional.assign.copy.templ]
*this contains a value
*this does not contain a value
rhs contains a value
assigns *rhs to the contained value
direct-non-list-initializes the contained value with *rhs
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: rhs.has_value() == this->has_value().
Returns: *this.
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class U> constexpr optional<T>& operator=(optional<U>&& rhs);
Constraints:
  • is_constructible_v<T, U> is true,
  • is_assignable_v<T&, U> is true,
  • converts-from-any-cvref<T, optional<U>> is false,
  • is_assignable_v<T&, optional<U>&> is false,
  • is_assignable_v<T&, optional<U>&&> is false,
  • is_assignable_v<T&, const optional<U>&> is false, and
  • is_assignable_v<T&, const optional<U>&&> is false.
Effects: See Table 65.
The result of the expression rhs.has_value() remains unchanged.
Table 65optional​::​operator=(optional<U>&&) effects [tab:optional.assign.move.templ]
*this contains a value
*this does not contain a value
rhs contains a value
assigns std​::​move(*rhs) to the contained value
direct-non-list-initializes the contained value with std​::​move(*rhs)
rhs does not contain a value
destroys the contained value by calling val->T​::​~T()
no effect
Postconditions: rhs.has_value() == this->has_value().
Returns: *this.
Remarks: If any exception is thrown, the result of the expression this->has_value() remains unchanged.
If an exception is thrown during the call to T's constructor, the state of *rhs.val is determined by the exception safety guarantee of T's constructor.
If an exception is thrown during the call to T's assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T's assignment.
template<class... Args> constexpr T& emplace(Args&&... args);
Mandates: is_constructible_v<T, Args...> is true.
Effects: Calls *this = nullopt.
Then direct-non-list-initializes the contained value with std​::​forward​<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.
template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Calls *this = nullopt.
Then direct-non-list-initializes the contained value with il, std​::​​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of T.
Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and the previous *val (if any) has been destroyed.

22.5.3.5 Swap [optional.swap]

constexpr void swap(optional& rhs) noexcept(see below);
Mandates: is_move_constructible_v<T> is true.
Preconditions: T meets the Cpp17Swappable requirements ([swappable.requirements]).
Effects: See Table 66.
Table 66optional​::​swap(optional&) effects [tab:optional.swap]
*this contains a value
*this does not contain a value
rhs contains a value
calls swap(*(*this), *rhs)
direct-non-list-initializes the contained value of *this with std​::​move(*rhs), followed by rhs.val->T​::​~T(); postcondition is that *this contains a value and rhs does not contain a value
rhs does not contain a value
direct-non-list-initializes the contained value of rhs with std​::​move(*(*this)), followed by val->T​::​~T(); postcondition is that *this does not contain a value and rhs contains a value
no effect
Throws: Any exceptions thrown by the operations in the relevant part of Table 66.
Remarks: The exception specification is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions this->has_value() and rhs.has_value() remain unchanged.
If an exception is thrown during the call to function swap, the state of *val and *rhs.val is determined by the exception safety guarantee of swap for lvalues of T.
If an exception is thrown during the call to T's move constructor, the state of *val and *rhs.val is determined by the exception safety guarantee of T's move constructor.

22.5.3.6 Iterator support [optional.iterators]

using iterator = implementation-defined; using const_iterator = implementation-defined;
These types model contiguous_iterator ([iterator.concept.contiguous]), meet the Cpp17RandomAccessIterator requirements ([random.access.iterators]), and meet the requirements for constexpr iterators ([iterator.requirements.general]), with value type remove_cv_t<T>.
The reference type is T& for iterator and const T& for const_iterator.
All requirements on container iterators ([container.reqmts]) apply to optional​::​iterator and optional​::​const_iterator as well.
Any operation that initializes or destroys the contained value of an optional object invalidates all iterators into that object.
constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept;
Returns: If has_value() is true, an iterator referring to the contained value.
Otherwise, a past-the-end iterator value.
constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept;
Returns: begin() + has_value().

22.5.3.7 Observers [optional.observe]

constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept;
Preconditions: *this contains a value.
Returns: val.
Remarks: These functions are constexpr functions.
constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept;
Preconditions: *this contains a value.
Returns: *val.
Remarks: These functions are constexpr functions.
constexpr T&& operator*() && noexcept; constexpr const T&& operator*() const && noexcept;
Preconditions: *this contains a value.
Effects: Equivalent to: return std​::​move(*val);
constexpr explicit operator bool() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr bool has_value() const noexcept;
Returns: true if and only if *this contains a value.
Remarks: This function is a constexpr function.
constexpr const T& value() const &; constexpr T& value() &;
Effects: Equivalent to: return has_value() ? *val : throw bad_optional_access();
constexpr T&& value() &&; constexpr const T&& value() const &&;
Effects: Equivalent to: return has_value() ? std::move(*val) : throw bad_optional_access();
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
Mandates: is_copy_constructible_v<T> && is_convertible_v<U&&, T> is true.
Effects: Equivalent to: return has_value() ? **this : static_cast<T>(std::forward<U>(v));
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
Mandates: is_move_constructible_v<T> && is_convertible_v<U&&, T> is true.
Effects: Equivalent to: return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));

22.5.3.8 Monadic operations [optional.monadic]

template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) const &;
Let U be invoke_result_t<F, decltype(*val)>.
Mandates: remove_cvref_t<U> is a specialization of optional.
Effects: Equivalent to: if (*this) { return invoke(std::forward<F>(f), *val); } else { return remove_cvref_t<U>(); }
template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &&;
Let U be invoke_result_t<F, decltype(std​::​move(*val))>.
Mandates: remove_cvref_t<U> is a specialization of optional.
Effects: Equivalent to: if (*this) { return invoke(std::forward<F>(f), std::move(*val)); } else { return remove_cvref_t<U>(); }
template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) const &;
Let U be remove_cv_t<invoke_result_t<F, decltype(*val)>>.
Mandates: U is a non-array object type other than in_place_t or nullopt_t.
The declaration U u(invoke(std::forward<F>(f), *val)); is well-formed for some invented variable u.
[Note 1: 
There is no requirement that U is movable ([dcl.init.general]).
— end note]
Returns: If *this contains a value, an optional<U> object whose contained value is direct-non-list-initialized with invoke(std​::​forward<F>(f), *val); otherwise, optional<U>().
template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &&;
Let U be remove_cv_t<invoke_result_t<F, decltype(std​::​move(*val))>>.
Mandates: U is a non-array object type other than in_place_t or nullopt_t.
The declaration U u(invoke(std::forward<F>(f), std::move(*val))); is well-formed for some invented variable u.
[Note 2: 
There is no requirement that U is movable ([dcl.init.general]).
— end note]
Returns: If *this contains a value, an optional<U> object whose contained value is direct-non-list-initialized with invoke(std​::​forward<F>(f), std​::​move(*val)); otherwise, optional<U>().
template<class F> constexpr optional or_else(F&& f) const &;
Constraints: F models invocable<> and T models copy_constructible.
Mandates: is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is true.
Effects: Equivalent to: if (*this) { return *this; } else { return std::forward<F>(f)(); }
template<class F> constexpr optional or_else(F&& f) &&;
Constraints: F models invocable<> and T models move_constructible.
Mandates: is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is true.
Effects: Equivalent to: if (*this) { return std::move(*this); } else { return std::forward<F>(f)(); }

22.5.3.9 Modifiers [optional.mod]

constexpr void reset() noexcept;
Effects: If *this contains a value, calls val->T​::​~T() to destroy the contained value; otherwise no effect.
Postconditions: *this does not contain a value.

22.5.4 No-value state indicator [optional.nullopt]

struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified);
The struct nullopt_t is an empty class type used as a unique type to indicate the state of not containing a value for optional objects.
In particular, optional<T> has a constructor with nullopt_t as a single argument; this indicates that an optional object not containing a value shall be constructed.
Type nullopt_t shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate.

22.5.5 Class bad_optional_access [optional.bad.access]

namespace std { class bad_optional_access : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; }; }
The class bad_optional_access defines the type of objects thrown as exceptions to report the situation where an attempt is made to access the value of an optional object that does not contain a value.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.5.6 Relational operators [optional.relops]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
Constraints: The expression *x == *y is well-formed and its result is convertible to bool.
[Note 1:  — end note]
Returns: If x.has_value() != y.has_value(), false; otherwise if x.has_value() == false, true; otherwise *x == *y.
Remarks: Specializations of this function template for which *x == *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
Constraints: The expression *x != *y is well-formed and its result is convertible to bool.
Returns: If x.has_value() != y.has_value(), true; otherwise, if x.has_value() == false, false; otherwise *x != *y.
Remarks: Specializations of this function template for which *x != *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
Constraints: *x < *y is well-formed and its result is convertible to bool.
Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
Remarks: Specializations of this function template for which *x < *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Constraints: The expression *x > *y is well-formed and its result is convertible to bool.
Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
Remarks: Specializations of this function template for which *x > *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Constraints: The expression *x <= *y is well-formed and its result is convertible to bool.
Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
Remarks: Specializations of this function template for which *x <= *y is a core constant expression are constexpr functions.
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Constraints: The expression *x >= *y is well-formed and its result is convertible to bool.
Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
Remarks: Specializations of this function template for which *x >= *y is a core constant expression are constexpr functions.
template<class T, three_way_comparable_with<T> U> constexpr compare_three_way_result_t<T, U> operator<=>(const optional<T>& x, const optional<U>& y);
Returns: If x && y, *x <=> *y; otherwise x.has_value() <=> y.has_value().
Remarks: Specializations of this function template for which *x <=> *y is a core constant expression are constexpr functions.

22.5.7 Comparison with nullopt [optional.nullops]

template<class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;
Returns: !x.
template<class T> constexpr strong_ordering operator<=>(const optional<T>& x, nullopt_t) noexcept;
Returns: x.has_value() <=> false.

22.5.8 Comparison with T [optional.comp.with.t]

template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x == v is well-formed and its result is convertible to bool.
[Note 1:  — end note]
Effects: Equivalent to: return x.has_value() ? *x == v : false;
template<class T, class U> constexpr bool operator==(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v == *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v == *x : false;
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x != v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? *x != v : true;
template<class T, class U> constexpr bool operator!=(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v != *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v != *x : true;
template<class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x < v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? *x < v : true;
template<class T, class U> constexpr bool operator<(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v < *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v < *x : false;
template<class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x > v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? *x > v : false;
template<class T, class U> constexpr bool operator>(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v > *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v > *x : true;
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x <= v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? *x <= v : true;
template<class T, class U> constexpr bool operator<=(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v <= *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v <= *x : false;
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
Constraints: U is not a specialization of optional.
The expression *x >= v is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? *x >= v : false;
template<class T, class U> constexpr bool operator>=(const T& v, const optional<U>& x);
Constraints: T is not a specialization of optional.
The expression v >= *x is well-formed and its result is convertible to bool.
Effects: Equivalent to: return x.has_value() ? v >= *x : true;
template<class T, class U> requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U> constexpr compare_three_way_result_t<T, U> operator<=>(const optional<T>& x, const U& v);
Effects: Equivalent to: return x.has_value() ? *x <=> v : strong_ordering​::​less;

22.5.9 Specialized algorithms [optional.specalg]

template<class T> constexpr void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_move_constructible_v<T> is true and is_swappable_v<T> is true.
Effects: Calls x.swap(y).
template<class T> constexpr optional<decay_t<T>> make_optional(T&& v);
Returns: optional<decay_t<T>>(std​::​forward<T>(v)).
template<class T, class...Args> constexpr optional<T> make_optional(Args&&... args);
Effects: Equivalent to: return optional<T>(in_place, std​::​forward<Args>(args)...);
template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
Effects: Equivalent to: return optional<T>(in_place, il, std​::​forward<Args>(args)...);

22.5.10 Hash support [optional.hash]

template<class T> struct hash<optional<T>>;
The specialization hash<optional<T>> is enabled ([unord.hash]) if and only if hash<remove_const_t<T>> is enabled.
When enabled, for an object o of type optional<T>, if o.has_value() == true, then hash<optional<T>>()(o) evaluates to the same value as hash<remove_const_t<T>>()(*o); otherwise it evaluates to an unspecified value.
The member functions are not guaranteed to be noexcept.

22.6 Variants [variant]

22.6.1 General [variant.general]

A variant object holds and manages the lifetime of a value.
If the variant holds a value, that value's type has to be one of the template argument types given to variant.
These template arguments are called alternatives.
In [variant], GET denotes a set of exposition-only function templates ([variant.get]).

22.6.2 Header <variant> synopsis [variant.syn]

// mostly freestanding #include <compare> // see [compare.syn] namespace std { // [variant.variant], class template variant template<class... Types> class variant; // [variant.helper], variant helper classes template<class T> struct variant_size; // not defined template<class T> struct variant_size<const T>; template<class T> constexpr size_t variant_size_v = variant_size<T>::value; template<class... Types> struct variant_size<variant<Types...>>; template<size_t I, class T> struct variant_alternative; // not defined template<size_t I, class T> struct variant_alternative<I, const T>; template<size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type; template<size_t I, class... Types> struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; // [variant.get], value access template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept; template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); // freestanding-deleted template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); // freestanding-deleted template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); // freestanding-deleted template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); // freestanding-deleted template<class T, class... Types> constexpr T& get(variant<Types...>&); // freestanding-deleted template<class T, class... Types> constexpr T&& get(variant<Types...>&&); // freestanding-deleted template<class T, class... Types> constexpr const T& get(const variant<Types...>&); // freestanding-deleted template<class T, class... Types> constexpr const T&& get(const variant<Types...>&&); // freestanding-deleted template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept; template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept; template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept; // [variant.relops], relational operators template<class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); template<class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); template<class... Types> requires (three_way_comparable<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>&, const variant<Types...>&); // [variant.visit], visitation template<class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...); template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...); // [variant.monostate], class monostate struct monostate; // [variant.monostate.relops], monostate relational operators constexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [variant.specalg], specialized algorithms template<class... Types> constexpr void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); // [variant.bad.access], class bad_variant_access class bad_variant_access; // [variant.hash], hash support template<class T> struct hash; template<class... Types> struct hash<variant<Types...>>; template<> struct hash<monostate>; }

22.6.3 Class template variant [variant.variant]

22.6.3.1 General [variant.variant.general]

namespace std { template<class... Types> class variant { public: // [variant.ctor], constructors constexpr variant() noexcept(see below); constexpr variant(const variant&); constexpr variant(variant&&) noexcept(see below); template<class T> constexpr variant(T&&) noexcept(see below); template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...); template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...); // [variant.dtor], destructor constexpr ~variant(); // [variant.assign], assignment constexpr variant& operator=(const variant&); constexpr variant& operator=(variant&&) noexcept(see below); template<class T> constexpr variant& operator=(T&&) noexcept(see below); // [variant.mod], modifiers template<class T, class... Args> constexpr T& emplace(Args&&...); template<class T, class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...); template<size_t I, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&...); template<size_t I, class U, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...); // [variant.status], value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [variant.swap], swap constexpr void swap(variant&) noexcept(see below); // [variant.visit], visitation template<class Self, class Visitor> constexpr decltype(auto) visit(this Self&&, Visitor&&); template<class R, class Self, class Visitor> constexpr R visit(this Self&&, Visitor&&); }; }
Any instance of variant at any given time either holds a value of one of its alternative types or holds no value.
When an instance of variant holds a value of alternative type T, it means that a value of type T, referred to as the variant object's contained value, is nested within ([intro.object]) the variant object.
All types in Types shall meet the Cpp17Destructible requirements (Table 35).
A program that instantiates the definition of variant with no template arguments is ill-formed.
If a program declares an explicit or partial specialization of variant, the program is ill-formed, no diagnostic required.

22.6.3.2 Constructors [variant.ctor]

In the descriptions that follow, let i be in the range [0, sizeof...(Types)), and be the type in Types.
constexpr variant() noexcept(see below);
Constraints: is_default_constructible_v<> is true.
Effects: Constructs a variant holding a value-initialized value of type .
Postconditions: valueless_by_exception() is false and index() is 0.
Throws: Any exception thrown by the value-initialization of .
Remarks: This function is constexpr if and only if the value-initialization of the alternative type would be constexpr-suitable ([dcl.constexpr]).
The exception specification is equivalent to is_nothrow_default_constructible_v<>.
[Note 1: 
See also class monostate.
— end note]
constexpr variant(const variant& w);
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with GET<j>(w), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by direct-initializing any for all i.
Remarks: This constructor is defined as deleted unless is_copy_constructible_v<> is true for all i.
If is_trivially_copy_constructible_v<> is true for all i, this constructor is trivial.
constexpr variant(variant&& w) noexcept(see below);
Constraints: is_move_constructible_v<> is true for all i.
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with GET<j>(std​::​move(w)), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by move-constructing any for all i.
Remarks: The exception specification is equivalent to the logical and of is_nothrow_move_constructible_v<> for all i.
If is_trivially_move_constructible_v<> is true for all i, this constructor is trivial.
template<class T> constexpr variant(T&& t) noexcept(see below);
Let be a type that is determined as follows: build an imaginary function FUN() for each alternative type for which x[] = {std​::​forward<T>(t)}; is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std​::​forward<T>(​t)) defines the alternative which is the type of the contained value after construction.
Constraints:
  • sizeof...(Types) is nonzero,
  • is_same_v<remove_cvref_t<T>, variant> is false,
  • remove_cvref_t<T> is neither a specialization of in_place_type_t nor a specialization of in_place_index_t,
  • is_constructible_v<, T> is true, and
  • the expression FUN(std​::​forward<T>(t)) (with FUN being the above-mentioned set of imaginary functions) is well-formed.
    [Note 2: 
    variant<string, string> v("abc"); is ill-formed, as both alternative types have an equally viable constructor for the argument.
    — end note]
Effects: Initializes *this to hold the alternative type and direct-non-list-initializes the contained value with std​::​forward<T>(t).
Postconditions: holds_alternative<>(*this) is true.
Throws: Any exception thrown by the initialization of the selected alternative .
Remarks: The exception specification is equivalent to is_nothrow_constructible_v<, T>.
If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Constraints:
  • There is exactly one occurrence of T in Types... and
  • is_constructible_v<T, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type T with std​::​forward<Args>(args)....
Postconditions: holds_alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints:
  • There is exactly one occurrence of T in Types... and
  • is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type T with il, std​::​forward<Args>(​args)....
Postconditions: holds_alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Constraints:
  • I is less than sizeof...(Types) and
  • is_constructible_v<, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type with std​::​forward<Args>(args)....
Postconditions: index() is I.
Throws: Any exception thrown by calling the selected constructor of .
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Constraints:
  • I is less than sizeof...(Types) and
  • is_constructible_v<, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type with il, std​::​forward<Args>(​args)....
Postconditions: index() is I.
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

22.6.3.3 Destructor [variant.dtor]

constexpr ~variant();
Effects: If valueless_by_exception() is false, destroys the currently contained value.
Remarks: If is_trivially_destructible_v<> is true for all , then this destructor is trivial.

22.6.3.4 Assignment [variant.assign]

constexpr variant& operator=(const variant& rhs);
Let j be rhs.index().
Effects:
  • If neither *this nor rhs holds a value, there is no effect.
  • Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value.
  • Otherwise, if index() == j, assigns the value contained in rhs to the value contained in *this.
  • Otherwise, if either is_nothrow_copy_constructible_v<> is true or is_nothrow_move_constructible_v<> is false, equivalent to emplace<j>(GET<j>(rhs)).
  • Otherwise, equivalent to operator=(variant(rhs)).
Postconditions: index() == rhs.index().
Returns: *this.
Remarks: This operator is defined as deleted unless is_copy_constructible_v<> && is_copy_assignable_v<> is true for all i.
If is_trivially_copy_constructible_v<> && is_trivially_copy_assignable_v<> && is_trivially_destructible_v<> is true for all i, this assignment operator is trivial.
constexpr variant& operator=(variant&& rhs) noexcept(see below);
Let j be rhs.index().
Constraints: is_move_constructible_v<> && is_move_assignable_v<> is true for all i.
Effects:
  • If neither *this nor rhs holds a value, there is no effect.
  • Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value.
  • Otherwise, if index() == j, assigns GET<j>(std​::​move(rhs)) to the value contained in *this.
  • Otherwise, equivalent to emplace<j>(GET<j>(std​::​move(rhs))).
Returns: *this.
Remarks: If is_trivially_move_constructible_v<> && is_trivially_move_assignable_v<> && is_trivially_destructible_v<> is true for all i, this assignment operator is trivial.
The exception specification is equivalent to is_nothrow_move_constructible_v<> && is_nothrow_move_assignable_v<> for all i.
  • If an exception is thrown during the call to 's move construction (with j being rhs.index()), the variant will hold no value.
  • If an exception is thrown during the call to 's move assignment, the state of the contained value is as defined by the exception safety guarantee of 's move assignment; index() will be j.
template<class T> constexpr variant& operator=(T&& t) noexcept(see below);
Let be a type that is determined as follows: build an imaginary function FUN() for each alternative type for which x[] = {std​::​forward<T>(t)}; is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std​::​forward<T>(​t)) defines the alternative which is the type of the contained value after assignment.
Constraints:
  • is_same_v<remove_cvref_t<T>, variant> is false,
  • is_assignable_v<&, T> && is_constructible_v<, T> is true, and
  • the expression FUN(std​::​forward<T>(t)) (with FUN being the above-mentioned set of imaginary functions) is well-formed.
    [Note 1: 
    variant<string, string> v; v = "abc"; is ill-formed, as both alternative types have an equally viable constructor for the argument.
    — end note]
Effects:
  • If *this holds a , assigns std​::​forward<T>(t) to the value contained in *this.
  • Otherwise, if is_nothrow_constructible_v<, T> || !is_nothrow_move_constructible_v<> is true, equivalent to emplace<j>(std​::​forward<T>(t)).
  • Otherwise, equivalent to emplace<j>((std​::​forward<T>(t))).
Postconditions: holds_alternative<>(*this) is true, with selected by the imaginary function overload resolution described above.
Returns: *this.
Remarks: The exception specification is equivalent to: is_nothrow_assignable_v<T&, T> && is_nothrow_constructible_v<T, T>
  • If an exception is thrown during the assignment of std​::​forward<T>(t) to the value contained in *this, the state of the contained value and t are as defined by the exception safety guarantee of the assignment expression; valueless_by_exception() will be false.
  • If an exception is thrown during the initialization of the contained value, the variant object is permitted to not hold a value.

22.6.3.5 Modifiers [variant.mod]

template<class T, class... Args> constexpr T& emplace(Args&&... args);
Constraints: is_constructible_v<T, Args...> is true, and T occurs exactly once in Types.
Effects: Equivalent to: return emplace<I>(std::forward<Args>(args)...); where I is the zero-based index of T in Types.
template<class T, class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true, and T occurs exactly once in Types.
Effects: Equivalent to: return emplace<I>(il, std::forward<Args>(args)...); where I is the zero-based index of T in Types.
template<size_t I, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Mandates: I < sizeof...(Types).
Constraints: is_constructible_v<, Args...> is true.
Effects: Destroys the currently contained value if valueless_by_exception() is false.
Then direct-non-list-initializes the contained value of type with the arguments std​::​forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.
template<size_t I, class U, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
Mandates: I < sizeof...(Types).
Constraints: is_constructible_v<, initializer_list<U>&, Args...> is true.
Effects: Destroys the currently contained value if valueless_by_exception() is false.
Then direct-non-list-initializes the contained value of type with il, std​::​forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.

22.6.3.6 Value status [variant.status]

constexpr bool valueless_by_exception() const noexcept;
Effects: Returns false if and only if the variant holds a value.
[Note 1: 
It is possible for a variant to hold no value if an exception is thrown during a type-changing assignment or emplacement.
The latter means that even a variant<float, int> can become valueless_by_exception(), for instance by struct S { operator int() { throw 42; }}; variant<float, int> v{12.f}; v.emplace<1>(S());
— end note]
constexpr size_t index() const noexcept;
Effects: If valueless_by_exception() is true, returns variant_npos.
Otherwise, returns the zero-based index of the alternative of the contained value.

22.6.3.7 Swap [variant.swap]

constexpr void swap(variant& rhs) noexcept(see below);
Mandates: is_move_constructible_v<> is true for all i.
Preconditions: Each meets the Cpp17Swappable requirements ([swappable.requirements]).
Effects:
  • If valueless_by_exception() && rhs.valueless_by_exception() no effect.
  • Otherwise, if index() == rhs.index(), calls swap(GET<i>(*this), GET<i>(rhs)) where i is index().
  • Otherwise, exchanges values of rhs and *this.
Throws: If index() == rhs.index(), any exception thrown by swap(GET<i>(*this), GET<i>(rhs)) with i being index().
Otherwise, any exception thrown by the move constructor of or with i being index() and j being rhs.index().
Remarks: If an exception is thrown during the call to function swap(GET<i>(*this), GET<i>(rhs)), the states of the contained values of *this and of rhs are determined by the exception safety guarantee of swap for lvalues of with i being index().
If an exception is thrown during the exchange of the values of *this and rhs, the states of the values of *this and of rhs are determined by the exception safety guarantee of variant's move constructor.
The exception specification is equivalent to the logical and of is_nothrow_move_constructible_v<> && is_nothrow_swappable_v<> for all i.

22.6.4 variant helper classes [variant.helper]

template<class T> struct variant_size;
All specializations of variant_size meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, N> for some N.
template<class T> struct variant_size<const T>;
Let VS denote variant_size<T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, VS​::​value>.
template<class... Types> struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class T> struct variant_alternative<I, const T>;
Let VA denote variant_alternative<I, T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the type add_const_t<VA​::​type>.
variant_alternative<I, variant<Types...>>::type
Mandates: I < sizeof...(Types).
Type: The type .

22.6.5 Value access [variant.get]

template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: true if index() is equal to the zero-based index of T in Types.
template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& GET(variant<Types...>& v); // exposition only template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& GET(variant<Types...>&& v); // exposition only template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& GET(const variant<Types...>& v); // exposition only template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& GET(const variant<Types...>&& v); // exposition only
Mandates: I < sizeof...(Types).
Preconditions: v.index() is I.
Returns: A reference to the object stored in the variant.
template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v); template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Mandates: I < sizeof...(Types).
Effects: If v.index() is I, returns a reference to the object stored in the variant.
Otherwise, throws an exception of type bad_variant_access.
template<class T, class... Types> constexpr T& get(variant<Types...>& v); template<class T, class... Types> constexpr T&& get(variant<Types...>&& v); template<class T, class... Types> constexpr const T& get(const variant<Types...>& v); template<class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
Mandates: The type T occurs exactly once in Types.
Effects: If v holds a value of type T, returns a reference to that value.
Otherwise, throws an exception of type bad_variant_access.
template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>* v) noexcept; template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>* v) noexcept;
Mandates: I < sizeof...(Types).
Returns: A pointer to the value stored in the variant, if v != nullptr and v->index() == I.
Otherwise, returns nullptr.
template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>* v) noexcept; template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>* v) noexcept;
Mandates: The type T occurs exactly once in Types.
Effects: Equivalent to: return get_if<i>(v); with i being the zero-based index of T in Types.

22.6.6 Relational operators [variant.relops]

template<class... Types> constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) == GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), false; otherwise if v.valueless_by_exception(), true; otherwise GET<i>(v) == GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) != GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), true; otherwise if v.valueless_by_exception(), false; otherwise GET<i>(v) != GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) < GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_by_exception(), false; otherwise if v.valueless_by_exception(), true; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise GET<i>(v) < GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) > GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_by_exception(), false; otherwise if w.valueless_by_exception(), true; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise GET<i>(v) > GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) <= GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_by_exception(), true; otherwise if w.valueless_by_exception(), false; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise GET<i>(v) <= GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) >= GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_by_exception(), true; otherwise if v.valueless_by_exception(), false; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise GET<i>(v) >= GET<i>(w) with i being v.index().
template<class... Types> requires (three_way_comparable<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>& v, const variant<Types...>& w);
Effects: Equivalent to: if (v.valueless_by_exception() && w.valueless_by_exception()) return strong_ordering::equal; if (v.valueless_by_exception()) return strong_ordering::less; if (w.valueless_by_exception()) return strong_ordering::greater; if (auto c = v.index() <=> w.index(); c != 0) return c; return GET<i>(v) <=> GET<i>(w); with i being v.index().

22.6.7 Visitation [variant.visit]

template<class Visitor, class... Variants> constexpr see below visit(Visitor&& vis, Variants&&... vars); template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&& vis, Variants&&... vars);
Let as-variant denote the following exposition-only function templates: template<class... Ts> constexpr auto&& as-variant(variant<Ts...>& var) { return var; } template<class... Ts> constexpr auto&& as-variant(const variant<Ts...>& var) { return var; } template<class... Ts> constexpr auto&& as-variant(variant<Ts...>&& var) { return std::move(var); } template<class... Ts> constexpr auto&& as-variant(const variant<Ts...>&& var) { return std::move(var); }
Let n be sizeof...(Variants).
For each , let denote the type
decltype(as-variant(std​::​forward<>())).
Constraints: is a valid type for all .
Let V denote the pack of types .
Let m be a pack of n values of type size_t.
Such a pack is valid if
for all .
For each valid pack m, let e(m) denote the expression: INVOKE(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...) // see [func.require] for the first form and INVOKE<R>(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...) // see [func.require] for the second form.
Mandates: For each valid pack m, e(m) is a valid expression.
All such expressions are of the same type and value category.
Returns: e(m), where m is the pack for which is as-variant(vars).index() for all .
The return type is decltype(e(m)) for the first form.
Throws: bad_variant_access if (as-variant(vars).valueless_by_exception() || ...) is true.
Complexity: For n  ≤ 1, the invocation of the callable object is implemented in constant time, i.e., for , it does not depend on the number of alternative types of .
For , the invocation of the callable object has no complexity requirements.
template<class Self, class Visitor> constexpr decltype(auto) visit(this Self&& self, Visitor&& vis);
Let V be OVERRIDE_REF(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) ([forward]).
Constraints: The call to visit does not use an explicit template-argument-list that begins with a type template-argument.
Effects: Equivalent to: return std​::​visit(std​::​forward<Visitor>(vis), (V)self);
template<class R, class Self, class Visitor> constexpr R visit(this Self&& self, Visitor&& vis);
Let V be OVERRIDE_REF(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) ([forward]).
Effects: Equivalent to: return std​::​visit<R>(std​::​forward<Visitor>(vis), (V)self);

22.6.8 Class monostate [variant.monostate]

struct monostate{};
The class monostate can serve as a first alternative type for a variant to make the variant type default constructible.

22.6.9 monostate relational operators [variant.monostate.relops]

constexpr bool operator==(monostate, monostate) noexcept { return true; } constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; }
[Note 1: 
monostate objects have only a single state; they thus always compare equal.
— end note]

22.6.10 Specialized algorithms [variant.specalg]

template<class... Types> constexpr void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Constraints: is_move_constructible_v<> && is_swappable_v<> is true for all i.
Effects: Equivalent to v.swap(w).
Remarks: The exception specification is equivalent to noexcept(v.swap(w)).

22.6.11 Class bad_variant_access [variant.bad.access]

namespace std { class bad_variant_access : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; }; }
Objects of type bad_variant_access are thrown to report invalid accesses to the value of a variant object.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.6.12 Hash support [variant.hash]

template<class... Types> struct hash<variant<Types...>>;
The specialization hash<variant<Types...>> is enabled ([unord.hash]) if and only if every specialization in hash<remove_const_t<Types>>... is enabled.
The member functions are not guaranteed to be noexcept.
template<> struct hash<monostate>;
The specialization is enabled ([unord.hash]).

22.7 Storage for any type [any]

22.7.1 General [any.general]

Subclause [any] describes components that C++ programs may use to perform operations on objects of a discriminated type.
[Note 1: 
The discriminated type can contain values of different types but does not attempt conversion between them, i.e., 5 is held strictly as an int and is not implicitly convertible either to "5" or to 5.0.
This indifference to interpretation but awareness of type effectively allows safe, generic containers of single values, with no scope for surprises from ambiguous conversions.
— end note]

22.7.2 Header <any> synopsis [any.synop]

namespace std { // [any.bad.any.cast], class bad_any_cast class bad_any_cast; // [any.class], class any class any; // [any.nonmembers], non-member functions void swap(any& x, any& y) noexcept; template<class T, class... Args> any make_any(Args&&... args); template<class T, class U, class... Args> any make_any(initializer_list<U> il, Args&&... args); template<class T> T any_cast(const any& operand); template<class T> T any_cast(any& operand); template<class T> T any_cast(any&& operand); template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept; }

22.7.3 Class bad_any_cast [any.bad.any.cast]

namespace std { class bad_any_cast : public bad_cast { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; }; }
Objects of type bad_any_cast are thrown by a failed any_cast.
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.7.4 Class any [any.class]

22.7.4.1 General [any.class.general]

namespace std { class any { public: // [any.cons], construction and destruction constexpr any() noexcept; any(const any& other); any(any&& other) noexcept; template<class T> any(T&& value); template<class T, class... Args> explicit any(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U>, Args&&...); ~any(); // [any.assign], assignments any& operator=(const any& rhs); any& operator=(any&& rhs) noexcept; template<class T> any& operator=(T&& rhs); // [any.modifiers], modifiers template<class T, class... Args> decay_t<T>& emplace(Args&&...); template<class T, class U, class... Args> decay_t<T>& emplace(initializer_list<U>, Args&&...); void reset() noexcept; void swap(any& rhs) noexcept; // [any.observers], observers bool has_value() const noexcept; const type_info& type() const noexcept; }; }
An object of class any stores an instance of any type that meets the constructor requirements or it has no value, and this is referred to as the state of the class any object.
The stored instance is called the contained value.
Two states are equivalent if either they both have no value, or they both have a value and the contained values are equivalent.
The non-member any_cast functions provide type-safe access to the contained value.
Implementations should avoid the use of dynamically allocated memory for a small contained value.
However, any such small-object optimization shall only be applied to types T for which is_nothrow_move_constructible_v<T> is true.
[Example 1: 
A contained value of type int could be stored in an internal buffer, not in separately-allocated memory.
— end example]

22.7.4.2 Construction and destruction [any.cons]

constexpr any() noexcept;
Postconditions: has_value() is false.
any(const any& other);
Effects: If other.has_value() is false, constructs an object that has no value.
Otherwise, equivalent to any(in_place_type<T>, any_cast<const T&>(other)) where T is the type of the contained value.
Throws: Any exceptions arising from calling the selected constructor for the contained value.
any(any&& other) noexcept;
Effects: If other.has_value() is false, constructs an object that has no value.
Otherwise, constructs an object of type any that contains either the contained value of other, or contains an object of the same type constructed from the contained value of other considering that contained value as an rvalue.
template<class T> any(T&& value);
Let VT be decay_t<T>.
Constraints: VT is not the same type as any, VT is not a specialization of in_place_type_t, and is_copy_constructible_v<VT> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Constructs an object of type any that contains an object of type VT direct-initialized with std​::​forward<T>(value).
Throws: Any exception thrown by the selected constructor of VT.
template<class T, class... Args> explicit any(in_place_type_t<T>, Args&&... args);
Let VT be decay_t<T>.
Constraints: is_copy_constructible_v<VT> is true and is_constructible_v<VT, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Direct-non-list-initializes the contained value of type VT with std​::​forward<Args>(args)....
Postconditions: *this contains a value of type VT.
Throws: Any exception thrown by the selected constructor of VT.
template<class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Let VT be decay_t<T>.
Constraints: is_copy_constructible_v<VT> is true and is_constructible_v<VT, initializer_list<U>&, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Direct-non-list-initializes the contained value of type VT with il, std​::​forward<Args>(​args)....
Postconditions: *this contains a value.
Throws: Any exception thrown by the selected constructor of VT.
~any();
Effects: As if by reset().

22.7.4.3 Assignment [any.assign]

any& operator=(const any& rhs);
Effects: As if by any(rhs).swap(*this).
No effects if an exception is thrown.
Returns: *this.
Throws: Any exceptions arising from the copy constructor for the contained value.
any& operator=(any&& rhs) noexcept;
Effects: As if by any(std​::​move(rhs)).swap(*this).
Postconditions: The state of *this is equivalent to the original state of rhs.
Returns: *this.
template<class T> any& operator=(T&& rhs);
Let VT be decay_t<T>.
Constraints: VT is not the same type as any and is_copy_constructible_v<VT> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Constructs an object tmp of type any that contains an object of type VT direct-initialized with std​::​forward<T>(rhs), and tmp.swap(*this).
No effects if an exception is thrown.
Returns: *this.
Throws: Any exception thrown by the selected constructor of VT.

22.7.4.4 Modifiers [any.modifiers]

template<class T, class... Args> decay_t<T>& emplace(Args&&... args);
Let VT be decay_t<T>.
Constraints: is_copy_constructible_v<VT> is true and is_constructible_v<VT, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Calls reset().
Then direct-non-list-initializes the contained value of type VT with std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of VT.
Remarks: If an exception is thrown during the call to VT's constructor, *this does not contain a value, and any previously contained value has been destroyed.
template<class T, class U, class... Args> decay_t<T>& emplace(initializer_list<U> il, Args&&... args);
Let VT be decay_t<T>.
Constraints: is_copy_constructible_v<VT> is true and is_constructible_v<VT, initializer_list<U>&, Args...> is true.
Preconditions: VT meets the Cpp17CopyConstructible requirements.
Effects: Calls reset().
Then direct-non-list-initializes the contained value of type VT with il, std​::​forward<Args>(args)....
Postconditions: *this contains a value.
Returns: A reference to the new contained value.
Throws: Any exception thrown by the selected constructor of VT.
Remarks: If an exception is thrown during the call to VT's constructor, *this does not contain a value, and any previously contained value has been destroyed.
void reset() noexcept;
Effects: If has_value() is true, destroys the contained value.
Postconditions: has_value() is false.
void swap(any& rhs) noexcept;
Effects: Exchanges the states of *this and rhs.

22.7.4.5 Observers [any.observers]

bool has_value() const noexcept;
Returns: true if *this contains an object, otherwise false.
const type_info& type() const noexcept;
Returns: typeid(T) if *this has a contained value of type T, otherwise typeid(void).
[Note 1: 
Useful for querying against types known either at compile time or only at runtime.
— end note]

22.7.5 Non-member functions [any.nonmembers]

void swap(any& x, any& y) noexcept;
Effects: Equivalent to x.swap(y).
template<class T, class... Args> any make_any(Args&&... args);
Effects: Equivalent to: return any(in_place_type<T>, std​::​forward<Args>(args)...);
template<class T, class U, class... Args> any make_any(initializer_list<U> il, Args&&... args);
Effects: Equivalent to: return any(in_place_type<T>, il, std​::​forward<Args>(args)...);
template<class T> T any_cast(const any& operand); template<class T> T any_cast(any& operand); template<class T> T any_cast(any&& operand);
Let U be the type remove_cvref_t<T>.
Mandates: For the first overload, is_constructible_v<T, const U&> is true.
For the second overload, is_constructible_v<T, U&> is true.
For the third overload, is_constructible_v<T, U> is true.
Returns: For the first and second overload, static_cast<T>(*any_cast<U>(&operand)).
For the third overload, static_cast<T>(std​::​move(*any_cast<U>(&operand))).
Throws: bad_any_cast if operand.type() != typeid(remove_reference_t<T>).
[Example 1: any x(5); // x holds int assert(any_cast<int>(x) == 5); // cast to value any_cast<int&>(x) = 10; // cast to reference assert(any_cast<int>(x) == 10); x = "Meow"; // x holds const char* assert(strcmp(any_cast<const char*>(x), "Meow") == 0); any_cast<const char*&>(x) = "Harry"; assert(strcmp(any_cast<const char*>(x), "Harry") == 0); x = string("Meow"); // x holds string string s, s2("Jane"); s = move(any_cast<string&>(x)); // move from any assert(s == "Meow"); any_cast<string&>(x) = move(s2); // move to any assert(any_cast<const string&>(x) == "Jane"); string cat("Meow"); const any y(cat); // const y holds string assert(any_cast<const string&>(y) == cat); any_cast<string&>(y); // error: cannot any_cast away const — end example]
template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept;
Mandates: is_void_v<T> is false.
Returns: If operand != nullptr && operand->type() == typeid(T) is true, a pointer to the object contained by operand; otherwise, nullptr.
[Example 2: bool is_string(const any& operand) { return any_cast<string>(&operand) != nullptr; } — end example]

22.8 Expected objects [expected]

22.8.1 General [expected.general]

Subclause [expected] describes the class template expected that represents expected objects.
An expected<T, E> object holds an object of type T or an object of type E and manages the lifetime of the contained objects.

22.8.2 Header <expected> synopsis [expected.syn]

// mostly freestanding namespace std { // [expected.unexpected], class template unexpected template<class E> class unexpected; // [expected.bad], class template bad_expected_access template<class E> class bad_expected_access; // [expected.bad.void], specialization for void template<> class bad_expected_access<void>; // in-place construction of unexpected values struct unexpect_t { explicit unexpect_t() = default; }; inline constexpr unexpect_t unexpect{}; // [expected.expected], class template expected template<class T, class E> class expected; // partially freestanding // [expected.void], partial specialization of expected for void types template<class T, class E> requires is_void_v<T> class expected<T, E>; // partially freestanding }

22.8.3 Class template unexpected [expected.unexpected]

22.8.3.1 General [expected.un.general]

Subclause [expected.unexpected] describes the class template unexpected that represents unexpected objects stored in expected objects.
namespace std { template<class E> class unexpected { public: // [expected.un.cons], constructors constexpr unexpected(const unexpected&) = default; constexpr unexpected(unexpected&&) = default; template<class Err = E> constexpr explicit unexpected(Err&&); template<class... Args> constexpr explicit unexpected(in_place_t, Args&&...); template<class U, class... Args> constexpr explicit unexpected(in_place_t, initializer_list<U>, Args&&...); constexpr unexpected& operator=(const unexpected&) = default; constexpr unexpected& operator=(unexpected&&) = default; constexpr const E& error() const & noexcept; constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; constexpr void swap(unexpected& other) noexcept(see below); template<class E2> friend constexpr bool operator==(const unexpected&, const unexpected<E2>&); friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y))); private: E unex; // exposition only }; template<class E> unexpected(E) -> unexpected<E>; }
A program that instantiates the definition of unexpected for a non-object type, an array type, a specialization of unexpected, or a cv-qualified type is ill-formed.

22.8.3.2 Constructors [expected.un.cons]

template<class Err = E> constexpr explicit unexpected(Err&& e);
Constraints:
  • is_same_v<remove_cvref_t<Err>, unexpected> is false; and
  • is_same_v<remove_cvref_t<Err>, in_place_t> is false; and
  • is_constructible_v<E, Err> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<Err>(e).
Throws: Any exception thrown by the initialization of unex.
template<class... Args> constexpr explicit unexpected(in_place_t, Args&&... args);
Constraints: is_constructible_v<E, Args...> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of unex.
template<class U, class... Args> constexpr explicit unexpected(in_place_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes unex with il, std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of unex.

22.8.3.3 Observers [expected.un.obs]

constexpr const E& error() const & noexcept; constexpr E& error() & noexcept;
Returns: unex.
constexpr E&& error() && noexcept; constexpr const E&& error() const && noexcept;
Returns: std​::​move(unex).

22.8.3.4 Swap [expected.un.swap]

constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);
Mandates: is_swappable_v<E> is true.
Effects: Equivalent to: using std​::​swap; swap(unex, other.unex);
friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v<E> is true.
Effects: Equivalent to x.swap(y).

22.8.3.5 Equality operator [expected.un.eq]

template<class E2> friend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y);
Mandates: The expression x.error() == y.error() is well-formed and its result is convertible to bool.
Returns: x.error() == y.error().

22.8.4 Class template bad_expected_access [expected.bad]

namespace std { template<class E> class bad_expected_access : public bad_expected_access<void> { 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 unex; // exposition only }; }
The class template 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 expected<T, E> object for which has_value() is false.
explicit bad_expected_access(E e);
Effects: Initializes unex with std​::​move(e).
const E& error() const & noexcept; E& error() & noexcept;
Returns: unex.
E&& error() && noexcept; const E&& error() const && noexcept;
Returns: std​::​move(unex).
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.8.5 Class template specialization bad_expected_access<void> [expected.bad.void]

namespace std { template<> class bad_expected_access<void> : public exception { protected: bad_expected_access() noexcept; bad_expected_access(const bad_expected_access&) noexcept; bad_expected_access(bad_expected_access&&) noexcept; bad_expected_access& operator=(const bad_expected_access& noexcept); bad_expected_access& operator=(bad_expected_access&&) noexcept; ~bad_expected_access(); public: const char* what() const noexcept override; }; }
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.8.6 Class template expected [expected.expected]

22.8.6.1 General [expected.object.general]

namespace std { template<class T, class E> class expected { public: using value_type = T; using error_type = E; using unexpected_type = unexpected<E>; template<class U> using rebind = expected<U, error_type>; // [expected.object.cons], constructors constexpr expected(); constexpr expected(const expected&); constexpr expected(expected&&) noexcept(see below); template<class U, class G> constexpr explicit(see below) expected(const expected<U, G>&); template<class U, class G> constexpr explicit(see below) expected(expected<U, G>&&); template<class U = remove_cv_t<T>> constexpr explicit(see below) expected(U&& v); template<class G> constexpr explicit(see below) expected(const unexpected<G>&); template<class G> constexpr explicit(see below) expected(unexpected<G>&&); template<class... Args> constexpr explicit expected(in_place_t, Args&&...); template<class U, class... Args> constexpr explicit expected(in_place_t, initializer_list<U>, Args&&...); template<class... Args> constexpr explicit expected(unexpect_t, Args&&...); template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...); // [expected.object.dtor], destructor constexpr ~expected(); // [expected.object.assign], assignment constexpr expected& operator=(const expected&); constexpr expected& operator=(expected&&) noexcept(see below); template<class U = remove_cv_t<T>> constexpr expected& operator=(U&&); template<class G> constexpr expected& operator=(const unexpected<G>&); template<class G> constexpr expected& operator=(unexpected<G>&&); template<class... Args> constexpr T& emplace(Args&&...) noexcept; template<class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...) noexcept; // [expected.object.swap], swap constexpr void swap(expected&) noexcept(see below); friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // [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 &; // freestanding-deleted constexpr T& value() &; // freestanding-deleted constexpr const T&& value() const &&; // freestanding-deleted constexpr T&& value() &&; // freestanding-deleted constexpr const E& error() const & noexcept; constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &; template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&; template<class G = E> constexpr E error_or(G&&) const &; template<class G = E> constexpr E error_or(G&&) &&; // [expected.object.monadic], monadic operations template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &; template<class F> constexpr auto and_then(F&& f) const &&; template<class F> constexpr auto or_else(F&& f) &; template<class F> constexpr auto or_else(F&& f) &&; template<class F> constexpr auto or_else(F&& f) const &; template<class F> constexpr auto or_else(F&& f) const &&; template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &; template<class F> constexpr auto transform(F&& f) const &&; template<class F> constexpr auto transform_error(F&& f) &; template<class F> constexpr auto transform_error(F&& f) &&; template<class F> constexpr auto transform_error(F&& f) const &; template<class F> constexpr auto transform_error(F&& f) const &&; // [expected.object.eq], equality operators template<class T2, class E2> requires (!is_void_v<T2>) friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y); template<class T2> friend constexpr bool operator==(const expected&, const T2&); template<class E2> friend constexpr bool operator==(const expected&, const unexpected<E2>&); private: bool has_val; // exposition only union { T val; // exposition only E unex; // exposition only }; }; }
Any object of type expected<T, E> either contains a value of type T or a value of type E nested within ([intro.object]) it.
Member has_val indicates whether the expected<T, E> object contains an object of type T.
A type T is a valid value type for expected, if remove_cv_t<T> is void or a complete non-array object type that is not in_place_t, unexpect_t, or a specialization of unexpected.
A program which instantiates class template expected<T, E> with an argument T that is not a valid value type for expected is ill-formed.
A program that instantiates the definition of the template expected<T, E> with a type for the E parameter that is not a valid template argument for unexpected is ill-formed.
When T is not cv void, it shall meet the Cpp17Destructible requirements (Table 35).
E shall meet the Cpp17Destructible requirements.

22.8.6.2 Constructors [expected.object.cons]

The exposition-only variable template converts-from-any-cvref defined in [optional.ctor] is used by some constructors for expected.
constexpr expected();
Constraints: is_default_constructible_v<T> is true.
Effects: Value-initializes val.
Postconditions: has_value() is true.
Throws: Any exception thrown by the initialization of val.
constexpr expected(const expected& rhs);
Effects: If rhs.has_value() is true, direct-non-list-initializes val with *rhs.
Otherwise, direct-non-list-initializes unex with rhs.error().
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the initialization of val or unex.
Remarks: This constructor is defined as deleted unless
  • is_copy_constructible_v<T> is true and
  • is_copy_constructible_v<E> is true.
This constructor is trivial if
  • is_trivially_copy_constructible_v<T> is true and
  • is_trivially_copy_constructible_v<E> is true.
constexpr expected(expected&& rhs) noexcept(see below);
Constraints:
  • is_move_constructible_v<T> is true and
  • is_move_constructible_v<E> is true.
Effects: If rhs.has_value() is true, direct-non-list-initializes val with std​::​move(*rhs).
Otherwise, direct-non-list-initializes unex with std​::​move(rhs.error()).
Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
Throws: Any exception thrown by the initialization of val or unex.
Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.
This constructor is trivial if
  • is_trivially_move_constructible_v<T> is true and
  • is_trivially_move_constructible_v<E> is true.
template<class U, class G> constexpr explicit(see below) expected(const expected<U, G>& rhs); template<class U, class G> constexpr explicit(see below) expected(expected<U, G>&& rhs);
Let:
  • UF be const U& for the first overload and U for the second overload.
  • GF be const G& for the first overload and G for the second overload.
Constraints:
  • is_constructible_v<T, UF> is true; and
  • is_constructible_v<E, GF> is true; and
  • if T is not cv bool, converts-from-any-cvref<T, expected<U, G>> is false; and
  • is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
  • is_constructible_v<unexpected<E>, expected<U, G>> is false; and
  • is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
  • is_constructible_v<unexpected<E>, const expected<U, G>> is false.
Effects: If rhs.has_value(), direct-non-list-initializes val with std​::​forward<UF>(*rhs).
Otherwise, direct-non-list-initializes unex with std​::​forward<GF>(rhs.error()).
Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
Throws: Any exception thrown by the initialization of val or unex.
Remarks: The expression inside explicit is equivalent to !is_convertible_v<UF, T> || !is_convertible_v<GF, E>.
template<class U = remove_cv_t<T>> constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
Constraints:
  • is_same_v<remove_cvref_t<U>, in_place_t> is false; and
  • is_same_v<expected, remove_cvref_t<U>> is false; and
  • remove_cvref_t<U> is not a specialization of unexpected; and
  • is_constructible_v<T, U> is true; and
  • if T is cv bool, remove_cvref_t<U> is not a specialization of expected.
Effects: Direct-non-list-initializes val with std​::​forward<U>(v).
Postconditions: has_value() is true.
Throws: Any exception thrown by the initialization of val.
template<class G> constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e); template<class G> constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
Let GF be const G& for the first overload and G for the second overload.
Constraints: is_constructible_v<E, GF> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<GF>(e.error()).
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.
template<class... Args> constexpr explicit expected(in_place_t, Args&&... args);
Constraints: is_constructible_v<T, Args...> is true.
Effects: Direct-non-list-initializes val with std​::​forward<Args>(args)....
Postconditions: has_value() is true.
Throws: Any exception thrown by the initialization of val.
template<class U, class... Args> constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes val with il, std​::​forward<Args>(args)....
Postconditions: has_value() is true.
Throws: Any exception thrown by the initialization of val.
template<class... Args> constexpr explicit expected(unexpect_t, Args&&... args);
Constraints: is_constructible_v<E, Args...> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<Args>(args)....
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.
template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes unex with il, std​::​forward<Args>(args)....
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.

22.8.6.3 Destructor [expected.object.dtor]

constexpr ~expected();
Effects: If has_value() is true, destroys val, otherwise destroys unex.
Remarks: If is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.

22.8.6.4 Assignment [expected.object.assign]

This subclause makes use of the following exposition-only function template: template<class T, class U, class... Args> constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) { // exposition only if constexpr (is_nothrow_constructible_v<T, Args...>) { destroy_at(addressof(oldval)); construct_at(addressof(newval), std::forward<Args>(args)...); } else if constexpr (is_nothrow_move_constructible_v<T>) { T tmp(std::forward<Args>(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>(args)...); } catch (...) { construct_at(addressof(oldval), std::move(tmp)); throw; } } }
constexpr expected& operator=(const expected& rhs);
Effects:
  • If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs.
  • Otherwise, if this->has_value() is true, equivalent to: reinit-expected(unex, val, rhs.error())
  • Otherwise, if rhs.has_value() is true, equivalent to: reinit-expected(val, unex, *rhs)
  • Otherwise, equivalent to unex = rhs.error().
Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;
Returns: *this.
Remarks: This operator is defined as deleted unless:
  • is_copy_assignable_v<T> is true and
  • is_copy_constructible_v<T> is true and
  • is_copy_assignable_v<E> is true and
  • is_copy_constructible_v<E> is true and
  • is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
constexpr expected& operator=(expected&& rhs) noexcept(see below);
Constraints:
  • is_move_constructible_v<T> is true and
  • is_move_assignable_v<T> is true and
  • is_move_constructible_v<E> is true and
  • is_move_assignable_v<E> is true and
  • is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
Effects:
  • If this->has_value() && rhs.has_value() is true, equivalent to val = std​::​move(*rhs).
  • Otherwise, if this->has_value() is true, equivalent to: reinit-expected(unex, val, std::move(rhs.error()))
  • Otherwise, if rhs.has_value() is true, equivalent to: reinit-expected(val, unex, std::move(*rhs))
  • Otherwise, equivalent to unex = std​::​move(rhs.error()).
Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;
Returns: *this.
Remarks: The exception specification is equivalent to: is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
template<class U = remove_cv_t<T>> constexpr expected& operator=(U&& v);
Constraints:
  • is_same_v<expected, remove_cvref_t<U>> is false; and
  • remove_cvref_t<U> is not a specialization of unexpected; and
  • is_constructible_v<T, U> is true; and
  • is_assignable_v<T&, U> is true; and
  • is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||
    is_nothrow_move_constructible_v<E>
    is true.
Effects:
  • If has_value() is true, equivalent to: val = std​::​forward<U>(v);
  • Otherwise, equivalent to: reinit-expected(val, unex, std::forward<U>(v)); has_val = true;
Returns: *this.
template<class G> constexpr expected& operator=(const unexpected<G>& e); template<class G> constexpr expected& operator=(unexpected<G>&& e);
Let GF be const G& for the first overload and G for the second overload.
Constraints:
  • is_constructible_v<E, GF> is true; and
  • is_assignable_v<E&, GF> is true; and
  • is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
    is_nothrow_move_constructible_v<E>
    is true.
Effects:
  • If has_value() is true, equivalent to: reinit-expected(unex, val, std::forward<GF>(e.error())); has_val = false;
  • Otherwise, equivalent to: unex = std​::​forward<GF>(e.error());
Returns: *this.
template<class... Args> constexpr T& emplace(Args&&... args) noexcept;
Constraints: is_nothrow_constructible_v<T, Args...> is true.
Effects: Equivalent to: if (has_value()) { destroy_at(addressof(val)); } else { destroy_at(addressof(unex)); has_val = true; } return *construct_at(addressof(val), std::forward<Args>(args)...);
template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
Constraints: is_nothrow_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Equivalent to: if (has_value()) { destroy_at(addressof(val)); } else { destroy_at(addressof(unex)); has_val = true; } return *construct_at(addressof(val), il, std::forward<Args>(args)...);

22.8.6.5 Swap [expected.object.swap]

constexpr void swap(expected& rhs) noexcept(see below);
Constraints:
  • is_swappable_v<T> is true and
  • is_swappable_v<E> is true and
  • is_move_constructible_v<T> && is_move_constructible_v<E> is true, and
  • is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
Effects: See Table 67.
Table 67swap(expected&) effects [tab:expected.object.swap]
this->has_value()
!this->has_value()
rhs.has_value()
equivalent to: using std​::​swap; swap(val, rhs.val);
calls rhs.swap(*this)
!rhs.has_value()
see below
equivalent to: using std​::​swap; swap(unex, rhs.unex);
For the case where rhs.has_value() is false and this->has_value() is true, equivalent to: if constexpr (is_nothrow_move_constructible_v<E>) { E tmp(std::move(rhs.unex)); destroy_at(addressof(rhs.unex)); try { construct_at(addressof(rhs.val), std::move(val)); destroy_at(addressof(val)); construct_at(addressof(unex), std::move(tmp)); } catch(...) { construct_at(addressof(rhs.unex), std::move(tmp)); throw; } } else { T tmp(std::move(val)); destroy_at(addressof(val)); try { construct_at(addressof(unex), std::move(rhs.unex)); destroy_at(addressof(rhs.unex)); construct_at(addressof(rhs.val), std::move(tmp)); } catch (...) { construct_at(addressof(val), std::move(tmp)); throw; } } has_val = false; rhs.has_val = true;
Throws: Any exception thrown by the expressions in the Effects.
Remarks: The exception specification is equivalent to: is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to x.swap(y).

22.8.6.6 Observers [expected.object.obs]

constexpr const T* operator->() const noexcept; constexpr T* operator->() noexcept;
Preconditions: has_value() is true.
Returns: addressof(val).
constexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept;
Preconditions: has_value() is true.
Returns: val.
constexpr T&& operator*() && noexcept; constexpr const T&& operator*() const && noexcept;
Preconditions: has_value() is true.
Returns: std​::​move(val).
constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept;
Returns: has_val.
constexpr const T& value() const &; constexpr T& value() &;
Mandates: is_copy_constructible_v<E> is true.
Returns: val, if has_value() is true.
Throws: bad_expected_access(as_const(error())) if has_value() is false.
constexpr T&& value() &&; constexpr const T&& value() const &&;
Mandates: is_copy_constructible_v<E> is true and is_constructible_v<E, decltype(std​::​move(error()))> is true.
Returns: std​::​move(val), if has_value() is true.
Throws: bad_expected_access(std​::​move(error())) if has_value() is false.
constexpr const E& error() const & noexcept; constexpr E& error() & noexcept;
Preconditions: has_value() is false.
Returns: unex.
constexpr E&& error() && noexcept; constexpr const E&& error() const && noexcept;
Preconditions: has_value() is false.
Returns: std​::​move(unex).
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
Mandates: is_copy_constructible_v<T> is true and is_convertible_v<U, T> is true.
Returns: has_value() ? **this : static_cast<T>(std​::​forward<U>(v)).
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
Mandates: is_move_constructible_v<T> is true and is_convertible_v<U, T> is true.
Returns: has_value() ? std​::​move(**this) : static_cast<T>(std​::​forward<U>(v)).
template<class G = E> constexpr E error_or(G&& e) const &;
Mandates: is_copy_constructible_v<E> is true and is_convertible_v<G, E> is true.
Returns: std​::​forward<G>(e) if has_value() is true, error() otherwise.
template<class G = E> constexpr E error_or(G&& e) &&;
Mandates: is_move_constructible_v<E> is true and is_convertible_v<G, E> is true.
Returns: std​::​forward<G>(e) if has_value() is true, std​::​move(error()) otherwise.

22.8.6.7 Monadic operations [expected.object.monadic]

template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) const &;
Let U be remove_cvref_t<invoke_result_t<F, decltype((val))>>.
Constraints: is_constructible_v<E, decltype(error())> is true.
Mandates: U is a specialization of expected and is_same_v<U​::​error_type, E> is true.
Effects: Equivalent to: if (has_value()) return invoke(std::forward<F>(f), val); else return U(unexpect, error());
template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &&;
Let U be remove_cvref_t<invoke_result_t<F, decltype(std​::​move(val))>>.
Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.
Mandates: U is a specialization of expected and is_same_v<U​::​error_type, E> is true.
Effects: Equivalent to: if (has_value()) return invoke(std::forward<F>(f), std::move(val)); else return U(unexpect, std::move(error()));
template<class F> constexpr auto or_else(F&& f) &; template<class F> constexpr auto or_else(F&& f) const &;
Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>.
Constraints: is_constructible_v<T, decltype((val))> is true.
Mandates: G is a specialization of expected and is_same_v<G​::​value_type, T> is true.
Effects: Equivalent to: if (has_value()) return G(in_place, val); else return invoke(std::forward<F>(f), error());
template<class F> constexpr auto or_else(F&& f) &&; template<class F> constexpr auto or_else(F&& f) const &&;
Let G be remove_cvref_t<invoke_result_t<F, decltype(std​::​move(error()))>>.
Constraints: is_constructible_v<T, decltype(std​::​move(val))> is true.
Mandates: G is a specialization of expected and is_same_v<G​::​value_type, T> is true.
Effects: Equivalent to: if (has_value()) return G(in_place, std::move(val)); else return invoke(std::forward<F>(f), std::move(error()));
template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) const &;
Let U be remove_cv_t<invoke_result_t<F, decltype((val))>>.
Constraints: is_constructible_v<E, decltype(error())> is true.
Mandates: U is a valid value type for expected.
If is_void_v<U> is false, the declaration U u(invoke(std::forward<F>(f), val)); is well-formed.
Effects:
  • If has_value() is false, returns expected<U, E>(unexpect, error()).
  • Otherwise, if is_void_v<U> is false, returns an expected<U, E> object whose has_val member is true and val member is direct-non-list-initialized with invoke(std​::​forward<F>(f), val).
  • Otherwise, evaluates invoke(std​::​forward<F>(f), val) and then returns expected<U, E>().
template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &&;
Let U be remove_cv_t<invoke_result_t<F, decltype(std​::​move(val))>>.
Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.
Mandates: U is a valid value type for expected.
If is_void_v<U> is false, the declaration U u(invoke(std::forward<F>(f), std::move(val))); is well-formed.
Effects:
  • If has_value() is false, returns expected<U, E>(unexpect, std​::​move(error())).
  • Otherwise, if is_void_v<U> is false, returns an expected<U, E> object whose has_val member is true and val member is direct-non-list-initialized with invoke(std​::​forward<F>(f), std​::​move(val)).
  • Otherwise, evaluates invoke(std​::​forward<F>(f), std​::​move(val)) and then returns expected<U, E>().
template<class F> constexpr auto transform_error(F&& f) &; template<class F> constexpr auto transform_error(F&& f) const &;
Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>.
Constraints: is_constructible_v<T, decltype((val))> is true.
Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declaration G g(invoke(std::forward<F>(f), error())); is well-formed.
Returns: If has_value() is true, expected<T, G>(in_place, val); otherwise, an expected<T, G> object whose has_val member is false and unex member is direct-non-list-initialized with invoke(std​::​forward<F>(f), error()).
template<class F> constexpr auto transform_error(F&& f) &&; template<class F> constexpr auto transform_error(F&& f) const &&;
Let G be remove_cv_t<invoke_result_t<F, decltype(std​::​move(error()))>>.
Constraints: is_constructible_v<T, decltype(std​::​move(val))> is true.
Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declaration G g(invoke(std::forward<F>(f), std::move(error()))); is well-formed.
Returns: If has_value() is true, expected<T, G>(in_place, std​::​move(val)); otherwise, an expected<T, G> object whose has_val member is false and unex member is direct-non-list-initialized with invoke(std​::​forward<F>(f), std​::​move(error())).

22.8.6.8 Equality operators [expected.object.eq]

template<class T2, class E2> requires (!is_void_v<T2>) friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
Constraints: The expressions *x == *y and x.error() == y.error() are well-formed and their results are convertible to bool.
Returns: If x.has_value() does not equal y.has_value(), false; otherwise if x.has_value() is true, *x == *y; otherwise x.error() == y.error().
template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
Constraints: T2 is not a specialization of expected.
The expression *x == v is well-formed and its result is convertible to bool.
[Note 1:  — end note]
Returns: x.has_value() && static_cast<bool>(*x == v).
template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
Constraints: The expression x.error() == e.error() is well-formed and its result is convertible to bool.
Returns: !x.has_value() && static_cast<bool>(x.error() == e.error()).

22.8.7 Partial specialization of expected for void types [expected.void]

22.8.7.1 General [expected.void.general]

template<class T, class E> requires is_void_v<T> class expected<T, E> { public: using value_type = T; using error_type = E; using unexpected_type = unexpected<E>; template<class U> using rebind = expected<U, error_type>; // [expected.void.cons], constructors constexpr expected() noexcept; constexpr expected(const expected&); constexpr expected(expected&&) noexcept(see below); template<class U, class G> constexpr explicit(see below) expected(const expected<U, G>&); template<class U, class G> constexpr explicit(see below) expected(expected<U, G>&&); template<class G> constexpr explicit(see below) expected(const unexpected<G>&); template<class G> constexpr explicit(see below) expected(unexpected<G>&&); constexpr explicit expected(in_place_t) noexcept; template<class... Args> constexpr explicit expected(unexpect_t, Args&&...); template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...); // [expected.void.dtor], destructor constexpr ~expected(); // [expected.void.assign], assignment constexpr expected& operator=(const expected&); constexpr expected& operator=(expected&&) noexcept(see below); template<class G> constexpr expected& operator=(const unexpected<G>&); template<class G> constexpr expected& operator=(unexpected<G>&&); constexpr void emplace() noexcept; // [expected.void.swap], swap constexpr void swap(expected&) noexcept(see below); friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y))); // [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 &; // freestanding-deleted constexpr void value() &&; // freestanding-deleted constexpr const E& error() const & noexcept; constexpr E& error() & noexcept; constexpr const E&& error() const && noexcept; constexpr E&& error() && noexcept; template<class G = E> constexpr E error_or(G&&) const &; template<class G = E> constexpr E error_or(G&&) &&; // [expected.void.monadic], monadic operations template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &; template<class F> constexpr auto and_then(F&& f) const &&; template<class F> constexpr auto or_else(F&& f) &; template<class F> constexpr auto or_else(F&& f) &&; template<class F> constexpr auto or_else(F&& f) const &; template<class F> constexpr auto or_else(F&& f) const &&; template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &; template<class F> constexpr auto transform(F&& f) const &&; template<class F> constexpr auto transform_error(F&& f) &; template<class F> constexpr auto transform_error(F&& f) &&; template<class F> constexpr auto transform_error(F&& f) const &; template<class F> constexpr auto transform_error(F&& f) const &&; // [expected.void.eq], equality operators template<class T2, class E2> requires is_void_v<T2> friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y); template<class E2> friend constexpr bool operator==(const expected&, const unexpected<E2>&); private: bool has_val; // exposition only union { E unex; // exposition only }; };
Any object of type expected<T, E> either represents a value of type T, or contains a value of type E nested within ([intro.object]) it.
Member has_val indicates whether the expected<T, E> object represents a value of type T.
A program that instantiates the definition of the template expected<T, E> with a type for the E parameter that is not a valid template argument for unexpected is ill-formed.
E shall meet the requirements of Cpp17Destructible (Table 35).

22.8.7.2 Constructors [expected.void.cons]

constexpr expected() noexcept;
Postconditions: has_value() is true.
constexpr expected(const expected& rhs);
Effects: If rhs.has_value() is false, direct-non-list-initializes unex with rhs.error().
Postconditions: rhs.has_value() == this->has_value().
Throws: Any exception thrown by the initialization of unex.
Remarks: This constructor is defined as deleted unless is_copy_constructible_v<E> is true.
This constructor is trivial if is_trivially_copy_constructible_v<E> is true.
constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v<E>);
Constraints: is_move_constructible_v<E> is true.
Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std​::​move(rhs.error()).
Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
Throws: Any exception thrown by the initialization of unex.
Remarks: This constructor is trivial if is_trivially_move_constructible_v<E> is true.
template<class U, class G> constexpr explicit(!is_convertible_v<const G&, E>) expected(const expected<U, G>& rhs); template<class U, class G> constexpr explicit(!is_convertible_v<G, E>) expected(expected<U, G>&& rhs);
Let GF be const G& for the first overload and G for the second overload.
Constraints:
  • is_void_v<U> is true; and
  • is_constructible_v<E, GF> is true; and
  • is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
  • is_constructible_v<unexpected<E>, expected<U, G>> is false; and
  • is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
  • is_constructible_v<unexpected<E>, const expected<U, G>> is false.
Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std​::​forward<GF>(rhs.error()).
Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
Throws: Any exception thrown by the initialization of unex.
template<class G> constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e); template<class G> constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
Let GF be const G& for the first overload and G for the second overload.
Constraints: is_constructible_v<E, GF> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<GF>(e.error()).
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.
constexpr explicit expected(in_place_t) noexcept;
Postconditions: has_value() is true.
template<class... Args> constexpr explicit expected(unexpect_t, Args&&... args);
Constraints: is_constructible_v<E, Args...> is true.
Effects: Direct-non-list-initializes unex with std​::​forward<Args>(args)....
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.
template<class U, class... Args> constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes unex with il, std​::​forward<Args>(args)....
Postconditions: has_value() is false.
Throws: Any exception thrown by the initialization of unex.

22.8.7.3 Destructor [expected.void.dtor]

constexpr ~expected();
Effects: If has_value() is false, destroys unex.
Remarks: If is_trivially_destructible_v<E> is true, then this destructor is a trivial destructor.

22.8.7.4 Assignment [expected.void.assign]

constexpr expected& operator=(const expected& rhs);
Effects:
  • If this->has_value() && rhs.has_value() is true, no effects.
  • Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
  • Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
  • Otherwise, equivalent to unex = rhs.error().
Returns: *this.
Remarks: This operator is defined as deleted unless is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true.
constexpr expected& operator=(expected&& rhs) noexcept(see below);
Constraints: is_move_constructible_v<E> is true and is_move_assignable_v<E> is true.
Effects:
  • If this->has_value() && rhs.has_value() is true, no effects.
  • Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), std::move(rhs.unex)); has_val = false;
  • Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
  • Otherwise, equivalent to unex = std​::​move(rhs.error()).
Returns: *this.
Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>.
template<class G> constexpr expected& operator=(const unexpected<G>& e); template<class G> constexpr expected& operator=(unexpected<G>&& e);
Let GF be const G& for the first overload and G for the second overload.
Constraints: is_constructible_v<E, GF> is true and is_assignable_v<E&, GF> is true.
Effects:
  • If has_value() is true, equivalent to: construct_at(addressof(unex), std::forward<GF>(e.error())); has_val = false;
  • Otherwise, equivalent to: unex = std​::​forward<GF>(e.error());
Returns: *this.
constexpr void emplace() noexcept;
Effects: If has_value() is false, destroys unex and sets has_val to true.

22.8.7.5 Swap [expected.void.swap]

constexpr void swap(expected& rhs) noexcept(see below);
Constraints: is_swappable_v<E> is true and is_move_constructible_v<E> is true.
Effects: See Table 68.
Table 68swap(expected&) effects [tab:expected.void.swap]
this->has_value()
!this->has_value()
rhs.has_value()
no effects
calls rhs.swap(*this)
!rhs.has_value()
see below
equivalent to: using std​::​swap; swap(unex, rhs.unex);
For the case where rhs.has_value() is false and this->has_value() is true, equivalent to: construct_at(addressof(unex), std::move(rhs.unex)); destroy_at(addressof(rhs.unex)); has_val = false; rhs.has_val = true;
Throws: Any exception thrown by the expressions in the Effects.
Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>.
friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to x.swap(y).

22.8.7.6 Observers [expected.void.obs]

constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept;
Returns: has_val.
constexpr void operator*() const noexcept;
Preconditions: has_value() is true.
constexpr void value() const &;
Mandates: is_copy_constructible_v<E> is true.
Throws: bad_expected_access(error()) if has_value() is false.
constexpr void value() &&;
Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true.
Throws: bad_expected_access(std​::​move(error())) if has_value() is false.
constexpr const E& error() const & noexcept; constexpr E& error() & noexcept;
Preconditions: has_value() is false.
Returns: unex.
constexpr E&& error() && noexcept; constexpr const E&& error() const && noexcept;
Preconditions: has_value() is false.
Returns: std​::​move(unex).
template<class G = E> constexpr E error_or(G&& e) const &;
Mandates: is_copy_constructible_v<E> is true and is_convertible_v<G, E> is true.
Returns: std​::​forward<G>(e) if has_value() is true, error() otherwise.
template<class G = E> constexpr E error_or(G&& e) &&;
Mandates: is_move_constructible_v<E> is true and is_convertible_v<G, E> is true.
Returns: std​::​forward<G>(e) if has_value() is true, std​::​move(error()) otherwise.

22.8.7.7 Monadic operations [expected.void.monadic]

template<class F> constexpr auto and_then(F&& f) &; template<class F> constexpr auto and_then(F&& f) const &;
Let U be remove_cvref_t<invoke_result_t<F>>.
Constraints: is_constructible_v<E, decltype(error())>> is true.
Mandates: U is a specialization of expected and is_same_v<U​::​error_type, E> is true.
Effects: Equivalent to: if (has_value()) return invoke(std::forward<F>(f)); else return U(unexpect, error());
template<class F> constexpr auto and_then(F&& f) &&; template<class F> constexpr auto and_then(F&& f) const &&;
Let U be remove_cvref_t<invoke_result_t<F>>.
Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.
Mandates: U is a specialization of expected and is_same_v<U​::​error_type, E> is true.
Effects: Equivalent to: if (has_value()) return invoke(std::forward<F>(f)); else return U(unexpect, std::move(error()));
template<class F> constexpr auto or_else(F&& f) &; template<class F> constexpr auto or_else(F&& f) const &;
Let G be remove_cvref_t<invoke_result_t<F, decltype(error())>>.
Mandates: G is a specialization of expected and is_same_v<G​::​value_type, T> is true.
Effects: Equivalent to: if (has_value()) return G(); else return invoke(std::forward<F>(f), error());
template<class F> constexpr auto or_else(F&& f) &&; template<class F> constexpr auto or_else(F&& f) const &&;
Let G be remove_cvref_t<invoke_result_t<F, decltype(std​::​move(error()))>>.
Mandates: G is a specialization of expected and is_same_v<G​::​value_type, T> is true.
Effects: Equivalent to: if (has_value()) return G(); else return invoke(std::forward<F>(f), std::move(error()));
template<class F> constexpr auto transform(F&& f) &; template<class F> constexpr auto transform(F&& f) const &;
Let U be remove_cv_t<invoke_result_t<F>>.
Constraints: is_constructible_v<E, decltype(error())> is true.
Mandates: U is a valid value type for expected.
If is_void_v<U> is false, the declaration U u(invoke(std::forward<F>(f))); is well-formed.
Effects:
  • If has_value() is false, returns expected<U, E>(unexpect, error()).
  • Otherwise, if is_void_v<U> is false, returns an expected<U, E> object whose has_val member is true and val member is direct-non-list-initialized with invoke(std​::​forward<F>(f)).
  • Otherwise, evaluates invoke(std​::​forward<F>(f)) and then returns expected<U, E>().
template<class F> constexpr auto transform(F&& f) &&; template<class F> constexpr auto transform(F&& f) const &&;
Let U be remove_cv_t<invoke_result_t<F>>.
Constraints: is_constructible_v<E, decltype(std​::​move(error()))> is true.
Mandates: U is a valid value type for expected.
If is_void_v<U> is false, the declaration U u(invoke(std::forward<F>(f))); is well-formed.
Effects:
  • If has_value() is false, returns expected<U, E>(unexpect, std​::​move(error())).
  • Otherwise, if is_void_v<U> is false, returns an expected<U, E> object whose has_val member is true and val member is direct-non-list-initialized with invoke(std​::​forward<F>(f)).
  • Otherwise, evaluates invoke(std​::​forward<F>(f)) and then returns expected<U, E>().
template<class F> constexpr auto transform_error(F&& f) &; template<class F> constexpr auto transform_error(F&& f) const &;
Let G be remove_cv_t<invoke_result_t<F, decltype(error())>>.
Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declaration G g(invoke(std::forward<F>(f), error())); is well-formed.
Returns: If has_value() is true, expected<T, G>(); otherwise, an expected<T, G> object whose has_val member is false and unex member is direct-non-list-initialized with invoke(std​::​forward<F>(f), error()).
template<class F> constexpr auto transform_error(F&& f) &&; template<class F> constexpr auto transform_error(F&& f) const &&;
Let G be remove_cv_t<invoke_result_t<F, decltype(std​::​move(error()))>>.
Mandates: G is a valid template argument for unexpected ([expected.un.general]) and the declaration G g(invoke(std::forward<F>(f), std::move(error()))); is well-formed.
Returns: If has_value() is true, expected<T, G>(); otherwise, an expected<T, G> object whose has_val member is false and unex member is direct-non-list-initialized with invoke(std​::​forward<F>(f), std​::​move(error())).

22.8.7.8 Equality operators [expected.void.eq]

template<class T2, class E2> requires is_void_v<T2> friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
Constraints: The expression x.error() == y.error() is well-formed and its result is convertible to bool.
Returns: If x.has_value() does not equal y.has_value(), false; otherwise x.has_value() || static_cast<bool>(x.error() == y.error()).
template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
Constraints: The expression x.error() == e.error() is well-formed and its result is convertible to bool.
Returns: !x.has_value() && static_cast<bool>(x.error() == e.error()).

22.9 Bitsets [bitset]

22.9.1 Header <bitset> synopsis [bitset.syn]

The header <bitset> defines a class template and several related functions for representing and manipulating fixed-size sequences of bits.
#include <string> // see [string.syn] #include <iosfwd> // for istream ([istream.syn]), ostream ([ostream.syn]), see [iosfwd.syn] namespace std { template<size_t N> class bitset; // [bitset.operators], bitset operators template<size_t N> constexpr bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept; template<size_t N> constexpr bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept; template<size_t N> constexpr bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept; template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x); template<class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x); }

22.9.2 Class template bitset [template.bitset]

22.9.2.1 General [template.bitset.general]

namespace std { template<size_t N> class bitset { public: // bit reference class reference { public: constexpr reference(const reference&) = default; constexpr ~reference(); constexpr reference& operator=(bool x) noexcept; // for b[i] = x; constexpr reference& operator=(const reference&) noexcept; // for b[i] = b[j]; constexpr bool operator~() const noexcept; // flips the bit constexpr operator bool() const noexcept; // for x = b[i]; constexpr reference& flip() noexcept; // for b[i].flip(); }; // [bitset.cons], constructors constexpr bitset() noexcept; constexpr bitset(unsigned long long val) noexcept; template<class charT, class traits, class Allocator> constexpr explicit bitset( const basic_string<charT, traits, Allocator>& str, typename basic_string<charT, traits, Allocator>::size_type pos = 0, typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos, charT zero = charT('0'), charT one = charT('1')); template<class charT, class traits> constexpr explicit bitset( basic_string_view<charT, traits> str, typename basic_string_view<charT, traits>::size_type pos = 0, typename basic_string_view<charT, traits>::size_type n = basic_string_view<charT, traits>::npos, charT zero = charT('0'), charT one = charT('1')); template<class charT> constexpr explicit bitset( const charT* str, typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos, charT zero = charT('0'), charT one = charT('1')); // [bitset.members], bitset operations constexpr bitset& operator&=(const bitset& rhs) noexcept; constexpr bitset& operator|=(const bitset& rhs) noexcept; constexpr bitset& operator^=(const bitset& rhs) noexcept; constexpr bitset& operator<<=(size_t pos) noexcept; constexpr bitset& operator>>=(size_t pos) noexcept; constexpr bitset operator<<(size_t pos) const noexcept; constexpr bitset operator>>(size_t pos) const noexcept; constexpr bitset& set() noexcept; constexpr bitset& set(size_t pos, bool val = true); constexpr bitset& reset() noexcept; constexpr bitset& reset(size_t pos); constexpr bitset operator~() const noexcept; constexpr bitset& flip() noexcept; constexpr bitset& flip(size_t pos); // element access constexpr bool operator[](size_t pos) const; constexpr reference operator[](size_t pos); constexpr unsigned long to_ulong() const; constexpr unsigned long long to_ullong() const; template<class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> constexpr basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const; // observers constexpr size_t count() const noexcept; constexpr size_t size() const noexcept; constexpr bool operator==(const bitset& rhs) const noexcept; constexpr bool test(size_t pos) const; constexpr bool all() const noexcept; constexpr bool any() const noexcept; constexpr bool none() const noexcept; }; // [bitset.hash], hash support template<class T> struct hash; template<size_t N> struct hash<bitset<N>>; }
The class template bitset<N> describes an object that can store a sequence consisting of a fixed number of bits, N.
Each bit represents either the value zero (reset) or one (set).
To toggle a bit is to change the value zero to one, or the value one to zero.
Each bit has a non-negative position pos.
When converting between an object of class bitset<N> and a value of some integral type, bit position pos corresponds to the bit value 1 << pos.
The integral value corresponding to two or more bits is the sum of their bit values.
The functions described in [template.bitset] can report three kinds of errors, each associated with a distinct exception:

22.9.2.2 Constructors [bitset.cons]

constexpr bitset() noexcept;
Effects: Initializes all bits in *this to zero.
constexpr bitset(unsigned long long val) noexcept;
Effects: Initializes the first M bit positions to the corresponding bit values in val.
M is the smaller of N and the number of bits in the value representation ([basic.types.general]) of unsigned long long.
If M < N, the remaining bit positions are initialized to zero.
template<class charT, class traits, class Allocator> constexpr explicit bitset( const basic_string<charT, traits, Allocator>& str, typename basic_string<charT, traits, Allocator>::size_type pos = 0, typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos, charT zero = charT('0'), charT one = charT('1')); template<class charT, class traits> constexpr explicit bitset( basic_string_view<charT, traits> str, typename basic_string_view<charT, traits>::size_type pos = 0, typename basic_string_view<charT, traits>::size_type n = basic_string_view<charT, traits>::npos, charT zero = charT('0'), charT one = charT('1'));
Effects: Determines the effective length rlen of the initializing string as the smaller of n and str.size() - pos.
Initializes the first M bit positions to values determined from the corresponding characters in the string str.
M is the smaller of N and rlen.
An element of the constructed object has value zero if the corresponding character in str, beginning at position pos, is zero.
Otherwise, the element has the value one.
Character position pos + M - 1 corresponds to bit position zero.
Subsequent decreasing character positions correspond to increasing bit positions.
If M < N, remaining bit positions are initialized to zero.
The function uses traits​::​eq to compare the character values.
Throws: out_of_range if pos > str.size() or invalid_argument if any of the rlen characters in str beginning at position pos is other than zero or one.
template<class charT> constexpr explicit bitset( const charT* str, typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos, charT zero = charT('0'), charT one = charT('1'));
Effects: As if by: bitset(n == basic_string_view<charT>::npos ? basic_string_view<charT>(str) : basic_string_view<charT>(str, n), 0, n, zero, one)

22.9.2.3 Members [bitset.members]

constexpr bitset& operator&=(const bitset& rhs) noexcept;
Effects: Clears each bit in *this for which the corresponding bit in rhs is clear, and leaves all other bits unchanged.
Returns: *this.
constexpr bitset& operator|=(const bitset& rhs) noexcept;
Effects: Sets each bit in *this for which the corresponding bit in rhs is set, and leaves all other bits unchanged.
Returns: *this.
constexpr bitset& operator^=(const bitset& rhs) noexcept;
Effects: Toggles each bit in *this for which the corresponding bit in rhs is set, and leaves all other bits unchanged.
Returns: *this.
constexpr bitset& operator<<=(size_t pos) noexcept;
Effects: Replaces each bit at position I in *this with a value determined as follows:
  • If I < pos, the new value is zero;
  • If I >= pos, the new value is the previous value of the bit at position I - pos.
Returns: *this.
constexpr bitset& operator>>=(size_t pos) noexcept;
Effects: Replaces each bit at position I in *this with a value determined as follows:
  • If pos >= N - I, the new value is zero;
  • If pos < N - I, the new value is the previous value of the bit at position I + pos.
Returns: *this.
constexpr bitset operator<<(size_t pos) const noexcept;
Returns: bitset(*this) <<= pos.
constexpr bitset operator>>(size_t pos) const noexcept;
Returns: bitset(*this) >>= pos.
constexpr bitset& set() noexcept;
Effects: Sets all bits in *this.
Returns: *this.
constexpr bitset& set(size_t pos, bool val = true);
Effects: Stores a new value in the bit at position pos in *this.
If val is true, the stored value is one, otherwise it is zero.
Returns: *this.
Throws: out_of_range if pos does not correspond to a valid bit position.
constexpr bitset& reset() noexcept;
Effects: Resets all bits in *this.
Returns: *this.
constexpr bitset& reset(size_t pos);
Effects: Resets the bit at position pos in *this.
Returns: *this.
Throws: out_of_range if pos does not correspond to a valid bit position.
constexpr bitset operator~() const noexcept;
Effects: Constructs an object x of class bitset and initializes it with *this.
Returns: x.flip().
constexpr bitset& flip() noexcept;
Effects: Toggles all bits in *this.
Returns: *this.
constexpr bitset& flip(size_t pos);
Effects: Toggles the bit at position pos in *this.
Returns: *this.
Throws: out_of_range if pos does not correspond to a valid bit position.
constexpr bool operator[](size_t pos) const;
Preconditions: pos is valid.
Returns: true if the bit at position pos in *this has the value one, otherwise false.
Throws: Nothing.
constexpr bitset::reference operator[](size_t pos);
Preconditions: pos is valid.
Returns: An object of type bitset​::​reference such that (*this)[pos] == this->test(pos), and such that (*this)[pos] = val is equivalent to this->set(pos, val).
Throws: Nothing.
Remarks: For the purpose of determining the presence of a data race ([intro.multithread]), any access or update through the resulting reference potentially accesses or modifies, respectively, the entire underlying bitset.
constexpr unsigned long to_ulong() const;
Returns: x.
Throws: overflow_error if the integral value x corresponding to the bits in *this cannot be represented as type unsigned long.
constexpr unsigned long long to_ullong() const;
Returns: x.
Throws: overflow_error if the integral value x corresponding to the bits in *this cannot be represented as type unsigned long long.
template<class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> constexpr basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const;
Effects: Constructs a string object of the appropriate type and initializes it to a string of length N characters.
Each character is determined by the value of its corresponding bit position in *this.
Character position N - 1 corresponds to bit position zero.
Subsequent decreasing character positions correspond to increasing bit positions.
Bit value zero becomes the character zero, bit value one becomes the character one.
Returns: The created object.
constexpr size_t count() const noexcept;
Returns: A count of the number of bits set in *this.
constexpr size_t size() const noexcept;
Returns: N.
constexpr bool operator==(const bitset& rhs) const noexcept;
Returns: true if the value of each bit in *this equals the value of the corresponding bit in rhs.
constexpr bool test(size_t pos) const;
Returns: true if the bit at position pos in *this has the value one.
Throws: out_of_range if pos does not correspond to a valid bit position.
constexpr bool all() const noexcept;
Returns: count() == size().
constexpr bool any() const noexcept;
Returns: count() != 0.
constexpr bool none() const noexcept;
Returns: count() == 0.

22.9.3 bitset hash support [bitset.hash]

template<size_t N> struct hash<bitset<N>>;
The specialization is enabled ([unord.hash]).

22.9.4 bitset operators [bitset.operators]

template<size_t N> constexpr bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) &= rhs.
template<size_t N> constexpr bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) |= rhs.
template<size_t N> constexpr bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns: bitset<N>(lhs) ^= rhs.
template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
A formatted input function ([istream.formatted]).
Effects: Extracts up to N characters from is.
Stores these characters in a temporary object str of type basic_string<charT, traits>, then evaluates the expression x = bitset<N>(str).
Characters are extracted and stored until any of the following occurs:
  • N characters have been extracted and stored;
  • end-of-file occurs on the input sequence;
  • the next input character is neither is.widen('0') nor is.widen('1') (in which case the input character is not extracted).
If N > 0 and no characters are stored in str, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: is.
template<class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
Returns: os << x.template to_string<charT, traits, allocator<charT>>( use_facet<ctype<charT>>(os.getloc()).widen('0'), use_facet<ctype<charT>>(os.getloc()).widen('1')) (see [ostream.formatted]).

22.10 Function objects [function.objects]

22.10.1 General [function.objects.general]

A function object type is an object type ([basic.types.general]) that can be the type of the postfix-expression in a function call ([expr.call], [over.match.call]).196
A 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 ([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.
196)196)
Such a type is a function pointer or a class type which has a member operator() or a class type which has a conversion to a pointer to function.

22.10.2 Header <functional> synopsis [functional.syn]

namespace std { // [func.invoke], invoke template<class F, class... Args> constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // freestanding noexcept(is_nothrow_invocable_v<F, Args...>); template<class R, class F, class... Args> constexpr R invoke_r(F&& f, Args&&... args) // freestanding noexcept(is_nothrow_invocable_r_v<R, F, Args...>); // [refwrap], reference_wrapper template<class T> class reference_wrapper; // freestanding template<class T> constexpr reference_wrapper<T> ref(T&) noexcept; // freestanding template<class T> constexpr reference_wrapper<const T> cref(const T&) noexcept; // freestanding template<class T> void ref(const T&&) = delete; // freestanding template<class T> void cref(const T&&) = delete; // freestanding template<class T> constexpr reference_wrapper<T> ref(reference_wrapper<T>) noexcept; // freestanding template<class T> constexpr reference_wrapper<const T> cref(reference_wrapper<T>) noexcept; // freestanding // [refwrap.common.ref], common_reference related specializations template<class R, class T, template<class> class RQual, template<class> class TQual> requires see below struct basic_common_reference<R, T, RQual, TQual>; template<class T, class R, template<class> class TQual, template<class> class RQual> requires see below struct basic_common_reference<T, R, TQual, RQual>; // [arithmetic.operations], arithmetic operations template<class T = void> struct plus; // freestanding template<class T = void> struct minus; // freestanding template<class T = void> struct multiplies; // freestanding template<class T = void> struct divides; // freestanding template<class T = void> struct modulus; // freestanding template<class T = void> struct negate; // freestanding template<> struct plus<void>; // freestanding template<> struct minus<void>; // freestanding template<> struct multiplies<void>; // freestanding template<> struct divides<void>; // freestanding template<> struct modulus<void>; // freestanding template<> struct negate<void>; // freestanding // [comparisons], comparisons template<class T = void> struct equal_to; // freestanding template<class T = void> struct not_equal_to; // freestanding template<class T = void> struct greater; // freestanding template<class T = void> struct less; // freestanding template<class T = void> struct greater_equal; // freestanding template<class T = void> struct less_equal; // freestanding template<> struct equal_to<void>; // freestanding template<> struct not_equal_to<void>; // freestanding template<> struct greater<void>; // freestanding template<> struct less<void>; // freestanding template<> struct greater_equal<void>; // freestanding template<> struct less_equal<void>; // freestanding // [comparisons.three.way], class compare_three_way struct compare_three_way; // freestanding // [logical.operations], logical operations template<class T = void> struct logical_and; // freestanding template<class T = void> struct logical_or; // freestanding template<class T = void> struct logical_not; // freestanding template<> struct logical_and<void>; // freestanding template<> struct logical_or<void>; // freestanding template<> struct logical_not<void>; // freestanding // [bitwise.operations], bitwise operations template<class T = void> struct bit_and; // freestanding template<class T = void> struct bit_or; // freestanding template<class T = void> struct bit_xor; // freestanding template<class T = void> struct bit_not; // freestanding template<> struct bit_and<void>; // freestanding template<> struct bit_or<void>; // freestanding template<> struct bit_xor<void>; // freestanding template<> struct bit_not<void>; // freestanding // [func.identity], identity struct identity; // freestanding // [func.not.fn], function template not_fn template<class F> constexpr unspecified not_fn(F&& f); // freestanding template<auto f> constexpr unspecified not_fn() noexcept; // freestanding // [func.bind.partial], function templates bind_front and bind_back template<class F, class... Args> constexpr unspecified bind_front(F&&, Args&&...); // freestanding template<auto f, class... Args> constexpr unspecified bind_front(Args&&...); // freestanding template<class F, class... Args> constexpr unspecified bind_back(F&&, Args&&...); // freestanding template<auto f, class... Args> constexpr unspecified bind_back(Args&&...); // freestanding // [func.bind], bind template<class T> struct is_bind_expression; // freestanding template<class T> constexpr bool is_bind_expression_v = // freestanding is_bind_expression<T>::value; template<class T> struct is_placeholder; // freestanding template<class T> constexpr int is_placeholder_v = // freestanding is_placeholder<T>::value; template<class F, class... BoundArgs> constexpr unspecified bind(F&&, BoundArgs&&...); // freestanding template<class R, class F, class... BoundArgs> constexpr unspecified bind(F&&, BoundArgs&&...); // freestanding namespace placeholders { // M is the implementation-defined number of placeholders see below _1; // freestanding see below _2; // freestanding . . . see below _M; // freestanding } // [func.memfn], member function adaptors template<class R, class T> constexpr unspecified mem_fn(R T::*) noexcept; // freestanding // [func.wrap], polymorphic function wrappers // [func.wrap.badcall], class bad_function_call class bad_function_call; // [func.wrap.func], class template function template<class> class function; // not defined template<class R, class... ArgTypes> class function<R(ArgTypes...)>; // [func.wrap.func.alg], function specialized algorithms template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept; // [func.wrap.func.nullptr], function null pointer comparison operator functions template<class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; // [func.wrap.move], move-only wrapper template<class... S> class move_only_function; // not defined template<class R, class... ArgTypes> class move_only_function<R(ArgTypes...) cv ref noexcept(noex)>; // see below // [func.wrap.copy], copyable wrapper template<class... S> class copyable_function; // not defined template<class R, class... ArgTypes> class copyable_function<R(ArgTypes...) cv ref noexcept(noex)>; // see below // [func.wrap.ref], non-owning wrapper template<class... S> class function_ref; // freestanding, not defined template<class R, class... ArgTypes> class function_ref<R(ArgTypes...) cv noexcept(noex)>; // freestanding, see below // [func.search], searchers template<class ForwardIterator1, class BinaryPredicate = equal_to<>> class default_searcher; // freestanding template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_searcher; template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher; // [unord.hash], class template hash template<class T> struct hash; // freestanding namespace ranges { // [range.cmp], concept-constrained comparisons struct equal_to; // freestanding struct not_equal_to; // freestanding struct greater; // freestanding struct less; // freestanding struct greater_equal; // freestanding struct less_equal; // freestanding } template<class Fn, class... Args> concept callable = // exposition only requires (Fn&& fn, Args&&... args) { std::forward<Fn>(fn)(std::forward<Args>(args)...); }; template<class Fn, class... Args> concept nothrow-callable = // exposition only callable<Fn, Args...> && requires (Fn&& fn, Args&&... args) { { std::forward<Fn>(fn)(std::forward<Args>(args)...) } noexcept; }; template<class Fn, class... Args> using call-result-t = decltype(declval<Fn>()(declval<Args>()...)); // exposition only template<const auto& T> using decayed-typeof = decltype(auto(T)); // exposition only }
[Example 1: 
If a C++ program wants to have a by-element addition of two vectors a and b containing double and put the result into a, it can do: transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
— end example]
[Example 2: 
To negate every element of a:
transform(a.begin(), a.end(), a.begin(), negate<double>()); — end example]

22.10.3 Definitions [func.def]

The following definitions apply to this Clause:
A call signature is the name of a return type followed by a parenthesized comma-separated list of zero or more argument types.
A callable type is a function object type ([function.objects]) or a pointer to member.
A callable object is an object of a callable type.
A call wrapper type is a type that holds a callable object and supports a call operation that forwards to that object.
A call wrapper is an object of a call wrapper type.
A target object is the callable object held by a call wrapper.
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 bound argument entities.
The target object and bound argument entities of the call wrapper are collectively referred to as state entities.

22.10.4 Requirements [func.require]

Define INVOKE(f, t, t, , t) as follows:
  • (t.*f)(t, , t) when f is a pointer to a member function of a class T and is_same_v<T, remove_cvref_t<decltype(t)>> || is_base_of_v<T, remove_cvref_t<decltype(t)>> is true;
  • (t.get().*f)(t, , t) when f is a pointer to a member function of a class T and remove_cvref_t<decltype(t)> is a specialization of reference_wrapper;
  • ((*t).*f)(t, , t) when f is a pointer to a member function of a class T and t does not satisfy the previous two items;
  • t.*f when and f is a pointer to data member of a class T and is_same_v<T, remove_cvref_t<decltype(t)>> || is_base_of_v<T, remove_cvref_t<decltype(t)>> is true;
  • t.get().*f when and f is a pointer to data member of a class T and remove_cvref_t<decltype(t)> is a specialization of reference_wrapper;
  • (*t).*f when and f is a pointer to data member of a class T and t does not satisfy the previous two items;
  • f(t, t, , t) in all other cases.
Define INVOKE<R>(f, t, t, , t) as static_cast<void>(INVOKE(f, t, t, , t)) if R is cv void, otherwise INVOKE(f, t, t, , t) implicitly converted to R.
If reference_converts_from_temporary_v<R, decltype(INVOKE(f, t, t, , t))> is true, INVOKE<R>(f, t, t, , t) is ill-formed.
Every call wrapper ([func.def]) meets the Cpp17MoveConstructible and Cpp17Destructible requirements.
An 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.
[Note 1: 
In a typical implementation, argument forwarding call wrappers have an overloaded function call operator of the form template<class... UnBoundArgs> constexpr R operator()(UnBoundArgs&&... unbound_args) cv-qual;
— end note]
A 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 T as cv T& when the call is performed on an lvalue of the call wrapper type and as cv T&& otherwise, where cv represents the cv-qualifiers of the call wrapper and where cv shall be neither volatile nor const volatile.
A 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 ([defns.expression.equivalent]) to an expression e determined from its call pattern 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.
A simple call wrapper is a perfect forwarding call wrapper that meets the Cpp17CopyConstructible and Cpp17CopyAssignable requirements and whose copy constructor, move constructor, and assignment operators are constexpr functions that do not throw exceptions.
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 ([class.copy.ctor]).
[Note 2: 
This implies that each of the copy/move constructors has the same exception-specification as the corresponding implicit definition and is declared as constexpr if the corresponding implicit definition would be considered to be constexpr.
— end note]
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.

22.10.5 invoke functions [func.invoke]

template<class F, class... Args> constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>);
Constraints: is_invocable_v<F, Args...> is true.
Returns: INVOKE(std​::​forward<F>(f), std​::​forward<Args>(args)...) ([func.require]).
template<class R, class F, class... Args> constexpr R invoke_r(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);
Constraints: is_invocable_r_v<R, F, Args...> is true.
Returns: INVOKE<R>(std​::​forward<F>(f), std​::​forward<Args>(args)...) ([func.require]).

22.10.6 Class template reference_wrapper [refwrap]

22.10.6.1 General [refwrap.general]

namespace std { template<class T> class reference_wrapper { public: // types using type = T; // [refwrap.const], constructors template<class U> constexpr reference_wrapper(U&&) noexcept(see below); constexpr reference_wrapper(const reference_wrapper& x) noexcept; // [refwrap.assign], assignment constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept; // [refwrap.access], access constexpr operator T& () const noexcept; constexpr T& get() const noexcept; // [refwrap.invoke], invocation template<class... ArgTypes> constexpr invoke_result_t<T&, ArgTypes...> operator()(ArgTypes&&...) const noexcept(is_nothrow_invocable_v<T&, ArgTypes...>); // [refwrap.comparisons], comparisons friend constexpr bool operator==(reference_wrapper, reference_wrapper); friend constexpr bool operator==(reference_wrapper, const T&); friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>); friend constexpr auto operator<=>(reference_wrapper, reference_wrapper); friend constexpr auto operator<=>(reference_wrapper, const T&); friend constexpr auto operator<=>(reference_wrapper, reference_wrapper<const T>); }; template<class T> reference_wrapper(T&) -> reference_wrapper<T>; }
reference_wrapper<T> is a Cpp17CopyConstructible and Cpp17CopyAssignable wrapper around a reference to an object or function of type T.
reference_wrapper<T> is a trivially copyable type ([basic.types.general]).
The template parameter T of reference_wrapper may be an incomplete type.
[Note 1: 
Using the comparison operators described in [refwrap.comparisons] with T being an incomplete type can lead to an ill-formed program with no diagnostic required ([temp.point], [temp.constr.atomic]).
— end note]

22.10.6.2 Constructors [refwrap.const]

template<class U> constexpr reference_wrapper(U&& u) noexcept(see below);
Let FUN denote the exposition-only functions void FUN(T&) noexcept; void FUN(T&&) = delete;
Constraints: The expression FUN(declval<U>()) is well-formed and is_same_v<remove_cvref_t<U>, reference_wrapper> is false.
Effects: Creates a variable r as if by T& r = std​::​forward<U>(u), then constructs a reference_wrapper object that stores a reference to r.
Remarks: The exception specification is equivalent to noexcept(FUN(declval<U>())).
constexpr reference_wrapper(const reference_wrapper& x) noexcept;
Effects: Constructs a reference_wrapper object that stores a reference to x.get().

22.10.6.3 Assignment [refwrap.assign]

constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept;
Postconditions: *this stores a reference to x.get().

22.10.6.4 Access [refwrap.access]

constexpr operator T& () const noexcept;
Returns: The stored reference.
constexpr T& get() const noexcept;
Returns: The stored reference.

22.10.6.5 Invocation [refwrap.invoke]

template<class... ArgTypes> constexpr invoke_result_t<T&, ArgTypes...> operator()(ArgTypes&&... args) const noexcept(is_nothrow_invocable_v<T&, ArgTypes...>);
Mandates: T is a complete type.
Returns: INVOKE(get(), std​::​forward<ArgTypes>(args)...) ([func.require]).

22.10.6.6 Comparisons [refwrap.comparisons]

friend constexpr bool operator==(reference_wrapper x, reference_wrapper y);
Constraints: The expression x.get() == y.get() is well-formed and its result is convertible to bool.
Returns: x.get() == y.get().
friend constexpr bool operator==(reference_wrapper x, const T& y);
Constraints: The expression x.get() == y is well-formed and its result is convertible to bool.
Returns: x.get() == y.
friend constexpr bool operator==(reference_wrapper x, reference_wrapper<const T> y);
Constraints: is_const_v<T> is false and the expression x.get() == y.get() is well-formed and its result is convertible to bool.
Returns: x.get() == y.get().
friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper y);
Constraints: The expression synth-three-way(x.get(), y.get()) is well-formed.
Returns: synth-three-way(x.get(), y.get()).
friend constexpr auto operator<=>(reference_wrapper x, const T& y);
Constraints: The expression synth-three-way(x.get(), y) is well-formed.
Returns: synth-three-way(x.get(), y).
friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper<const T> y);
Constraints: is_const_v<T> is false.
The expression synth-three-way(x.get(), y.get()) is well-formed.
Returns: synth-three-way(x.get(), y.get()).

22.10.6.7 Helper functions [refwrap.helpers]

The template parameter T of the following ref and cref function templates may be an incomplete type.
template<class T> constexpr reference_wrapper<T> ref(T& t) noexcept;
Returns: reference_wrapper<T>(t).
template<class T> constexpr reference_wrapper<T> ref(reference_wrapper<T> t) noexcept;
Returns: t.
template<class T> constexpr reference_wrapper<const T> cref(const T& t) noexcept;
Returns: reference_wrapper<const T>(t).
template<class T> constexpr reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept;
Returns: t.

22.10.6.8 common_reference related specializations [refwrap.common.ref]

namespace std { template<class T> constexpr bool is-ref-wrapper = false; // exposition only template<class T> constexpr bool is-ref-wrapper<reference_wrapper<T>> = true; template<class R, class T, class RQ, class TQ> concept ref-wrap-common-reference-exists-with = // exposition only is-ref-wrapper<R> && requires { typename common_reference_t<typename R::type&, TQ>; } && convertible_to<RQ, common_reference_t<typename R::type&, TQ>>; template<class R, class T, template<class> class RQual, template<class> class TQual> requires (ref-wrap-common-reference-exists-with<R, T, RQual<R>, TQual<T>> && !ref-wrap-common-reference-exists-with<T, R, TQual<T>, RQual<R>>) struct basic_common_reference<R, T, RQual, TQual> { using type = common_reference_t<typename R::type&, TQual<T>>; }; template<class T, class R, template<class> class TQual, template<class> class RQual> requires (ref-wrap-common-reference-exists-with<R, T, RQual<R>, TQual<T>> && !ref-wrap-common-reference-exists-with<T, R, TQual<T>, RQual<R>>) struct basic_common_reference<T, R, TQual, RQual> { using type = common_reference_t<typename R::type&, TQual<T>>; }; }

22.10.7 Arithmetic operations [arithmetic.operations]

22.10.7.1 General [arithmetic.operations.general]

The library provides basic function object classes for all of the arithmetic operators in the language ([expr.mul], [expr.add]).

22.10.7.2 Class template plus [arithmetic.operations.plus]

template<class T = void> struct plus { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x + y.
template<> struct plus<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) + std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) + std::forward<U>(u));
Returns: std​::​forward<T>(t) + std​::​forward<U>(u).

22.10.7.3 Class template minus [arithmetic.operations.minus]

template<class T = void> struct minus { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x - y.
template<> struct minus<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) - std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) - std::forward<U>(u));
Returns: std​::​forward<T>(t) - std​::​forward<U>(u).

22.10.7.4 Class template multiplies [arithmetic.operations.multiplies]

template<class T = void> struct multiplies { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x * y.
template<> struct multiplies<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) * std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) * std::forward<U>(u));
Returns: std​::​forward<T>(t) * std​::​forward<U>(u).

22.10.7.5 Class template divides [arithmetic.operations.divides]

template<class T = void> struct divides { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x / y.
template<> struct divides<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) / std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) / std::forward<U>(u));
Returns: std​::​forward<T>(t) / std​::​forward<U>(u).

22.10.7.6 Class template modulus [arithmetic.operations.modulus]

template<class T = void> struct modulus { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x % y.
template<> struct modulus<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) % std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) % std::forward<U>(u));
Returns: std​::​forward<T>(t) % std​::​forward<U>(u).

22.10.7.7 Class template negate [arithmetic.operations.negate]

template<class T = void> struct negate { constexpr T operator()(const T& x) const; };
constexpr T operator()(const T& x) const;
Returns: -x.
template<> struct negate<void> { template<class T> constexpr auto operator()(T&& t) const -> decltype(-std::forward<T>(t)); using is_transparent = unspecified; };
template<class T> constexpr auto operator()(T&& t) const -> decltype(-std::forward<T>(t));
Returns: -std​::​forward<T>(t).

22.10.8 Comparisons [comparisons]

22.10.8.1 General [comparisons.general]

The library provides basic function object classes for all of the comparison operators in the language ([expr.rel], [expr.eq]).
For templates less, greater, less_equal, and greater_equal, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers ([defns.order.ptr]).
[Note 1: 
If a < b is well-defined for pointers a and b of type P, then (a < b) == less<P>()(a, b), (a > b) == greater<P>()(a, b), and so forth.
— end note]
For template specializations less<void>, greater<void>, less_equal<void>, and greater_equal<void>, 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.

22.10.8.2 Class template equal_to [comparisons.equal.to]

template<class T = void> struct equal_to { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x == y.
template<> struct equal_to<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) == std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) == std::forward<U>(u));
Returns: std​::​forward<T>(t) == std​::​forward<U>(u).

22.10.8.3 Class template not_equal_to [comparisons.not.equal.to]

template<class T = void> struct not_equal_to { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x != y.
template<> struct not_equal_to<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) != std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) != std::forward<U>(u));
Returns: std​::​forward<T>(t) != std​::​forward<U>(u).

22.10.8.4 Class template greater [comparisons.greater]

template<class T = void> struct greater { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x > y.
template<> struct greater<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) > std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) > std::forward<U>(u));
Returns: std​::​forward<T>(t) > std​::​forward<U>(u).

22.10.8.5 Class template less [comparisons.less]

template<class T = void> struct less { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x < y.
template<> struct less<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) < std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) < std::forward<U>(u));
Returns: std​::​forward<T>(t) < std​::​forward<U>(u).

22.10.8.6 Class template greater_equal [comparisons.greater.equal]

template<class T = void> struct greater_equal { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x >= y.
template<> struct greater_equal<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) >= std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) >= std::forward<U>(u));
Returns: std​::​forward<T>(t) >= std​::​forward<U>(u).

22.10.8.7 Class template less_equal [comparisons.less.equal]

template<class T = void> struct less_equal { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x <= y.
template<> struct less_equal<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) <= std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) <= std::forward<U>(u));
Returns: std​::​forward<T>(t) <= std​::​forward<U>(u).

22.10.8.8 Class compare_three_way [comparisons.three.way]

namespace std { struct compare_three_way { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const; using is_transparent = unspecified; }; }
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const;
Constraints: T and U satisfy three_way_comparable_with.
Preconditions: If the expression std​::​forward<T>(t) <=> std​::​forward<U>(u) results in a call to a built-in operator <=> comparing pointers of type P, the conversion sequences from both T and U to P are equality-preserving ([concepts.equality]); otherwise, T and U model three_way_comparable_with.
Effects:
  • If the expression std​::​forward<T>(t) <=> std​::​forward<U>(u) results in a call to a built-in operator <=> comparing pointers of type P, returns strong_ordering​::​less if (the converted value of) t precedes u in the implementation-defined strict total order over pointers ([defns.order.ptr]), strong_ordering​::​greater if u precedes t, and otherwise strong_ordering​::​equal.
  • Otherwise, equivalent to: return std​::​forward<T>(t) <=> std​::​forward<U>(u);

22.10.9 Concept-constrained comparisons [range.cmp]

struct ranges::equal_to { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy equality_comparable_with.
Preconditions: If the expression std​::​forward<T>(t) == std​::​forward<U>(u) results in a call to a built-in operator == comparing pointers of type P, the conversion sequences from both T and U to P are equality-preserving ([concepts.equality]); otherwise, T and U model equality_comparable_with.
Effects:
  • If the expression std​::​forward<T>(t) == std​::​forward<U>(u) results in a call to a built-in operator == comparing pointers: returns false if either (the converted value of) t precedes u or u precedes t in the implementation-defined strict total order over pointers ([defns.order.ptr]) and otherwise true.
  • Otherwise, equivalent to: return std​::​forward<T>(t) == std​::​forward<U>(u);
struct ranges::not_equal_to { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy equality_comparable_with.
Effects: Equivalent to: return !ranges::equal_to{}(std::forward<T>(t), std::forward<U>(u));
struct ranges::greater { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy totally_ordered_with.
Effects: Equivalent to: return ranges::less{}(std::forward<U>(u), std::forward<T>(t));
struct ranges::less { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy totally_ordered_with.
Preconditions: If the expression std​::​forward<T>(t) < std​::​forward<U>(u) results in a call to a built-in operator < comparing pointers of type P, the conversion sequences from both T and U to P are equality-preserving ([concepts.equality]); otherwise, T and U model totally_ordered_with.
For any expressions ET and EU such that decltype((ET)) is T and decltype((EU)) is U, exactly one of ranges​::​less{}(ET, EU), ranges​::​less{}(EU, ET), or ranges​::​equal_to{}(ET, EU) is true.
Effects:
  • If the expression std​::​forward<T>(t) < std​::​forward<U>(u) results in a call to a built-in operator < comparing pointers: returns true if (the converted value of) t precedes u in the implementation-defined strict total order over pointers ([defns.order.ptr]) and otherwise false.
  • Otherwise, equivalent to: return std​::​forward<T>(t) < std​::​forward<U>(u);
struct ranges::greater_equal { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy totally_ordered_with.
Effects: Equivalent to: return !ranges::less{}(std::forward<T>(t), std::forward<U>(u));
struct ranges::less_equal { template<class T, class U> constexpr bool operator()(T&& t, U&& u) const; using is_transparent = unspecified; };
template<class T, class U> constexpr bool operator()(T&& t, U&& u) const;
Constraints: T and U satisfy totally_ordered_with.
Effects: Equivalent to: return !ranges::less{}(std::forward<U>(u), std::forward<T>(t));

22.10.10 Logical operations [logical.operations]

22.10.10.1 General [logical.operations.general]

The library provides basic function object classes for all of the logical operators in the language ([expr.log.and], [expr.log.or], [expr.unary.op]).

22.10.10.2 Class template logical_and [logical.operations.and]

template<class T = void> struct logical_and { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x && y.
template<> struct logical_and<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) && std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) && std::forward<U>(u));
Returns: std​::​forward<T>(t) && std​::​forward<U>(u).

22.10.10.3 Class template logical_or [logical.operations.or]

template<class T = void> struct logical_or { constexpr bool operator()(const T& x, const T& y) const; };
constexpr bool operator()(const T& x, const T& y) const;
Returns: x || y.
template<> struct logical_or<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) || std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) || std::forward<U>(u));
Returns: std​::​forward<T>(t) || std​::​forward<U>(u).

22.10.10.4 Class template logical_not [logical.operations.not]

template<class T = void> struct logical_not { constexpr bool operator()(const T& x) const; };
constexpr bool operator()(const T& x) const;
Returns: !x.
template<> struct logical_not<void> { template<class T> constexpr auto operator()(T&& t) const -> decltype(!std::forward<T>(t)); using is_transparent = unspecified; };
template<class T> constexpr auto operator()(T&& t) const -> decltype(!std::forward<T>(t));
Returns: !std​::​forward<T>(t).

22.10.11 Bitwise operations [bitwise.operations]

22.10.11.1 General [bitwise.operations.general]

The library provides basic function object classes for all of the bitwise operators in the language ([expr.bit.and], [expr.or], [expr.xor], [expr.unary.op]).

22.10.11.2 Class template bit_and [bitwise.operations.and]

template<class T = void> struct bit_and { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x & y.
template<> struct bit_and<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) & std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) & std::forward<U>(u));
Returns: std​::​forward<T>(t) & std​::​forward<U>(u).

22.10.11.3 Class template bit_or [bitwise.operations.or]

template<class T = void> struct bit_or { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x | y.
template<> struct bit_or<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) | std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) | std::forward<U>(u));
Returns: std​::​forward<T>(t) | std​::​forward<U>(u).

22.10.11.4 Class template bit_xor [bitwise.operations.xor]

template<class T = void> struct bit_xor { constexpr T operator()(const T& x, const T& y) const; };
constexpr T operator()(const T& x, const T& y) const;
Returns: x ^ y.
template<> struct bit_xor<void> { template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) ^ std::forward<U>(u)); using is_transparent = unspecified; };
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) ^ std::forward<U>(u));
Returns: std​::​forward<T>(t) ^ std​::​forward<U>(u).

22.10.11.5 Class template bit_not [bitwise.operations.not]

template<class T = void> struct bit_not { constexpr T operator()(const T& x) const; };
constexpr T operator()(const T& x) const;
Returns: ~x.
template<> struct bit_not<void> { template<class T> constexpr auto operator()(T&& t) const -> decltype(~std::forward<T>(t)); using is_transparent = unspecified; };
template<class T> constexpr auto operator()(T&& t) const -> decltype(~std::forward<T>(t));
Returns: ~std​::​forward<T>(t).

22.10.12 Class identity [func.identity]

struct identity { template<class T> constexpr T&& operator()(T&& t) const noexcept; using is_transparent = unspecified; }; template<class T> constexpr T&& operator()(T&& t) const noexcept;
Effects: Equivalent to: return std​::​forward<T>(t);

22.10.13 Function template not_fn [func.not.fn]

template<class F> constexpr unspecified not_fn(F&& f);
In the text that follows:
  • g is a value of the result of a not_fn invocation,
  • FD is the type decay_t<F>,
  • fd is the target object of g ([func.def]) of type FD, direct-non-list-initialized with std​::​forward<F​>(f),
  • call_args is an argument pack used in a function call expression ([expr.call]) of g.
Mandates: is_constructible_v<FD, F> && is_move_constructible_v<FD> is true.
Preconditions: FD meets the Cpp17MoveConstructible requirements.
Returns: A perfect forwarding call wrapper ([func.require]) g with call pattern !invoke(fd, call_args...).
Throws: Any exception thrown by the initialization of fd.
template<auto f> constexpr unspecified not_fn() noexcept;
In the text that follows:
  • F is the type of f,
  • g is a value of the result of a not_fn invocation,
  • call_args is an argument pack used in a function call expression ([expr.call]) of g.
Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
Returns: A perfect forwarding call wrapper ([func.require]) g that does not have state entities, and has the call pattern !invoke(f, call_args...).

22.10.14 Function templates bind_front and bind_back [func.bind.partial]

template<class F, class... Args> constexpr unspecified bind_front(F&& f, Args&&... args); template<class F, class... Args> constexpr unspecified bind_back(F&& f, Args&&... args);
Within this subclause:
  • g is a value of the result of a bind_front or bind_back invocation,
  • FD is the type decay_t<F>,
  • fd is the target object of g ([func.def]) of type FD, direct-non-list-initialized with std​::​forward<F​>(f),
  • BoundArgs is a pack that denotes decay_t<Args>...,
  • bound_args is a pack of bound argument entities of g ([func.def]) of types BoundArgs..., direct-non-list-initialized with std​::​forward<Args>(args)..., respectively, and
  • call_args is an argument pack used in a function call expression ([expr.call]) of g.
Mandates: is_constructible_v<FD, F> && is_move_constructible_v<FD> && (is_constructible_v<BoundArgs, Args> && ...) && (is_move_constructible_v<BoundArgs> && ...) is true.
Preconditions: FD meets the Cpp17MoveConstructible requirements.
For each in BoundArgs, if is an object type, meets the Cpp17MoveConstructible requirements.
Returns: A perfect forwarding call wrapper ([func.require]) g with call pattern:
  • invoke(fd, bound_args..., call_args...) for a bind_front invocation, or
  • invoke(fd, call_args..., bound_args...) for a bind_back invocation.
Throws: Any exception thrown by the initialization of the state entities of g ([func.def]).
template<auto f, class... Args> constexpr unspecified bind_front(Args&&... args); template<auto f, class... Args> constexpr unspecified bind_back(Args&&... args);
Within this subclause:
  • F is the type of f,
  • g is a value of the result of a bind_front or bind_back invocation,
  • BoundArgs is a pack that denotes decay_t<Args>...,
  • bound_args is a pack of bound argument entities of g ([func.def]) of types BoundArgs..., direct-non-list-initialized with std​::​forward<Args>(args)..., respectively, and
  • call_args is an argument pack used in a function call expression ([expr.call]) of g.
Mandates:
  • (is_constructible_v<BoundArgs, Args> && ...) is true, and
  • (is_move_constructible_v<BoundArgs> && ...) is true, and
  • if is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
Preconditions: For each in BoundArgs, meets the Cpp17MoveConstructible requirements.
Returns: A perfect forwarding call wrapper ([func.require]) g that does not have a target object, and has the call pattern:
  • invoke(f, bound_args..., call_args...) for a bind_front invocation, or
  • invoke(f, call_args..., bound_args...) for a bind_back invocation.
throws Any exception thrown by the initialization of bound_args.

22.10.15 Function object binders [func.bind]

22.10.15.1 General [func.bind.general]

Subclause [func.bind] describes a uniform mechanism for binding arguments of callable objects.

22.10.15.2 Class template is_bind_expression [func.bind.isbind]

namespace std { template<class T> struct is_bind_expression; // see below }
The class template is_bind_expression can be used to detect function objects generated by bind.
The function template bind uses is_bind_expression to detect subexpressions.
Specializations of the is_bind_expression template shall meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]).
The implementation provides a definition that has a base characteristic of true_type if T is a type returned from bind, otherwise it has a base characteristic of false_type.
A program may specialize this template for a program-defined type T to have a base characteristic of true_type to indicate that T should be treated as a subexpression in a bind call.

22.10.15.3 Class template is_placeholder [func.bind.isplace]

namespace std { template<class T> struct is_placeholder; // see below }
The class template is_placeholder can be used to detect the standard placeholders _1, _2, and so on ([func.bind.place]).
The function template bind uses is_placeholder to detect placeholders.
Specializations of the is_placeholder template shall meet the Cpp17UnaryTypeTrait requirements ([meta.rqmts]).
The implementation provides a definition that has the base characteristic of integral_constant<int, J> if T is the type of std​::​placeholders​::​_J, otherwise it has a base characteristic of integral_constant<int, 0>.
A program may specialize this template for a program-defined type T to have a base characteristic of integral_constant<int, N> with N > 0 to indicate that T should be treated as a placeholder type.

22.10.15.4 Function template bind [func.bind.bind]

In the text that follows:
  • g is a value of the result of a bind invocation,
  • FD is the type decay_t<F>,
  • fd is an lvalue that is a target object of g ([func.def]) of type FD direct-non-list-initialized with std​::​forward<F>(f),
  • is the type in the template parameter pack BoundArgs,
  • is the type decay_t<>,
  • is the argument in the function parameter pack bound_args,
  • is a bound argument entity of g ([func.def]) of type direct-non-list-initialized with std​::​forward<>(),
  • is the deduced type of the UnBoundArgs&&... parameter of the argument forwarding call wrapper, and
  • is the argument associated with .
template<class F, class... BoundArgs> constexpr unspecified bind(F&& f, BoundArgs&&... bound_args); template<class R, class F, class... BoundArgs> constexpr unspecified bind(F&& f, BoundArgs&&... bound_args);
Mandates: is_constructible_v<FD, F> is true.
For each in BoundArgs, is_constructible_v<, > is true.
Preconditions: FD and each meet the Cpp17MoveConstructible and Cpp17Destructible requirements.
INVOKE(fd, , , , ) ([func.require]) is a valid expression for some values , , , , where N has the value sizeof...(bound_args).
Returns: An argument forwarding call wrapper g ([func.require]).
A program that attempts to invoke a volatile-qualified g is ill-formed.
When g is not volatile-qualified, invocation of g(, , , ) is expression-equivalent ([defns.expression.equivalent]) to INVOKE(static_cast<>(), static_cast<>(), static_cast<>(), , static_cast<>()) for the first overload, and INVOKE<R>(static_cast<>(), static_cast<>(), static_cast<>(), , static_cast<>()) for the second overload, where the values and types of the target argument and of the bound arguments , , , are determined as specified below.
Throws: Any exception thrown by the initialization of the state entities of g.
[Note 1: 
If all of FD and meet the requirements of Cpp17CopyConstructible, then the return type meets the requirements of Cpp17CopyConstructible.
— end note]
The values of the bound arguments , , , and their corresponding types , , , depend on the types derived from the call to bind and the cv-qualifiers cv of the call wrapper g as follows:
  • if is reference_wrapper<T>, the argument is .get() and its type is T&;
  • if the value of is_bind_expression_v<> is true, the argument is static_cast<cv &>()(std::forward<>()...) and its type is invoke_result_t<cv &, ...>&&;
  • if the value j of is_placeholder_v<> is not zero, the argument is std​::​forward<>() and its type is &&;
  • otherwise, the value is and its type is cv &.
The value of the target argument is fd and its corresponding type is cv FD&.

22.10.15.5 Placeholders [func.bind.place]

namespace std::placeholders { // M is the number of placeholders see below _1; see below _2; . . . see below _M; }
The number M of placeholders is implementation-defined.
All placeholder types meet the Cpp17DefaultConstructible and Cpp17CopyConstructible requirements, and their default constructors and copy/move constructors are constexpr functions that do not throw exceptions.
It is implementation-defined whether placeholder types meet the Cpp17CopyAssignable requirements, but if so, their copy assignment operators are constexpr functions that do not throw exceptions.
Placeholders should be defined as: inline constexpr unspecified _1{};
If they are not, they are declared as: extern unspecified _1;
Placeholders are freestanding items ([freestanding.item]).

22.10.16 Function template mem_fn [func.memfn]

template<class R, class T> constexpr unspecified mem_fn(R T::* pm) noexcept;
Returns: A simple call wrapper ([func.require]) fn with call pattern invoke(pmd, call_args...), where pmd is the target object of fn of type R T​::​* direct-non-list-initialized with pm, and call_args is an argument pack used in a function call expression ([expr.call]) of fn.

22.10.17 Polymorphic function wrappers [func.wrap]

22.10.17.1 General [func.wrap.general]

Subclause [func.wrap] describes polymorphic wrapper classes that encapsulate arbitrary callable objects.
Let t be an object of a type that is a specialization of function, copyable_function, or move_only_function, such that the target object x of t has a type that is a specialization of function, copyable_function, or move_only_function.
Each argument of the invocation of x evaluated as part of the invocation of t may alias an argument in the same position in the invocation of t that has the same type, even if the corresponding parameter is not of reference type.
[Example 1: move_only_function<void(T)> f{copyable_function<void(T)>{[](T) {}}}; T t; f(t); // it is unspecified how many copies of T are made — end example]
Recommended practice: Implementations should avoid double wrapping when constructing polymorphic wrappers from one another.

22.10.17.2 Class bad_function_call [func.wrap.badcall]

An exception of type bad_function_call is thrown by function​::​operator() ([func.wrap.func.inv]) when the function wrapper object has no target.
namespace std { class bad_function_call : public exception { public: // see [exception] for the specification of the special member functions const char* what() const noexcept override; }; }
const char* what() const noexcept override;
Returns: An implementation-defined ntbs.

22.10.17.3 Class template function [func.wrap.func]

22.10.17.3.1 General [func.wrap.func.general]

namespace std { template<class R, class... ArgTypes> class function<R(ArgTypes...)> { public: using result_type = R; // [func.wrap.func.con], construct/copy/destroy function() noexcept; function(nullptr_t) noexcept; function(const function&); function(function&&) noexcept; template<class F> function(F&&); function& operator=(const function&); function& operator=(function&&); function& operator=(nullptr_t) noexcept; template<class F> function& operator=(F&&); template<class F> function& operator=(reference_wrapper<F>) noexcept; ~function(); // [func.wrap.func.mod], function modifiers void swap(function&) noexcept; // [func.wrap.func.cap], function capacity explicit operator bool() const noexcept; // [func.wrap.func.inv], function invocation R operator()(ArgTypes...) const; // [func.wrap.func.targ], function target access const type_info& target_type() const noexcept; template<class T> T* target() noexcept; template<class T> const T* target() const noexcept; }; template<class R, class... ArgTypes> function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>; template<class F> function(F) -> function<see below>; }
The function class template provides polymorphic wrappers that generalize the notion of a function pointer.
Wrappers can store, copy, and call arbitrary callable objects ([func.def]), given a call signature ([func.def]).
A callable type ([func.def]) F is Lvalue-Callable for argument types ArgTypes and return type R if the expression INVOKE<R>(declval<F&>(), declval<ArgTypes>()...), considered as an unevaluated operand ([expr.context]), is well-formed ([func.require]).
The function class template is a call wrapper ([func.def]) whose call signature ([func.def]) is R(ArgTypes...).
[Note 1: 
The types deduced by the deduction guides for function might change in future revisions of C++.
— end note]

22.10.17.3.2 Constructors and destructor [func.wrap.func.con]

function() noexcept;
Postconditions: !*this.
function(nullptr_t) noexcept;
Postconditions: !*this.
function(const function& f);
Postconditions: !*this if !f; otherwise, the target object of *this is a copy of the target object of f.
Throws: Nothing if f's target is a specialization of reference_wrapper or a function pointer.
Otherwise, may throw bad_alloc or any exception thrown by the copy constructor of the stored callable object.
Recommended practice: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer.
function(function&& f) noexcept;
Postconditions: If !f, *this has no target; otherwise, the target of *this is equivalent to the target of f before the construction, and f is in a valid state with an unspecified value.
Recommended practice: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer.
template<class F> function(F&& f);
Let FD be decay_t<F>.
Constraints:
  • is_same_v<remove_cvref_t<F>, function> is false, and
  • FD is Lvalue-Callable ([func.wrap.func]) for argument types ArgTypes... and return type R.
Mandates:
  • is_copy_constructible_v<FD> is true, and
  • is_constructible_v<FD, F> is true.
Preconditions: FD meets the Cpp17CopyConstructible requirements.
Postconditions: !*this is true if any of the following hold:
  • f is a null function pointer value.
  • f is a null member pointer value.
  • remove_cvref_t<F> is a specialization of the function class template, and !f is true.
Otherwise, *this has a target object of type FD direct-non-list-initialized with std​::​forward<F>(f).
Throws: Nothing if FD is a specialization of reference_wrapper or a function pointer type.
Otherwise, may throw bad_alloc or any exception thrown by the initialization of the target object.
Recommended practice: Implementations should avoid the use of dynamically allocated memory for small callable objects, for example, where f refers to an object holding only a pointer or reference to an object and a member function pointer.
template<class F> function(F) -> function<see below>;
Constraints: &F​::​operator() is well-formed when treated as an unevaluated operand and either
  • F​::​operator() is a non-static member function and decltype(&F​::​operator()) is either of the form R(G​::​*)(A...) cv & noexcept or of the form R(*)(G, A...) noexcept for a type G, or
  • F​::​operator() is a static member function and decltype(&F​::​operator()) is of the form R(*)(A...) noexcept.
Remarks: The deduced type is function<R(A...)>.
[Example 1: void f() { int i{5}; function g = [&](double) { return i; }; // deduces function<int(double)> } — end example]
function& operator=(const function& f);
Effects: As if by function(f).swap(*this);
Returns: *this.
function& operator=(function&& f);
Effects: Replaces the target of *this with the target of f.
Returns: *this.
function& operator=(nullptr_t) noexcept;
Effects: If *this != nullptr, destroys the target of this.
Postconditions: !(*this).
Returns: *this.
template<class F> function& operator=(F&& f);
Constraints: decay_t<F> is Lvalue-Callable ([func.wrap.func]) for argument types ArgTypes... and return type R.
Effects: As if by: function(std​::​forward<F>(f)).swap(*this);
Returns: *this.
template<class F> function& operator=(reference_wrapper<F> f) noexcept;
Effects: As if by: function(f).swap(*this);
Returns: *this.
~function();
Effects: If *this != nullptr, destroys the target of this.

22.10.17.3.3 Modifiers [func.wrap.func.mod]

void swap(function& other) noexcept;
Effects: Interchanges the target objects of *this and other.

22.10.17.3.4 Capacity [func.wrap.func.cap]

explicit operator bool() const noexcept;
Returns: true if *this has a target, otherwise false.

22.10.17.3.5 Invocation [func.wrap.func.inv]

R operator()(ArgTypes... args) const;
Returns: INVOKE<R>(f, std​::​forward<ArgTypes>(args)...) ([func.require]), where f is the target object ([func.def]) of *this.
Throws: bad_function_call if !*this; otherwise, any exception thrown by the target object.

22.10.17.3.6 Target access [func.wrap.func.targ]

const type_info& target_type() const noexcept;
Returns: If *this has a target of type T, typeid(T); otherwise, typeid(void).
template<class T> T* target() noexcept; template<class T> const T* target() const noexcept;
Returns: If target_type() == typeid(T) a pointer to the stored function target; otherwise a null pointer.

22.10.17.3.7 Null pointer comparison operator functions [func.wrap.func.nullptr]

template<class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
Returns: !f.

22.10.17.3.8 Specialized algorithms [func.wrap.func.alg]

template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;
Effects: As if by: f1.swap(f2);

22.10.17.4 Move-only wrapper [func.wrap.move]

22.10.17.4.1 General [func.wrap.move.general]

The header provides partial specializations of move_only_function for each combination of the possible replacements of the placeholders cv, ref, and noex where
  • cv is either const or empty,
  • ref is either &, &&, or empty, and
  • noex is either true or false.
For each of the possible combinations of the placeholders mentioned above, there is a placeholder inv-quals defined as follows:
  • If ref is empty, let inv-quals be cv&,
  • otherwise, let inv-quals be cv ref.

22.10.17.4.2 Class template move_only_function [func.wrap.move.class]

namespace std { template<class R, class... ArgTypes> class move_only_function<R(ArgTypes...) cv ref noexcept(noex)> { public: using result_type = R; // [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<class F> move_only_function(F&&); template<class T, class... Args> explicit move_only_function(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> explicit move_only_function(in_place_type_t<T>, initializer_list<U>, Args&&...); move_only_function& operator=(move_only_function&&); move_only_function& operator=(nullptr_t) noexcept; template<class F> move_only_function& operator=(F&&); ~move_only_function(); // [func.wrap.move.inv], invocation explicit operator bool() const noexcept; R operator()(ArgTypes...) cv ref noexcept(noex); // [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<class VT> static constexpr bool is-callable-from = see below; // exposition only }; }
The move_only_function class template provides polymorphic wrappers that generalize the notion of a callable object ([func.def]).
These wrappers can store, move, and call arbitrary callable objects, given a call signature.
Recommended practice: Implementations should avoid the use of dynamically allocated memory for a small contained value.
[Note 1: 
Such small-object optimization can only be applied to a type T for which is_nothrow_move_constructible_v<T> is true.
— end note]

22.10.17.4.3 Constructors, assignment, and destructor [func.wrap.move.ctor]

template<class VT> static constexpr bool is-callable-from = see below;
If noex is true, is-callable-from<VT> is equal to: is_nothrow_invocable_r_v<R, VT cv ref, ArgTypes...> && is_nothrow_invocable_r_v<R, VT inv-quals, ArgTypes...>
Otherwise, is-callable-from<VT> is equal to: is_invocable_r_v<R, VT cv ref, ArgTypes...> && is_invocable_r_v<R, VT inv-quals, ArgTypes...>
move_only_function() noexcept; move_only_function(nullptr_t) noexcept;
Postconditions: *this has no target object.
move_only_function(move_only_function&& f) noexcept;
Postconditions: The target object of *this is the target object f had before construction, and f is in a valid state with an unspecified value.
template<class F> move_only_function(F&& f);
Let VT be decay_t<F>.
Constraints:
  • remove_cvref_t<F> is not the same type as move_only_function, and
  • remove_cvref_t<F> is not a specialization of in_place_type_t, and
  • is-callable-from<VT> is true.
Mandates: is_constructible_v<VT, F> is true.
Preconditions: VT meets the Cpp17Destructible requirements, and if is_move_constructible_v<VT> is true, VT meets the Cpp17MoveConstructible requirements.
Postconditions: *this has no target object if any of the following hold:
  • f is a null function pointer value, or
  • f is a null member pointer value, or
  • remove_cvref_t<F> is a specialization of the move_only_function class template, and f has no target object.
Otherwise, *this has a target object of type VT direct-non-list-initialized with std​::​forward<F>(f).
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a function pointer or a specialization of reference_wrapper.
template<class T, class... Args> explicit move_only_function(in_place_type_t<T>, Args&&... args);
Let VT be decay_t<T>.
Constraints:
  • is_constructible_v<VT, Args...> is true, and
  • is-callable-from<VT> is true.
Mandates: VT is the same type as T.
Preconditions: VT meets the Cpp17Destructible requirements, and if is_move_constructible_v<VT> is true, VT meets the Cpp17MoveConstructible requirements.
Postconditions: *this has a target object of type VT direct-non-list-initialized with std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a function pointer or a specialization of reference_wrapper.
template<class T, class U, class... Args> explicit move_only_function(in_place_type_t<T>, initializer_list<U> ilist, Args&&... args);
Let VT be decay_t<T>.
Constraints:
  • is_constructible_v<VT, initializer_list<U>&, Args...> is true, and
  • is-callable-from<VT> is true.
Mandates: VT is the same type as T.
Preconditions: VT meets the Cpp17Destructible requirements, and if is_move_constructible_v<VT> is true, VT meets the Cpp17MoveConstructible requirements.
Postconditions: *this has a target object of type VT direct-non-list-initialized with ilist, std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a function pointer or a specialization of reference_wrapper.
move_only_function& operator=(move_only_function&& f);
Effects: Equivalent to: move_only_function(std​::​move(f)).swap(*this);
Returns: *this.
move_only_function& operator=(nullptr_t) noexcept;
Effects: Destroys the target object of *this, if any.
Returns: *this.
template<class F> move_only_function& operator=(F&& f);
Effects: Equivalent to: move_only_function(std​::​forward<F>(f)).swap(*this);
Returns: *this.
~move_only_function();
Effects: Destroys the target object of *this, if any.

22.10.17.4.4 Invocation [func.wrap.move.inv]

explicit operator bool() const noexcept;
Returns: true if *this has a target object, otherwise false.
R operator()(ArgTypes... args) cv ref noexcept(noex);
Preconditions: *this has a target object.
Effects: Equivalent to: return INVOKE<R>(static_cast<F inv-quals>(f), std::forward<ArgTypes>(args)...); where f is an lvalue designating the target object of *this and F is the type of f.

22.10.17.4.5 Utility [func.wrap.move.util]

void swap(move_only_function& other) noexcept;
Effects: Exchanges the target objects of *this and other.
friend void swap(move_only_function& f1, move_only_function& f2) noexcept;
Effects: Equivalent to f1.swap(f2).
friend bool operator==(const move_only_function& f, nullptr_t) noexcept;
Returns: true if f has no target object, otherwise false.

22.10.17.5 Copyable wrapper [func.wrap.copy]

22.10.17.5.1 General [func.wrap.copy.general]

The header provides partial specializations of copyable_function for each combination of the possible replacements of the placeholders cv, ref, and noex where
  • cv is either const or empty,
  • ref is either &, &&, or empty, and
  • noex is either true or false.
For each of the possible combinations of the placeholders mentioned above, there is a placeholder inv-quals defined as follows:
  • If ref is empty, let inv-quals be cv&,
  • otherwise, let inv-quals be cv ref.

22.10.17.5.2 Class template copyable_function [func.wrap.copy.class]

namespace std { template<class R, class... ArgTypes> class copyable_function<R(ArgTypes...) cv ref noexcept(noex)> { public: using result_type = R; // [func.wrap.copy.ctor], constructors, assignments, and destructors copyable_function() noexcept; copyable_function(nullptr_t) noexcept; copyable_function(const copyable_function&); copyable_function(copyable_function&&) noexcept; template<class F> copyable_function(F&&); template<class T, class... Args> explicit copyable_function(in_place_type_t<T>, Args&&...); template<class T, class U, class... Args> explicit copyable_function(in_place_type_t<T>, initializer_list<U>, Args&&...); copyable_function& operator=(const copyable_function&); copyable_function& operator=(copyable_function&&); copyable_function& operator=(nullptr_t) noexcept; template<class F> copyable_function& operator=(F&&); ~copyable_function(); // [func.wrap.copy.inv], invocation explicit operator bool() const noexcept; R operator()(ArgTypes...) cv ref noexcept(noex); // [func.wrap.copy.util], utility void swap(copyable_function&) noexcept; friend void swap(copyable_function&, copyable_function&) noexcept; friend bool operator==(const copyable_function&, nullptr_t) noexcept; private: template<class VT> static constexpr bool is-callable-from = see below; // exposition only }; }
The copyable_function class template provides polymorphic wrappers that generalize the notion of a callable object ([func.def]).
These wrappers can store, copy, move, and call arbitrary callable objects, given a call signature.
Recommended practice: Implementations should avoid the use of dynamically allocated memory for a small contained value.
[Note 1: 
Such small-object optimization can only be applied to a type T for which is_nothrow_move_constructible_v<T> is true.
— end note]

22.10.17.5.3 Constructors, assignments, and destructors [func.wrap.copy.ctor]

template<class VT> static constexpr bool is-callable-from = see below;
If noex is true, is-callable-from<VT> is equal to: is_nothrow_invocable_r_v<R, VT cv ref, ArgTypes...> && is_nothrow_invocable_r_v<R, VT inv-quals, ArgTypes...>
Otherwise, is-callable-from<VT> is equal to: is_invocable_r_v<R, VT cv ref, ArgTypes...> && is_invocable_r_v<R, VT inv-quals, ArgTypes...>
copyable_function() noexcept; copyable_function(nullptr_t) noexcept;
Postconditions: *this has no target object.
copyable_function(const copyable_function& f);
Postconditions: *this has no target object if f had no target object.
Otherwise, the target object of *this is a copy of the target object of f.
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc.
copyable_function(copyable_function&& f) noexcept;
Postconditions: The target object of *this is the target object f had before construction, and f is in a valid state with an unspecified value.
template<class F> copyable_function(F&& f);
Let VT be decay_t<F>.
Constraints:
  • remove_cvref_t<F> is not the same type as copyable_function, and
  • remove_cvref_t<F> is not a specialization of in_place_type_t, and
  • is-callable-from<VT> is true.
Mandates:
  • is_constructible_v<VT, F> is true, and
  • is_copy_constructible_v<VT> is true.
Preconditions: VT meets the Cpp17Destructible and Cpp17CopyConstructible requirements.
Postconditions: *this has no target object if any of the following hold:
  • f is a null function pointer value, or
  • f is a null member pointer value, or
  • remove_cvref_t<F> is a specialization of the copyable_function class template, and f has no target object.
Otherwise, *this has a target object of type VT direct-non-list-initialized with std​::​forward<F>(f).
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a function pointer or a specialization of reference_wrapper.
template<class T, class... Args> explicit copyable_function(in_place_type_t<T>, Args&&... args);
Let VT be decay_t<T>.
Constraints:
  • is_constructible_v<VT, Args...> is true, and
  • is-callable-from<VT> is true.
Mandates:
  • VT is the same type as T, and
  • is_copy_constructible_v<VT> is true.
Preconditions: VT meets the Cpp17Destructible and Cpp17CopyConstructible requirements.
Postconditions: *this has a target object of type VT direct-non-list-initialized with std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a pointer or a specialization of reference_wrapper.
template<class T, class U, class... Args> explicit copyable_function(in_place_type_t<T>, initializer_list<U> ilist, Args&&... args);
Let VT be decay_t<T>.
Constraints:
  • is_constructible_v<VT, initializer_list<U>&, Args...> is true, and
  • is-callable-from<VT> is true.
Mandates:
  • VT is the same type as T, and
  • is_copy_constructible_v<VT> is true.
Preconditions: VT meets the Cpp17Destructible and Cpp17CopyConstructible requirements.
Postconditions: *this has a target object of type VT direct-non-list-initialized with ilist, std​::​forward<Args>(args)....
Throws: Any exception thrown by the initialization of the target object.
May throw bad_alloc unless VT is a pointer or a specialization of reference_wrapper.
copyable_function& operator=(const copyable_function& f);
Effects: Equivalent to: copyable_function(f).swap(*this);
Returns: *this.
copyable_function& operator=(copyable_function&& f);
Effects: Equivalent to: copyable_function(std​::​move(f)).swap(*this);
Returns: *this.
copyable_function& operator=(nullptr_t) noexcept;
Effects: Destroys the target object of *this, if any.
Returns: *this.
template<class F> copyable_function& operator=(F&& f);
Effects: Equivalent to: copyable_function(std​::​forward<F>(f)).swap(*this);
Returns: *this.
~copyable_function();
Effects: Destroys the target object of *this, if any.

22.10.17.5.4 Invocation [func.wrap.copy.inv]

explicit operator bool() const noexcept;
Returns: true if *this has a target object, otherwise false.
R operator()(ArgTypes... args) cv ref noexcept(noex);
Preconditions: *this has a target object.
Effects: Equivalent to: return INVOKE<R>(static_cast<F inv-quals>(f), std::forward<ArgTypes>(args)...); where f is an lvalue designating the target object of *this and F is the type of f.

22.10.17.5.5 Utility [func.wrap.copy.util]

void swap(copyable_function& other) noexcept;
Effects: Exchanges the target objects of *this and other.
friend void swap(copyable_function& f1, copyable_function& f2) noexcept;
Effects: Equivalent to f1.swap(f2).
friend bool operator==(const copyable_function& f, nullptr_t) noexcept;
Returns: true if f has no target object, otherwise false.

22.10.17.6 Non-owning wrapper [func.wrap.ref]

22.10.17.6.1 General [func.wrap.ref.general]

The header provides partial specializations of function_ref for each combination of the possible replacements of the placeholders cv and noex where:
  • cv is either const or empty, and
  • noex is either true or false.

22.10.17.6.2 Class template function_ref [func.wrap.ref.class]

namespace std { template<class R, class... ArgTypes> class function_ref<R(ArgTypes...) cv noexcept(noex)> { public: // [func.wrap.ref.ctor], constructors and assignment operators template<class F> function_ref(F*) noexcept; template<class F> constexpr function_ref(F&&) noexcept; template<auto f> constexpr function_ref(nontype_t<f>) noexcept; template<auto f, class U> constexpr function_ref(nontype_t<f>, U&&) noexcept; template<auto f, class T> constexpr function_ref(nontype_t<f>, cv T*) noexcept; constexpr function_ref(const function_ref&) noexcept = default; constexpr function_ref& operator=(const function_ref&) noexcept = default; template<class T> function_ref& operator=(T) = delete; // [func.wrap.ref.inv], invocation R operator()(ArgTypes...) const noexcept(noex); private: template<class... T> static constexpr bool is-invocable-using = see below; // exposition only R (*thunk-ptr)(BoundEntityType, Args&&...) noexcept(noex); // exposition only BoundEntityType bound-entity; // exposition only }; // [func.wrap.ref.deduct], deduction guides template<class F> function_ref(F*) -> function_ref<F>; template<auto f> function_ref(nontype_t<f>) -> function_ref<see below>; template<auto f, class T> function_ref(nontype_t<f>, T&&) -> function_ref<see below>; }
An object of class function_ref<R(Args...) cv noexcept(noex)> stores a pointer to function thunk-ptr and an object bound-entity.
bound-entity has an unspecified trivially copyable type BoundEntityType, that models copyable and is capable of storing a pointer to object value or a pointer to function value.
The type of thunk-ptr is R(*)(BoundEntityType, Args&&...) noexcept(noex).
Each specialization of function_ref is a trivially copyable type ([basic.types.general]) that models copyable.
Within [func.wrap.ref], call-args is an argument pack with elements such that decltype((call-args))... denote Args&&... respectively.

22.10.17.6.3 Constructors and assignment operators [func.wrap.ref.ctor]

template<class... T> static constexpr bool is-invocable-using = see below;
If noex is true, is-invocable-using<T...> is equal to: is_nothrow_invocable_r_v<R, T..., ArgTypes...>
Otherwise, is-invocable-using<T...> is equal to: is_invocable_r_v<R, T..., ArgTypes...>
template<class F> function_ref(F* f) noexcept;
Constraints:
  • is_function_v<F> is true, and
  • is-invocable-using<F> is true.
Preconditions: f is not a null pointer.
Effects: Initializes bound-entity with f, and thunk-ptr with the address of a function thunk such that thunk(bound-entity, call-args...) is expression-equivalent ([defns.expression.equivalent]) to invoke_r<R>(f, call-args...).
template<class F> constexpr function_ref(F&& f) noexcept;
Let T be remove_reference_t<F>.
Constraints:
  • remove_cvref_t<F> is not the same type as function_ref,
  • is_member_pointer_v<T> is false, and
  • is-invocable-using<cv T&> is true.
Effects: Initializes bound-entity with addressof(f), and thunk-ptr with the address of a function thunk such that thunk(bound-entity, call-args...) is expression-equivalent ([defns.expression.equivalent]) to invoke_r<R>(static_cast<cv T&>(f), call-args...).
template<auto f> constexpr function_ref(nontype_t<f>) noexcept;
Let F be decltype(f).
Constraints: is-invocable-using<F> is true.
Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
Effects: Initializes bound-entity with a pointer to an unspecified object or null pointer value, and thunk-ptr with the address of a function thunk such that thunk(bound-entity, call-args...) is expression-equivalent ([defns.expression.equivalent]) to invoke_r<R>(f, call-args...).
template<auto f, class U> constexpr function_ref(nontype_t<f>, U&& obj) noexcept;
Let T be remove_reference_t<U> and F be decltype(f).
Constraints:
  • is_rvalue_reference_v<U&&> is false, and
  • is-invocable-using<F, cv T&> is true.
Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
Effects: Initializes bound-entity with addressof(obj), and thunk-ptr with the address of a function thunk such that thunk(bound-entity, call-args...) is expression-equivalent ([defns.expression.equivalent]) to invoke_r<R>(f, static_cast<cv T&>(obj), call-args...).
template<auto f, class T> constexpr function_ref(nontype_t<f>, cv T* obj) noexcept;
Let F be decltype(f).
Constraints: is-invocable-using<F, cv T*> is true.
Mandates: If is_pointer_v<F> || is_member_pointer_v<F> is true, then f != nullptr is true.
Preconditions: If is_member_pointer_v<F> is true, obj is not a null pointer.
Effects: Initializes bound-entity with obj, and thunk-ptr with the address of a function thunk such that thunk(bound-entity, call-args...) is expression-equivalent ([defns.expression.equivalent]) to invoke_r<R>(f, obj, call-args...).
template<class T> function_ref& operator=(T) = delete;
Constraints:
  • T is not the same type as function_ref,
  • is_pointer_v<T> is false, and
  • T is not a specialization of nontype_t.

22.10.17.6.4 Invocation [func.wrap.ref.inv]

R operator()(ArgTypes... args) const noexcept(noex);
Effects: Equivalent to: return thunk-ptr(bound-entity, std​::​forward<ArgTypes>(args)...);

22.10.17.6.5 Deduction guides [func.wrap.ref.deduct]

template<class F> function_ref(F*) -> function_ref<F>;
Constraints: is_function_v<F> is true.
template<auto f> function_ref(nontype_t<f>) -> function_ref<see below>;
Let F be remove_pointer_t<decltype(f)>.
Constraints: is_function_v<F> is true.
Remarks: The deduced type is function_ref<F>.
template<auto f, class T> function_ref(nontype_t<f>, T&&) -> function_ref<see below>;
Let F be decltype(f).
Constraints:
  • F is of the form R(G​::​*)(A...) cv & noexcept(E) for a type G, or
  • F is of the form M G​::​* for a type G and an object type M, in which case let R be invoke_result_t<F, T&>, A... be an empty pack, and E be false, or
  • F is of the form R(*)(G, A...) noexcept(E) for a type G.
Remarks: The deduced type is function_ref<R(A...) noexcept(E)>.

22.10.18 Searchers [func.search]

22.10.18.1 General [func.search.general]

Subclause [func.search] provides function object types ([function.objects]) for operations that search for a sequence [pat_first, pat_last) in another sequence [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.
Each specialization of a class template specified in [func.search] shall meet the Cpp17CopyConstructible and Cpp17CopyAssignable requirements.
Template parameters named of templates specified in [func.search] shall meet the same requirements and semantics as specified in [algorithms.general].
Template parameters named Hash shall meet the Cpp17Hash requirements (Table 37).
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.

22.10.18.2 Class template default_searcher [func.search.default]

namespace std { template<class ForwardIterator1, class BinaryPredicate = equal_to<>> class default_searcher { public: constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, BinaryPredicate pred = BinaryPredicate()); template<class ForwardIterator2> constexpr pair<ForwardIterator2, ForwardIterator2> operator()(ForwardIterator2 first, ForwardIterator2 last) const; private: ForwardIterator1 pat_first_; // exposition only ForwardIterator1 pat_last_; // exposition only BinaryPredicate pred_; // exposition only }; }
constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, BinaryPredicate pred = BinaryPredicate());
Effects: Constructs a default_searcher object, initializing pat_first_ with pat_first, pat_last_ with pat_last, and pred_ with pred.
Throws: Any exception thrown by the copy constructor of BinaryPredicate or ForwardIterator1.
template<class ForwardIterator2> constexpr pair<ForwardIterator2, ForwardIterator2> operator()(ForwardIterator2 first, ForwardIterator2 last) const;
Effects: Returns a pair of iterators i and j such that
  • i == search(first, last, pat_first_, pat_last_, pred_), and
  • if i == last, then j == last, otherwise j == next(i, distance(pat_first_, pat_last_)).

22.10.18.3 Class template boyer_moore_searcher [func.search.bm]

namespace std { template<class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; private: RandomAccessIterator1 pat_first_; // exposition only RandomAccessIterator1 pat_last_; // exposition only Hash hash_; // exposition only BinaryPredicate pred_; // exposition only }; }
boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
Preconditions: The value type of RandomAccessIterator1 meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.
Let V be iterator_traits<RandomAccessIterator1>​::​value_type.
For any two values A and B of type V, if pred(A, B) == true, then hf(A) == hf(B) is true.
Effects: Initializes pat_first_ with pat_first, pat_last_ with pat_last, hash_ with hf, and pred_ with pred.
Throws: Any exception thrown by the copy constructor of RandomAccessIterator1, or by the default constructor, copy constructor, or the copy assignment operator of the value type of RandomAccessIterator1, or the copy constructor or operator() of BinaryPredicate or Hash.
May throw bad_alloc if additional memory needed for internal data structures cannot be allocated.
template<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Mandates: RandomAccessIterator1 and RandomAccessIterator2 have the same value type.
Effects: Finds a subsequence of equal values in a sequence.
Returns: A pair of iterators i and j such that
  • i is the first iterator in the range [first, last - (pat_last_ - pat_first_)) such that for every non-negative integer n less than pat_last_ - pat_first_ the following condition holds: pred(*(i + n), *(pat_first_ + n)) != false, and
  • j == next(i, distance(pat_first_, pat_last_)).
Returns make_pair(first, first) if [pat_first_, pat_last_) is empty, otherwise returns make_pair(last, last) if no such iterator is found.
Complexity: At most (last - first) * (pat_last_ - pat_first_) applications of the predicate.

22.10.18.4 Class template boyer_moore_horspool_searcher [func.search.bmh]

namespace std { template<class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::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<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; private: RandomAccessIterator1 pat_first_; // exposition only RandomAccessIterator1 pat_last_; // exposition only Hash hash_; // exposition only BinaryPredicate pred_; // exposition only }; }
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
Preconditions: The value type of RandomAccessIterator1 meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.
Let V be iterator_traits<RandomAccessIterator1>​::​value_type.
For any two values A and B of type V, if pred(A, B) == true, then hf(A) == hf(B) is true.
Effects: Initializes pat_first_ with pat_first, pat_last_ with pat_last, hash_ with hf, and pred_ with pred.
Throws: Any exception thrown by the copy constructor of RandomAccessIterator1, or by the default constructor, copy constructor, or the copy assignment operator of the value type of RandomAccessIterator1, or the copy constructor or operator() of BinaryPredicate or Hash.
May throw bad_alloc if additional memory needed for internal data structures cannot be allocated.
template<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Mandates: RandomAccessIterator1 and RandomAccessIterator2 have the same value type.
Effects: Finds a subsequence of equal values in a sequence.
Returns: A pair of iterators i and j such that
  • i is the first iterator in the range [first, last - (pat_last_ - pat_first_)) such that for every non-negative integer n less than pat_last_ - pat_first_ the following condition holds: pred(*(i + n), *(pat_first_ + n)) != false, and
  • j == next(i, distance(pat_first_, pat_last_)).
Returns make_pair(first, first) if [pat_first_, pat_last_) is empty, otherwise returns make_pair(last, last) if no such iterator is found.
Complexity: At most (last - first) * (pat_last_ - pat_first_) applications of the predicate.

22.10.19 Class template hash [unord.hash]

The unordered associative containers defined in [unord] use specializations of the class template hash ([functional.syn]) as the default hash function.
Each specialization of hash is either enabled or disabled, as described below.
[Note 1: 
Enabled specializations meet the Cpp17Hash requirements, and disabled specializations do not.
— end note]
Each header that declares the template hash provides enabled specializations of hash for nullptr_t and all cv-unqualified arithmetic, enumeration, and pointer types.
For any type Key for which neither the library nor the user provides an explicit or partial specialization of the class template hash, hash<Key> is disabled.
If the library provides an explicit or partial specialization of hash<Key>, that specialization is enabled except as noted otherwise, and its member functions are noexcept except as noted otherwise.
If H is a disabled specialization of hash, these values are false: is_default_constructible_v<H>, is_copy_constructible_v<H>, is_move_constructible_v<H>, is_copy_assignable_v<H>, and is_move_assignable_v<H>.
Disabled specializations of hash are not function object types ([function.objects]).
[Note 2: 
This means that the specialization of hash exists, but any attempts to use it as a Cpp17Hash will be ill-formed.
— end note]
An enabled specialization hash<Key> will:
  • meet the Cpp17Hash requirements (Table 37), with Key as the function call argument type, the Cpp17DefaultConstructible requirements (Table 30), the Cpp17CopyAssignable requirements (Table 34), the Cpp17Swappable requirements ([swappable.requirements]),
  • meet the requirement that if k1 == k2 is true, h(k1) == h(k2) is also true, where h is an object of type hash<Key> and k1 and k2 are objects of type Key;
  • meet the requirement that the expression h(k), where h is an object of type hash<Key> and k is an object of type Key, shall not throw an exception unless hash<Key> is a program-defined specialization.

22.11 Bit manipulation [bit]

22.11.1 General [bit.general]

The header <bit> provides components to access, manipulate and process both individual bits and bit sequences.

22.11.2 Header <bit> synopsis [bit.syn]

// all freestanding namespace std { // [bit.cast], bit_cast template<class To, class From> constexpr To bit_cast(const From& from) noexcept; // [bit.byteswap], byteswap template<class T> constexpr T byteswap(T value) noexcept; // [bit.pow.two], integral powers of 2 template<class T> constexpr bool has_single_bit(T x) noexcept; template<class T> constexpr T bit_ceil(T x); template<class T> constexpr T bit_floor(T x) noexcept; template<class T> constexpr int bit_width(T x) noexcept; // [bit.rotate], rotating template<class T> constexpr T rotl(T x, int s) noexcept; template<class T> constexpr T rotr(T x, int s) noexcept; // [bit.count], counting template<class T> constexpr int countl_zero(T x) noexcept; template<class T> constexpr int countl_one(T x) noexcept; template<class T> constexpr int countr_zero(T x) noexcept; template<class T> constexpr int countr_one(T x) noexcept; template<class T> constexpr int popcount(T x) noexcept; // [bit.endian], endian enum class endian { little = see below, big = see below, native = see below }; }

22.11.3 Function template bit_cast [bit.cast]

template<class To, class From> constexpr To bit_cast(const From& from) noexcept;
Constraints:
  • sizeof(To) == sizeof(From) is true;
  • is_trivially_copyable_v<To> is true; and
  • is_trivially_copyable_v<From> is true.
Returns: An object of type To.
Implicitly creates objects nested within the result ([intro.object]).
Each bit of the value representation of the result is equal to the corresponding bit in the object representation of 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 from or corresponds to a bit for which the smallest enclosing object is not within its lifetime or has an indeterminate value ([basic.indet]).
A bit in the value representation of the result is erroneous if it corresponds to a bit for which the smallest enclosing object has an erroneous value.
For each bit b in the value representation of the result that is indeterminate or erroneous, let u be the smallest object containing that bit enclosing b:
  • If u is of unsigned ordinary character type or std​::​byte type, u has an indeterminate value if any of the bits in its value representation are indeterminate, or otherwise has an erroneous value.
  • Otherwise, if b is indeterminate, the behavior is undefined.
  • Otherwise, the behavior is erroneous, and the result is as specified above.
The result does not otherwise contain any indeterminate or erroneous values.
Remarks: This function is constexpr if and only if To, From, and the types of all subobjects of To and From are types T such that:
  • is_union_v<T> is false;
  • is_pointer_v<T> is false;
  • is_member_pointer_v<T> is false;
  • is_volatile_v<T> is false; and
  • T has no non-static data members of reference type.

22.11.4 byteswap [bit.byteswap]

template<class T> constexpr T byteswap(T value) noexcept;
Constraints: T models integral.
Mandates: T does not have padding bits ([basic.types.general]).
Let the sequence R comprise the bytes of the object representation of value in reverse order.
Returns: An object v of type T such that each byte in the object representation of v is equal to the byte in the corresponding position in R.

22.11.5 Integral powers of 2 [bit.pow.two]

template<class T> constexpr bool has_single_bit(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: true if x is an integral power of two; false otherwise.
template<class T> constexpr T bit_ceil(T x);
Let N be the smallest power of 2 greater than or equal to x.
Constraints: T is an unsigned integer type ([basic.fundamental]).
Preconditions: N is representable as a value of type T.
Returns: N.
Throws: Nothing.
Remarks: A function call expression that violates the precondition in the Preconditions: element is not a core constant expression ([expr.const]).
template<class T> constexpr T bit_floor(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: If x == 0, 0; otherwise the maximal value y such that has_single_bit(y) is true and y <= x.
template<class T> constexpr int bit_width(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any fractional part discarded.

22.11.6 Rotating [bit.rotate]

In the following descriptions, let N denote numeric_limits<T>​::​digits.
template<class T> constexpr T rotl(T x, int s) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Let r be s % N.
Returns: If r is 0, x; if r is positive, (x << r) | (x >> (N - r)); if r is negative, rotr(x, -r).
template<class T> constexpr T rotr(T x, int s) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Let r be s % N.
Returns: If r is 0, x; if r is positive, (x >> r) | (x << (N - r)); if r is negative, rotl(x, -r).

22.11.7 Counting [bit.count]

In the following descriptions, let N denote numeric_limits<T>​::​digits.
template<class T> constexpr int countl_zero(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: The number of consecutive 0 bits in the value of x, starting from the most significant bit.
[Note 1: 
Returns N if x == 0.
— end note]
template<class T> constexpr int countl_one(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: The number of consecutive 1 bits in the value of x, starting from the most significant bit.
[Note 2: 
Returns N if x == numeric_limits<T>​::​max().
— end note]
template<class T> constexpr int countr_zero(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: The number of consecutive 0 bits in the value of x, starting from the least significant bit.
[Note 3: 
Returns N if x == 0.
— end note]
template<class T> constexpr int countr_one(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: The number of consecutive 1 bits in the value of x, starting from the least significant bit.
[Note 4: 
Returns N if x == numeric_limits<T>​::​max().
— end note]
template<class T> constexpr int popcount(T x) noexcept;
Constraints: T is an unsigned integer type ([basic.fundamental]).
Returns: The number of 1 bits in the value of x.

22.11.8 Endian [bit.endian]

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.
enum class endian { little = see below, big = see below, native = see below };
If all scalar types have size 1 byte, then all of endian​::​little, endian​::​big, and endian​::​native have the same value.
Otherwise, endian​::​little is not equal to endian​::​big.
If all scalar types are big-endian, endian​::​native is equal to endian​::​big.
If all scalar types are little-endian, endian​::​native is equal to endian​::​little.
Otherwise, endian​::​native is not equal to either endian​::​big or endian​::​little.

22.12 Header <stdbit.h> synopsis [stdbit.h.syn]

#define __STDC_VERSION_STDBIT_H__ 202311L #define __STDC_ENDIAN_BIG__ see below #define __STDC_ENDIAN_LITTLE__ see below #define __STDC_ENDIAN_NATIVE__ see below unsigned int stdc_leading_zeros_uc(unsigned char value); unsigned int stdc_leading_zeros_us(unsigned short value); unsigned int stdc_leading_zeros_ui(unsigned int value); unsigned int stdc_leading_zeros_ul(unsigned long int value); unsigned int stdc_leading_zeros_ull(unsigned long long int value); template<class T> see below stdc_leading_zeros(T value); unsigned int stdc_leading_ones_uc(unsigned char value); unsigned int stdc_leading_ones_us(unsigned short value); unsigned int stdc_leading_ones_ui(unsigned int value); unsigned int stdc_leading_ones_ul(unsigned long int value); unsigned int stdc_leading_ones_ull(unsigned long long int value); template<class T> see below stdc_leading_ones(T value); unsigned int stdc_trailing_zeros_uc(unsigned char value); unsigned int stdc_trailing_zeros_us(unsigned short value); unsigned int stdc_trailing_zeros_ui(unsigned int value); unsigned int stdc_trailing_zeros_ul(unsigned long int value); unsigned int stdc_trailing_zeros_ull(unsigned long long int value); template<class T> see below stdc_trailing_zeros(T value); unsigned int stdc_trailing_ones_uc(unsigned char value); unsigned int stdc_trailing_ones_us(unsigned short value); unsigned int stdc_trailing_ones_ui(unsigned int value); unsigned int stdc_trailing_ones_ul(unsigned long int value); unsigned int stdc_trailing_ones_ull(unsigned long long int value); template<class T> see below stdc_trailing_ones(T value); unsigned int stdc_first_leading_zero_uc(unsigned char value); unsigned int stdc_first_leading_zero_us(unsigned short value); unsigned int stdc_first_leading_zero_ui(unsigned int value); unsigned int stdc_first_leading_zero_ul(unsigned long int value); unsigned int stdc_first_leading_zero_ull(unsigned long long int value); template<class T> see below stdc_first_leading_zero(T value); unsigned int stdc_first_leading_one_uc(unsigned char value); unsigned int stdc_first_leading_one_us(unsigned short value); unsigned int stdc_first_leading_one_ui(unsigned int value); unsigned int stdc_first_leading_one_ul(unsigned long int value); unsigned int stdc_first_leading_one_ull(unsigned long long int value); template<class T> see below stdc_first_leading_one(T value); unsigned int stdc_first_trailing_zero_uc(unsigned char value); unsigned int stdc_first_trailing_zero_us(unsigned short value); unsigned int stdc_first_trailing_zero_ui(unsigned int value); unsigned int stdc_first_trailing_zero_ul(unsigned long int value); unsigned int stdc_first_trailing_zero_ull(unsigned long long int value); template<class T> see below stdc_first_trailing_zero(T value); unsigned int stdc_first_trailing_one_uc(unsigned char value); unsigned int stdc_first_trailing_one_us(unsigned short value); unsigned int stdc_first_trailing_one_ui(unsigned int value); unsigned int stdc_first_trailing_one_ul(unsigned long int value); unsigned int stdc_first_trailing_one_ull(unsigned long long int value); template<class T> see below stdc_first_trailing_one(T value); unsigned int stdc_count_zeros_uc(unsigned char value); unsigned int stdc_count_zeros_us(unsigned short value); unsigned int stdc_count_zeros_ui(unsigned int value); unsigned int stdc_count_zeros_ul(unsigned long int value); unsigned int stdc_count_zeros_ull(unsigned long long int value); template<class T> see below stdc_count_zeros(T value); unsigned int stdc_count_ones_uc(unsigned char value); unsigned int stdc_count_ones_us(unsigned short value); unsigned int stdc_count_ones_ui(unsigned int value); unsigned int stdc_count_ones_ul(unsigned long int value); unsigned int stdc_count_ones_ull(unsigned long long int value); template<class T> see below stdc_count_ones(T value); bool stdc_has_single_bit_uc(unsigned char value); bool stdc_has_single_bit_us(unsigned short value); bool stdc_has_single_bit_ui(unsigned int value); bool stdc_has_single_bit_ul(unsigned long int value); bool stdc_has_single_bit_ull(unsigned long long int value); template<class T> bool stdc_has_single_bit(T value); unsigned int stdc_bit_width_uc(unsigned char value); unsigned int stdc_bit_width_us(unsigned short value); unsigned int stdc_bit_width_ui(unsigned int value); unsigned int stdc_bit_width_ul(unsigned long int value); unsigned int stdc_bit_width_ull(unsigned long long int value); template<class T> see below stdc_bit_width(T value); unsigned char stdc_bit_floor_uc(unsigned char value); unsigned short stdc_bit_floor_us(unsigned short value); unsigned int stdc_bit_floor_ui(unsigned int value); unsigned long int stdc_bit_floor_ul(unsigned long int value); unsigned long long int stdc_bit_floor_ull(unsigned long long int value); template<class T> T stdc_bit_floor(T value); unsigned char stdc_bit_ceil_uc(unsigned char value); unsigned short stdc_bit_ceil_us(unsigned short value); unsigned int stdc_bit_ceil_ui(unsigned int value); unsigned long int stdc_bit_ceil_ul(unsigned long int value); unsigned long long int stdc_bit_ceil_ull(unsigned long long int value); template<class T> T stdc_bit_ceil(T value);
For a function template whose return type is not specified above, the return type is an implementation-defined unsigned integer type large enough to represent all possible result values.
Each function template has the same semantics as the corresponding type-generic function with the same name specified in ISO/IEC 9899:2024, 7.18.
Mandates: T is an unsigned integer type.
Otherwise, the contents and meaning of the header <stdbit.h> are the same as the C standard library header <stdbit.h>.
See also: ISO/IEC 9899:2024, 7.18

23 Containers library [containers]

23.1 General [containers.general]

This Clause describes components that C++ programs may use to organize collections of information.
The following subclauses describe container requirements, and components for sequence containers and associative containers, as summarized in Table 69.
Table 69 — Containers library summary [tab:containers.summary]
Subclause
Header
Requirements
Sequence containers
<array>, <deque>, <forward_list>, <inplace_vector>,
<list>, <vector>
Associative containers
<map>, <set>
Unordered associative containers
<unordered_map>, <unordered_set>
Container adaptors
<queue>, <stack>, <flat_map>, <flat_set>
Views
<span>, <mdspan>

23.2 Requirements [container.requirements]

23.2.1 Preamble [container.requirements.pre]

Containers are objects that store other objects.
They control allocation and deallocation of these objects through constructors, destructors, insert and erase operations.
All of the complexity requirements in this Clause are stated solely in terms of the number of operations on the contained objects.
[Example 1: 
The copy constructor of type vector<vector<int>> has linear complexity, even though the complexity of copying each contained vector<int> is itself linear.
— end example]
Allocator-aware containers ([container.alloc.reqmts]) other than basic_string construct elements using the function allocator_traits<allocator_type>​::​rebind_traits<U>​::​​construct and destroy elements using the function allocator_traits<allocator_type>​::​rebind_traits<U>​::​​destroy ([allocator.traits.members]), where U is either allocator_type​::​value_type or an internal type used by the container.
These functions are called only for the container's element type, not for internal types used by the container.
[Note 1: 
This means, for example, that a node-based container would need to construct nodes containing aligned buffers and call construct to place the element into the buffer.
— end note]

23.2.2 General containers [container.requirements.general]

23.2.2.1 Introduction [container.intro.reqmts]

In [container.requirements.general],
  • X denotes a container class containing objects of type T,
  • a denotes a value of type X,
  • b and c denote values of type (possibly const) X,
  • i and j denote values of type (possibly const) X​::​iterator,
  • u denotes an identifier,
  • v denotes an lvalue of type (possibly const) X or an rvalue of type const X,
  • s and t denote non-const lvalues of type X, and
  • rv denotes a non-const rvalue of type X.
The following exposition-only concept is used in the definition of containers: template<class R, class T> concept container-compatible-range = // exposition only ranges::input_range<R> && convertible_to<ranges::range_reference_t<R>, T>;

23.2.2.2 Container requirements [container.reqmts]

A type X meets the container requirements if the following types, statements, and expressions are well-formed and have the specified semantics.
typename X::value_type
Result: T
Preconditions: T is Cpp17Erasable from X (see [container.alloc.reqmts], below).
typename X::reference
Result: T&
typename X::const_reference
Result: const T&
typename X::iterator
Result: A type that meets the forward iterator requirements ([forward.iterators]) with value type T.
The type X​::​iterator is convertible to X​::​const_iterator.
typename X::const_iterator
Result: A type that meets the requirements of a constant iterator and those of a forward iterator with value type T.
typename X::difference_type
Result: A signed integer type, identical to the difference type of X​::​iterator and X​::​const_iterator.
typename X::size_type
Result: An unsigned integer type that can represent any non-negative value of X​::​difference_type.
X u; X u = X();
Postconditions: u.empty()
Complexity: Constant.
X u(v); X u = v;
Preconditions: T is Cpp17CopyInsertable into X (see below).
Postconditions: u == v.
Complexity: Linear.
X u(rv); X u = rv;
Postconditions: u is equal to the value that rv had before this construction.
Complexity: Linear for array and inplace_vector and constant for all other standard containers.
t = v;
Result: X&.
Postconditions: t == v.
Complexity: Linear.
t = rv
Result: X&.
Effects: All existing elements of t are either move assigned to or destroyed.
Postconditions: If t and rv do not refer to the same object, t is equal to the value that rv had before this assignment.
Complexity: Linear.
a.~X()
Result: void.
Effects: Destroys every element of a; any memory obtained is deallocated.
Complexity: Linear.
b.begin()
Result: iterator; const_iterator for constant b.
Returns: An iterator referring to the first element in the container.
Complexity: Constant.
b.end()
Result: iterator; const_iterator for constant b.
Returns: An iterator which is the past-the-end value for the container.
Complexity: Constant.
b.cbegin()
Result: const_iterator.
Returns: const_cast<X const&>(b).begin()
Complexity: Constant.
b.cend()
Result: const_iterator.
Returns: const_cast<X const&>(b).end()
Complexity: Constant.
i <=> j
Result: strong_ordering.
Constraints: X​::​iterator meets the random access iterator requirements.
Complexity: Constant.
c == b
Preconditions: T meets the Cpp17EqualityComparable requirements.
Result: bool.
Returns: equal(c.begin(), c.end(), b.begin(), b.end())
[Note 1: 
The algorithm equal is defined in [alg.equal].
— end note]
Complexity: Constant if c.size() != b.size(), linear otherwise.
Remarks: == is an equivalence relation.
c != b
Effects: Equivalent to !(c == b).
t.swap(s)
Result: void.
Effects: Exchanges the contents of t and s.
Complexity: Linear for array and inplace_vector, and constant for all other standard containers.
swap(t, s)
Effects: Equivalent to t.swap(s).
c.size()
Result: size_type.
Returns: distance(c.begin(), c.end()), i.e., the number of elements in the container.
Complexity: Constant.
Remarks: The number of elements is defined by the rules of constructors, inserts, and erases.
c.max_size()
Result: size_type.
Returns: distance(begin(), end()) for the largest possible container.
Complexity: Constant.
c.empty()
Result: bool.
Returns: c.begin() == c.end()
Complexity: Constant.
Remarks: If the container is empty, then c.empty() is true.
In the expressions i == j i != j i < j i <= j i >= j i > j i <=> j i - j where i and j denote objects of a container's iterator type, either or both may be replaced by an object of the container's const_iterator type referring to the same element with no change in semantics.
Unless otherwise specified, all containers defined in this Clause obtain memory using an allocator (see [allocator.requirements]).
[Note 2: 
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 P or pointer_traits<P>​::​template rebind<unspecified>, where P is allocator_traits<allocator_type>​::​pointer.
— end note]
Copy constructors for these container types obtain an allocator by calling allocator_traits<allocator_type>​::​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 const allocator_type& argument.
[Note 3: 
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 swap().
Allocator replacement is performed by copy assignment, move assignment, or swapping of the allocator only if
  • allocator_traits<allocator_type>​::​propagate_on_container_copy_assignment​::​value,
  • allocator_traits<allocator_type>​::​propagate_on_container_move_assignment​::​value, or
  • allocator_traits<allocator_type>​::​propagate_on_container_swap​::​value
is true within the implementation of the corresponding container operation.
In all container types defined in this Clause, the member 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.
The expression a.swap(b), for containers a and b of a standard container type other than array and inplace_vector, shall exchange the values of a and b without invoking any move, copy, or swap operations on the individual container elements.
Any Compare, Pred, or Hash types belonging to a and b shall meet the Cpp17Swappable requirements and shall be exchanged by calling swap as described in [swappable.requirements].
If allocator_traits<allocator_type>​::​propagate_on_container_swap​::​value is true, then allocator_type shall meet the Cpp17Swappable requirements and the allocators of a and b shall also be exchanged by calling swap as described in [swappable.requirements].
Otherwise, the allocators shall not be swapped, and the behavior is undefined unless 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 a.end() before the swap will have value b.end() after the swap.
Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers], [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following additional requirements:
  • If an exception is thrown by an insert() or emplace() function while inserting a single element, that function has no effects.
  • If an exception is thrown by a push_back(), push_front(), emplace_back(), or emplace_front() function, that function has no effects.
  • No erase(), clear(), pop_back() or pop_front() function throws an exception.
  • No copy constructor or assignment operator of a returned iterator throws an exception.
  • No swap() function throws an exception.
  • No swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped.
    [Note 4: 
    The end() iterator does not refer to any element, so it can be invalidated.
    — end note]
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.
A contiguous container is a container whose member types iterator and const_iterator meet the Cpp17RandomAccessIterator requirements ([random.access.iterators]) and model contiguous_iterator ([iterator.concept.contiguous]).
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 A shall not qualify as an allocator unless it meets both of the following conditions:
  • The qualified-id A​::​value_type is valid and denotes a type ([temp.deduct]).
  • The expression declval<A&>().allocate(size_t{}) is well-formed when treated as an unevaluated operand.

23.2.2.3 Reversible container requirements [container.rev.reqmts]

A type X meets the reversible container requirements if X meets the container requirements, the iterator type of X belongs to the bidirectional or random access iterator categories ([iterator.requirements]), and the following types and expressions are well-formed and have the specified semantics.
typename X::reverse_iterator
Result: The type reverse_iterator<X​::​iterator>, an iterator type whose value type is T.
typename X::const_reverse_iterator
Result: The type reverse_iterator<X​::​const_iterator>, a constant iterator type whose value type is T.
a.rbegin()
Result: reverse_iterator; const_reverse_iterator for constant a.
Returns: reverse_iterator(end())
Complexity: Constant.
a.rend()
Result: reverse_iterator; const_reverse_iterator for constant a.
Returns: reverse_iterator(begin())
Complexity: Constant.
a.crbegin()
Result: const_reverse_iterator.
Returns: const_cast<X const&>(a).rbegin()
Complexity: Constant.
a.crend()
Result: const_reverse_iterator.
Returns: const_cast<X const&>(a).rend()
Complexity: Constant.

23.2.2.4 Optional container requirements [container.opt.reqmts]

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 lexicographical_compare_three_way meet the constexpr iterator requirements ([iterator.requirements.general]) then the operations described below are implemented by constexpr functions.
a <=> b
Result: synth-three-way-result<X​::​value_type>.
Preconditions: Either T models three_way_comparable, or < is defined for values of type (possibly const) T and < is a total ordering relationship.
Returns: lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end(),
synth-three-way)
[Note 1: 
The algorithm lexicographical_compare_three_way is defined in [algorithms].
— end note]
Complexity: Linear.

23.2.2.5 Allocator-aware containers [container.alloc.reqmts]

Except for array and inplace_vector, all of the containers defined in [containers], [stacktrace.basic], [basic.string], and [re.results] meet the additional requirements of an allocator-aware container, as described below.
Given an allocator type A and given a container type X having a value_type identical to T and an allocator_type identical to allocator_traits<A>​::​rebind_alloc<T> and given an lvalue m of type A, a pointer p of type T*, an expression v that denotes an lvalue of type T or const T or an rvalue of type const T, and an rvalue rv of type T, the following terms are defined.
If X is not allocator-aware or is a specialization of basic_string, the terms below are defined as if A were allocator<T> — no allocator object needs to be created and user specializations of allocator<T> are not instantiated:
  • T is Cpp17DefaultInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p)
  • An element of X is default-inserted if it is initialized by evaluation of the expression allocator_traits<A>::construct(m, p) where p is the address of the uninitialized storage for the element allocated within X.
  • T is Cpp17MoveInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p, rv) and its evaluation causes the following postcondition to hold: The value of *p is equivalent to the value of rv before the evaluation.
    [Note 1: 
    rv remains a valid object.
    Its state is unspecified.
    — end note]
  • T is Cpp17CopyInsertable into X means that, in addition to T being Cpp17MoveInsertable into X, the following expression is well-formed: allocator_traits<A>::construct(m, p, v) and its evaluation causes the following postcondition to hold: The value of v is unchanged and is equivalent to *p.
  • T is Cpp17EmplaceConstructible into X from args, for zero or more arguments args, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args)
  • T is Cpp17Erasable from X means that the following expression is well-formed: allocator_traits<A>::destroy(m, p)
[Note 2: 
A container calls allocator_traits<A>​::​construct(m, p, args) to construct an element at p using args, with m == get_allocator().
The default construct in allocator will call ​::​new((void*)p) T(args), but specialized allocators can choose a different definition.
— end note]
In this subclause,
  • X denotes an allocator-aware container class with a value_type of T using an allocator of type A,
  • u denotes a variable,
  • a and b denote non-const lvalues of type X,
  • c denotes an lvalue of type const X,
  • t denotes an lvalue or a const rvalue of type X,
  • rv denotes a non-const rvalue of type X, and
  • m is a value of type A.
A type X meets the allocator-aware container requirements if X meets the container requirements and the following types, statements, and expressions are well-formed and have the specified semantics.
typename X::allocator_type
Result: A
Mandates: allocator_type​::​value_type is the same as X​::​value_type.
c.get_allocator()
Result: A
Complexity: Constant.
X u; X u = X();
Preconditions: A meets the Cpp17DefaultConstructible requirements.
Postconditions: u.empty() returns true, u.get_allocator() == A().
Complexity: Constant.
X u(m);
Postconditions: u.empty() returns true, u.get_allocator() == m.
Complexity: Constant.
X u(t, m);
Preconditions: T is Cpp17CopyInsertable into X.
Postconditions: u == t, u.get_allocator() == m
Complexity: Linear.
X u(rv);
Postconditions: u has the same elements as rv had before this construction; the value of u.get_allocator() is the same as the value of rv.get_allocator() before this construction.
Complexity: Constant.
X u(rv, m);
Preconditions: T is Cpp17MoveInsertable into X.
Postconditions: u has the same elements, or copies of the elements, that rv had before this construction, u.get_allocator() == m.
Complexity: Constant if m == rv.get_allocator(), otherwise linear.
a = t
Result: X&.
Preconditions: T is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Postconditions: a == t is true.
Complexity: Linear.
a = rv
Result: X&.
Preconditions: If allocator_traits<allocator_type>​::​propagate_on_container_move_assignment​::​value is false, T is Cpp17MoveInsertable into X and Cpp17MoveAssignable.
Effects: All existing elements of a are either move assigned to or destroyed.
Postconditions: If a and rv do not refer to the same object, a is equal to the value that rv had before this assignment.
Complexity: Linear.
a.swap(b)
Result: void
Effects: Exchanges the contents of a and b.
Complexity: Constant.

23.2.3 Container data races [container.requirements.dataraces]

For purposes of avoiding data races ([res.on.data.races]), implementations shall consider the following functions to be const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at and, except in associative or unordered associative containers, operator[].
Notwithstanding [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 vector<bool>, are modified concurrently.
[Note 1: 
For a vector<int> x with a size greater than one, x[1] = 5 and *x.begin() = 10 can be executed concurrently without a data race, but x[0] = 5 and *x.begin() = 10 executed concurrently can result in a data race.
As an exception to the general rule, for a vector<bool> y, y[0] = true can race with y[1] = true.
— end note]

23.2.4 Sequence containers [sequence.reqmts]

A sequence container organizes a finite set of objects, all of the same type, into a strictly linear arrangement.
The library provides the following basic kinds of sequence containers: vector, inplace_vector, forward_list, list, and deque.
In addition, 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 stacks, queues, flat_maps, flat_multimaps, flat_sets, or flat_multisets, out of the basic sequence container kinds (or out of other program-defined sequence containers).
In this subclause,
  • X denotes a sequence container class,
  • a denotes a value of type X containing elements of type T,
  • u denotes the name of a variable being declared,
  • A denotes X​::​allocator_type if the qualified-id X​::​allocator_type is valid and denotes a type ([temp.deduct]) and allocator<T> if it doesn't,
  • i and j denote iterators that meet the Cpp17InputIterator requirements and refer to elements implicitly convertible to value_type,
  • [i, j) denotes a valid range,
  • rg denotes a value of a type R that models container-compatible-range<T>,
  • il designates an object of type initializer_list<value_type>,
  • n denotes a value of type X​::​size_type,
  • p denotes a valid constant iterator to a,
  • q denotes a valid dereferenceable constant iterator to a,
  • [q1, q2) denotes a valid range of constant iterators in a,
  • t denotes an lvalue or a const rvalue of X​::​value_type, and
  • rv denotes a non-const rvalue of X​::​value_type.
  • Args denotes a template parameter pack;
  • args denotes a function parameter pack with the pattern Args&&.
The complexities of the expressions are sequence dependent.
A type X meets the sequence container requirements if X meets the container requirements and the following statements and expressions are well-formed and have the specified semantics.
X u(n, t);
Preconditions: T is Cpp17CopyInsertable into X.
Effects: Constructs a sequence container with n copies of t.
Postconditions: distance(u.begin(), u.end()) == n is true.
X u(i, j);
Preconditions: T is Cpp17EmplaceConstructible into X from *i.
For vector, if the iterator does not meet the Cpp17ForwardIterator requirements ([forward.iterators]), T is also Cpp17MoveInsertable into X.
Effects: Constructs a sequence container equal to the range [i, j).
Each iterator in the range [i, j) is dereferenced exactly once.
Postconditions: distance(u.begin(), u.end()) == distance(i, j) is true.
X(from_range, rg)
Preconditions: T is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
For vector, if R models neither ranges​::​sized_range nor ranges​::​forward_range, T is also Cpp17MoveInsertable into X.
Effects: Constructs a sequence container equal to the range rg.
Each iterator in the range rg is dereferenced exactly once.
Postconditions: distance(begin(), end()) == ranges​::​distance(rg) is true.
X(il)
Effects: Equivalent to X(il.begin(), il.end()).
a = il
Result: X&.
Preconditions: T is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Effects: Assigns the range [il.begin(), il.end()) into a.
All existing elements of a are either assigned to or destroyed.
Returns: *this.
a.emplace(p, args)
Result: iterator.
Preconditions: T is Cpp17EmplaceConstructible into X from args.
For vector, inplace_vector, and deque, T is also Cpp17MoveInsertable into X and Cpp17MoveAssignable.
Effects: Inserts an object of type T constructed with std​::​forward<Args>(args)... before p.
[Note 1: 
args can directly or indirectly refer to a value in a.
— end note]
Returns: An iterator that points to the new element.
a.insert(p, t)
Result: iterator.
Preconditions: T is Cpp17CopyInsertable into X.
For vector, inplace_vector, and deque, T is also Cpp17CopyAssignable.
Effects: Inserts a copy of t before p.
Returns: An iterator that points to the copy of t inserted into a.
a.insert(p, rv)
Result: iterator.
Preconditions: T is Cpp17MoveInsertable into X.
For vector, inplace_vector, and deque, T is also Cpp17MoveAssignable.
Effects: Inserts a copy of rv before p.
Returns: An iterator that points to the copy of rv inserted into a.
a.insert(p, n, t)
Result: iterator.
Preconditions: T is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Effects: Inserts n copies of t before p.
Returns: An iterator that points to the copy of the first element inserted into a, or p if n == 0.
a.insert(p, i, j)
Result: iterator.
Preconditions: T is Cpp17EmplaceConstructible into X from *i.
For vector, inplace_vector, and deque, T is also Cpp17MoveInsertable into X, and T meets the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Swappable ([swappable.requirements]) requirements.
Neither i nor j are iterators into a.
Effects: Inserts copies of elements in [i, j) before p.
Each iterator in the range [i, j) shall be dereferenced exactly once.
Returns: An iterator that points to the copy of the first element inserted into a, or p if i == j.
a.insert_range(p, rg)
Result: iterator.
Preconditions: T is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
For vector, inplace_vector, and deque, T is also Cpp17MoveInsertable into X, and T meets the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Swappable ([swappable.requirements]) requirements.
rg and a do not overlap.
Effects: Inserts copies of elements in rg before p.
Each iterator in the range rg is dereferenced exactly once.
Returns: An iterator that points to the copy of the first element inserted into a, or p if rg is empty.
a.insert(p, il)
Effects: Equivalent to a.insert(p, il.begin(), il.end()).
a.erase(q)
Result: iterator.
Preconditions: For vector, inplace_vector, and deque, T is Cpp17MoveAssignable.
Effects: Erases the element pointed to by q.
Returns: An iterator that points to the element immediately following q prior to the element being erased.
If no such element exists, a.end() is returned.
a.erase(q1, q2)
Result: iterator.
Preconditions: For vector, inplace_vector, and deque, T is Cpp17MoveAssignable.
Effects: Erases the elements in the range [q1, q2).
Returns: An iterator that points to the element pointed to by q2 prior to any elements being erased.
If no such element exists, a.end() is returned.
a.clear()
Result: void
Effects: Destroys all elements in a.
Invalidates all references, pointers, and iterators referring to the elements of a and may invalidate the past-the-end iterator.
Postconditions: a.empty() is true.
Complexity: Linear.
a.assign(i, j)
Result: void
Preconditions: T is Cpp17EmplaceConstructible into X from *i and assignable from *i.
For vector, if the iterator does not meet the forward iterator requirements ([forward.iterators]), T is also Cpp17MoveInsertable into X.
Neither i nor j are iterators into a.
Effects: Replaces elements in a with a copy of [i, j).
Invalidates all references, pointers and iterators referring to the elements of a.
For vector and deque, also invalidates the past-the-end iterator.
Each iterator in the range [i, j) is dereferenced exactly once.
a.assign_range(rg)
Result: void
Mandates: assignable_from<T&, ranges​::​range_reference_t<R>> is modeled.
Preconditions: T is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
For vector, if R models neither ranges​::​sized_range nor ranges​::​forward_range, T is also Cpp17MoveInsertable into X.
rg and a do not overlap.
Effects: Replaces elements in a with a copy of each element in rg.
Invalidates all references, pointers, and iterators referring to the elements of a.
For vector and deque, also invalidates the past-the-end iterator.
Each iterator in the range rg is dereferenced exactly once.
a.assign(il)
Effects: Equivalent to a.assign(il.begin(), il.end()).
a.assign(n, t)
Result: void
Preconditions: T is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
t is not a reference into a.
Effects: Replaces elements in a with n copies of t.
Invalidates all references, pointers and iterators referring to the elements of a.
For vector and deque, also invalidates the past-the-end iterator.
For every sequence container defined in this Clause and in [strings]:
  • If the constructor template<class InputIterator> X(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.
  • If the member functions of the forms: template<class InputIterator> return-type F(const_iterator p, InputIterator first, InputIterator last); // such as insert template<class InputIterator> return-type F(InputIterator first, InputIterator last); // such as append, assign template<class InputIterator> return-type F(const_iterator i1, const_iterator i2, InputIterator first, InputIterator last); // such as replace are called with a type InputIterator that does not qualify as an input iterator, then these functions shall not participate in overload resolution.
  • A deduction guide for a sequence container shall not participate in overload resolution if it has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter, or if it has an Allocator template parameter and a type that does not qualify as an allocator is deduced for that parameter.
The following operations are provided for some types of sequence containers but not others.
Operations other than prepend_range and append_range are implemented so as to take amortized constant time.
a.front()
Result: reference; const_reference for constant a.
Returns: *a.begin()
Remarks: Required for basic_string, array, deque, forward_list, inplace_vector, list, and vector.
a.back()
Result: reference; const_reference for constant a.
Effects: Equivalent to: auto tmp = a.end(); --tmp; return *tmp;
Remarks: Required for basic_string, array, deque, inplace_vector, list, and vector.
a.emplace_front(args)
Result: reference
Preconditions: T is Cpp17EmplaceConstructible into X from args.
Effects: Prepends an object of type T constructed with std​::​forward<Args>(args)....
Returns: a.front().
Remarks: Required for deque, forward_list, and list.
a.emplace_back(args)
Result: reference
Preconditions: T is Cpp17EmplaceConstructible into X from args.
For vector, T is also Cpp17MoveInsertable into X.
Effects: Appends an object of type T constructed with std​::​forward<Args>(args)....
Returns: a.back().
Remarks: Required for deque, inplace_vector, list, and vector.
a.push_front(t)
Result: void
Preconditions: T is Cpp17CopyInsertable into X.
Effects: Prepends a copy of t.
Remarks: Required for deque, forward_list, and list.
a.push_front(rv)
Result: void
Preconditions: T is Cpp17MoveInsertable into X.
Effects: Prepends a copy of rv.
Remarks: Required for deque, forward_list, and list.
a.prepend_range(rg)
Result: void
Preconditions: T is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
For deque, T is also Cpp17MoveInsertable into X, and T meets the Cpp17MoveConstructible, Cpp17MoveAssignable, and Cpp17Swappable ([swappable.requirements]) requirements.
Effects: Inserts copies of elements in rg before begin().
Each iterator in the range rg is dereferenced exactly once.
[Note 2: 
The order of elements in rg is not reversed.
— end note]
Remarks: Required for deque, forward_list, and list.
a.push_back(t)
Result: void
Preconditions: T is Cpp17CopyInsertable into X.
Effects: Appends a copy of t.
Remarks: Required for basic_string, deque, inplace_vector, list, and vector.
a.push_back(rv)
Result: void
Preconditions: T is Cpp17MoveInsertable into X.
Effects: Appends a copy of rv.
Remarks: Required for basic_string, deque, inplace_vector, list, and vector.
a.append_range(rg)
Result: void
Preconditions: T is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
For vector, T is also Cpp17MoveInsertable into X.
Effects: Inserts copies of elements in rg before end().
Each iterator in the range rg is dereferenced exactly once.
Remarks: Required for deque, inplace_vector, list, and vector.
a.pop_front()
Result: void
Preconditions: a.empty() is false.
Effects: Destroys the first element.
Remarks: Required for deque, forward_list, and list.
a.pop_back()
Result: void
Preconditions: a.empty() is false.
Effects: Destroys the last element.
Remarks: Required for basic_string, deque, inplace_vector, list, and vector.
a[n]
Result: reference; const_reference for constant a
Effects: Equivalent to: return *(a.begin() + n);
Remarks: Required for basic_string, array, deque, inplace_vector, and vector.
a.at(n)
Result: reference; const_reference for constant a
Returns: *(a.begin() + n)
Throws: out_of_range if n >= a.size().
Remarks: Required for basic_string, array, deque, inplace_vector, and vector.

23.2.5 Node handles [container.node]

23.2.5.1 Overview [container.node.overview]

A node handle is an object that accepts ownership of a single element from an associative container ([associative.reqmts]) or an unordered associative container ([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 Table 70.
Table 70 — Container types with compatible nodes [tab:container.node.compat]
map<K, T, C1, A>
map<K, T, C2, A>
map<K, T, C1, A>
multimap<K, T, C2, A>
set<K, C1, A>
set<K, C2, A>
set<K, C1, A>
multiset<K, C2, A>
unordered_map<K, T, H1, E1, A>
unordered_map<K, T, H2, E2, A>
unordered_map<K, T, H1, E1, A>
unordered_multimap<K, T, H2, E2, A>
unordered_set<K, H1, E1, A>
unordered_set<K, H2, E2, A>
unordered_set<K, H1, E1, A>
unordered_multiset<K, H2, E2, A>
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.
Class node-handle is for exposition only.
If a user-defined specialization of pair exists for pair<const Key, T> or pair<Key, T>, where Key is the container's key_type and T is the container's mapped_type, the behavior of operations involving node handles is undefined.
template<unspecified> class node-handle { public: // These type declarations are described in [associative.reqmts] and [unord.req]. using value_type = see below; // not present for map containers using key_type = see below; // not present for set containers using mapped_type = see below; // not present for set containers using allocator_type = see below; private: using container_node_type = unspecified; // exposition only using ator_traits = allocator_traits<allocator_type>; // exposition only typename ator_traits::template rebind_traits<container_node_type>::pointer ptr_; // exposition only optional<allocator_type> alloc_; // exposition only public: // [container.node.cons], constructors, copy, and assignment constexpr node-handle() noexcept : ptr_(), alloc_() {} node-handle(node-handle&&) noexcept; node-handle& operator=(node-handle&&); // [container.node.dtor], destructor ~node-handle(); // [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; bool empty() const noexcept; // [container.node.modifiers], modifiers void swap(node-handle&) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value); friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } };

23.2.5.2 Constructors, copy, and assignment [container.node.cons]

node-handle(node-handle&& nh) noexcept;
Effects: Constructs a node-handle object initializing ptr_ with nh.ptr_.
Move constructs alloc_ with nh.alloc_.
Assigns nullptr to nh.ptr_ and assigns nullopt to nh.alloc_.
node-handle& operator=(node-handle&& nh);
Preconditions: Either !alloc_, or ator_traits​::​propagate_on_container_move_assignment​::​value is true, or alloc_ == nh.alloc_.
Effects:
  • If ptr_ != nullptr, destroys the value_type subobject in the container_node_type object pointed to by ptr_ by calling ator_traits​::​destroy, then deallocates ptr_ by calling ator_traits​::​template rebind_traits<container_node_type>​::​deallocate.
  • Assigns nh.ptr_ to ptr_.
  • If !alloc_ or ator_traits​::​propagate_on_container_move_assignment​::​value is true, move assigns nh.alloc_ to alloc_.
  • Assigns nullptr to nh.ptr_ and assigns nullopt to nh.alloc_.
Returns: *this.
Throws: Nothing.

23.2.5.3 Destructor [container.node.dtor]

~node-handle();
Effects: If ptr_ != nullptr, destroys the value_type subobject in the container_node_type object pointed to by ptr_ by calling ator_traits​::​destroy, then deallocates ptr_ by calling ator_traits​::​template rebind_traits<container_node_type>​::​deallocate.

23.2.5.4 Observers [container.node.observers]

value_type& value() const;
Preconditions: empty() == false.
Returns: A reference to the value_type subobject in the container_node_type object pointed to by ptr_.
Throws: Nothing.
key_type& key() const;
Preconditions: empty() == false.
Returns: A non-const reference to the key_type member of the value_type subobject in the container_node_type object pointed to by ptr_.
Throws: Nothing.
Remarks: Modifying the key through the returned reference is permitted.
mapped_type& mapped() const;
Preconditions: empty() == false.
Returns: A reference to the mapped_type member of the value_type subobject in the container_node_type object pointed to by ptr_.
Throws: Nothing.
allocator_type get_allocator() const;
Preconditions: empty() == false.
Returns: *alloc_.
Throws: Nothing.
explicit operator bool() const noexcept;
Returns: ptr_ != nullptr.
bool empty() const noexcept;
Returns: ptr_ == nullptr.

23.2.5.5 Modifiers [container.node.modifiers]

void swap(node-handle& nh) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value);
Preconditions: !alloc_, or !nh.alloc_, or ator_traits​::​propagate_on_container_swap​::​value is true, or alloc_ == nh.alloc_.
Effects: Calls swap(ptr_, nh.ptr_).
If !alloc_, or !nh.alloc_, or ator_traits​::​propagate_on_container_swap​::​value is true calls swap(alloc_, nh.alloc_).

23.2.6 Insert return type [container.insert.return]

The associative containers with unique keys and the unordered containers with unique keys have a member function insert that returns a nested type insert_return_type.
That return type is a specialization of the template specified in this subclause.
template<class Iterator, class NodeType> struct insert-return-type { Iterator position; bool inserted; NodeType node; };
The name insert-return-type is exposition only.
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.

23.2.7 Associative containers [associative.reqmts]

23.2.7.1 General [associative.reqmts.general]

Associative containers provide fast retrieval of data based on keys.
The library provides four basic kinds of associative containers: set, multiset, map and multimap.
The library also provides container adaptors that make it easy to construct abstract data types, such as flat_maps, flat_multimaps, flat_sets, or flat_multisets, out of the basic sequence container kinds (or out of other program-defined sequence containers).
Each associative container is parameterized on Key and an ordering relation Compare that induces a strict weak ordering ([alg.sorting]) on elements of Key.
In addition, map and multimap associate an arbitrary mapped type T with the Key.
The object of type Compare is called the comparison object of a container.
The phrase “equivalence of keys” means the equivalence relation imposed by the comparison object.
That is, two keys k1 and k2 are considered to be equivalent if for the comparison object comp, comp(k1, k2) == false && comp(k2, k1) == false.
[Note 1: 
This is not necessarily the same as the result of k1 == k2.
— end note]
For any two keys k1 and k2 in the same container, calling comp(k1, k2) shall always return the same value.
An associative container supports unique keys if it may contain at most one element for each key.
Otherwise, it supports equivalent keys.
The set and map classes support unique keys; the multiset and multimap classes support equivalent keys.
For multiset and multimap, insert, emplace, and erase preserve the relative ordering of equivalent elements.
For set and multiset the value type is the same as the key type.
For map and multimap it is equal to pair<const Key, T>.
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 iterator and const_iterator are constant iterators.
It is unspecified whether or not iterator and const_iterator are the same type.
[Note 2: 
iterator and const_iterator have identical semantics in this case, and iterator is convertible to const_iterator.
Users can avoid violating the one-definition rule by always using const_iterator in their function parameter lists.
— end note]
In this subclause,
  • X denotes an associative container class,
  • a denotes a value of type X,
  • a2 denotes a value of a type with nodes compatible with type X (Table 70),
  • b denotes a value of type X or const X,
  • u denotes the name of a variable being declared,
  • a_uniq denotes a value of type X when X supports unique keys,
  • a_eq denotes a value of type X when X supports multiple keys,
  • a_tran denotes a value of type X or const X when the qualified-id X​::​key_compare​::​is_transparent is valid and denotes a type ([temp.deduct]),
  • i and j meet the Cpp17InputIterator requirements and refer to elements implicitly convertible to value_type,
  • [i, j) denotes a valid range,
  • rg denotes a value of a type R that models container-compatible-range<value_type>,
  • p denotes a valid constant iterator to a,
  • q denotes a valid dereferenceable constant iterator to a,
  • r denotes a valid dereferenceable iterator to a,
  • [q1, q2) denotes a valid range of constant iterators in a,
  • il designates an object of type initializer_list<value_type>,
  • t denotes a value of type X​::​value_type,
  • k denotes a value of type X​::​key_type, and
  • c denotes a value of type X​::​key_compare or const X​::​key_compare;
  • kl is a value such that a is partitioned ([alg.sorting]) with respect to c(x, kl), with x the key value of e and e in a;
  • ku is a value such that a is partitioned with respect to !c(ku, x), with x the key value of e and e in a;
  • ke is a value such that a is partitioned with respect to c(x, ke) and !c(ke, x), with c(x, ke) implying !c(ke, x) and with x the key value of e and e in a;
  • kx is a value such that
    • a is partitioned with respect to c(x, kx) and !c(kx, x), with c(x, kx) implying !c(kx, x) and with x the key value of e and e in a, and
    • kx is not convertible to either iterator or const_iterator; and
  • A denotes the storage allocator used by X, if any, or allocator<X​::​value_type> otherwise,
  • m denotes an allocator of a type convertible to A, and nh denotes a non-const rvalue of type X​::​node_type.
A type X meets the associative container requirements if X meets all the requirements of an allocator-aware container ([container.alloc.reqmts]) and the following types, statements, and expressions are well-formed and have the specified semantics, except that for map and multimap, the requirements placed on value_type in [container.reqmts] apply instead to key_type and mapped_type.
[Note 3: 
For example, in some cases key_type and mapped_type need to be Cpp17CopyAssignable even though the associated value_type, pair<const key_type, mapped_type>, is not Cpp17CopyAssignable.
— end note]
typename X::key_type
Result: Key.
typename X::mapped_type
Result: T.
Remarks: For map and multimap only.
typename X::value_type
Result: Key for set and multiset only; pair<const Key, T> for map and multimap only.
Preconditions: X​::​value_type is Cpp17Erasable from X.
typename X::key_compare
Result: Compare.
Preconditions: key_compare is Cpp17CopyConstructible.
typename X::value_compare
Result: A binary predicate type.
It is the same as key_compare for set and multiset; is an ordering relation on pairs induced by the first component (i.e., Key) for map and multimap.
typename X::node_type
Result: A specialization of the node-handle class template ([container.node]), such that the public nested types are the same types as the corresponding types in X.
X(c)
Effects: Constructs an empty container.
Uses a copy of c as a comparison object.
Complexity: Constant.
X u = X(); X u;
Preconditions: key_compare meets the Cpp17DefaultConstructible requirements.
Effects: Constructs an empty container.
Uses Compare() as a comparison object.
Complexity: Constant.
X(i, j, c)
Preconditions: value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container and inserts elements from the range [i, j) into it; uses c as a comparison object.
Complexity: in general, where N has the value distance(i, j); linear if [i, j) is sorted with respect to value_comp().
X(i, j)
Preconditions: key_compare meets the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container and inserts elements from the range [i, j) into it; uses Compare() as a comparison object.
Complexity: in general, where N has the value distance(i, j); linear if [i, j) is sorted with respect to value_comp().
X(from_range, rg, c)
Preconditions: value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container and inserts each element from rg into it.
Uses c as the comparison object.
Complexity: in general, where N has the value ranges​::​distance(rg); linear if rg is sorted with respect to value_comp().
X(from_range, rg)
Preconditions: key_compare meets the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container and inserts each element from rg into it.
Uses Compare() as the comparison object.
Complexity: Same as X(from_range, rg, c).
X(il, c)
Effects: Equivalent to X(il.begin(), il.end(), c).
X(il)
Effects: Equivalent to X(il.begin(), il.end()).
a = il
Result: X&
Preconditions: value_type is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Effects: Assigns the range [il.begin(), il.end()) into a.
All existing elements of a are either assigned to or destroyed.
Complexity: in general, where N has the value il.size() + a.size(); linear if [il.begin(), il.end()) is sorted with respect to value_comp().
b.key_comp()
Result: X​::​key_compare
Returns: The comparison object out of which b was constructed.
Complexity: Constant.
b.value_comp()
Result: X​::​value_compare
Returns: An object of value_compare constructed out of the comparison object.
Complexity: Constant.
a_uniq.emplace(args)
Result: pair<iterator, bool>
Preconditions: value_type is Cpp17EmplaceConstructible into X from args.
Effects: Inserts a value_type object t constructed with std​::​forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t.
Returns: The bool component of the returned pair is 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 t.
Complexity: Logarithmic.
a_eq.emplace(args)
Result: iterator
Preconditions: value_type is Cpp17EmplaceConstructible into X from args.
Effects: Inserts a value_type object t constructed with std​::​forward<Args>(args)....
If a range containing elements equivalent to t exists in a_eq, t is inserted at the end of that range.
Returns: An iterator pointing to the newly inserted element.
Complexity: Logarithmic.
a.emplace_hint(p, args)
Result: iterator
Effects: Equivalent to a.emplace(std​::​forward<Args>(args)...), except that the element is inserted as close as possible to the position just prior to p.
Returns: An iterator pointing to the element with the key equivalent to the newly inserted element.
Complexity: Logarithmic in general, but amortized constant if the element is inserted right before p.
a_uniq.insert(t)
Result: pair<iterator, bool>
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Inserts t if and only if there is no element in the container with key equivalent to the key of t.
Returns: The bool component of the returned pair is 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 t.
Complexity: Logarithmic.
a_eq.insert(t)
Result: iterator
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Inserts t and returns the iterator pointing to the newly inserted element.
If a range containing elements equivalent to t exists in a_eq, t is inserted at the end of that range.
Complexity: Logarithmic.
a.insert(p, t)
Result: iterator
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Inserts t if and only if there is no element with key equivalent to the key of t in containers with unique keys; always inserts t in containers with equivalent keys.
t is inserted as close as possible to the position just prior to p.
Returns: An iterator pointing to the element with key equivalent to the key of t.
Complexity: Logarithmic in general, but amortized constant if t is inserted right before p.
a.insert(i, j)
Result: void
Preconditions: value_type is Cpp17EmplaceConstructible into X from *i.
Neither i nor j are iterators into a.
Effects: Inserts each element from the 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.
Complexity: , where N has the value distance(i, j).
a.insert_range(rg)
Result: void
Preconditions: value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
rg and a do not overlap.
Effects: Inserts each element from 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.
Complexity: , where N has the value ranges​::​distance(rg).
a.insert(il)
Effects: Equivalent to a.insert(il.begin(), il.end()).
a_uniq.insert(nh)
Result: insert_return_type
Preconditions: nh is empty or a_uniq.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect.
Otherwise, inserts the element owned by nh if and only if there is no element in the container with a key equivalent to nh.key().
Returns: If nh is empty, inserted is false, position is end(), and node is empty.
Otherwise if the insertion took place, inserted is true, position points to the inserted element, and node is empty; if the insertion failed, inserted is false, node has the previous value of nh, and position points to an element with a key equivalent to nh.key().
Complexity: Logarithmic.
a_eq.insert(nh)
Result: iterator
Preconditions: nh is empty or a_eq.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect and returns a_eq.end().
Otherwise, inserts the element owned by nh and returns an iterator pointing to the newly inserted element.
If a range containing elements with keys equivalent to nh.key() exists in a_eq, the element is inserted at the end of that range.
Postconditions: nh is empty.
Complexity: Logarithmic.
a.insert(p, nh)
Result: iterator
Preconditions: nh is empty or a.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect and returns a.end().
Otherwise, inserts the element owned by nh if and only if there is no element with key equivalent to nh.key() in containers with unique keys; always inserts the element owned by nh in containers with equivalent keys.
The element is inserted as close as possible to the position just prior to p.
Postconditions: nh is empty if insertion succeeds, unchanged if insertion fails.
Returns: An iterator pointing to the element with key equivalent to nh.key().
Complexity: Logarithmic in general, but amortized constant if the element is inserted right before p.
a.extract(k)
Result: node_type
Effects: Removes the first element in the container with key equivalent to k.
Returns: A node_type owning the element if found, otherwise an empty node_type.
Complexity:
a_tran.extract(kx)
Result: node_type
Effects: Removes the first element in the container with key r such that !c(r, kx) && !c(kx, r) is true.
Returns: A node_type owning the element if found, otherwise an empty node_type.
Complexity:
a.extract(q)
Result: node_type
Effects: Removes the element pointed to by q.
Returns: A node_type owning that element.
Complexity: Amortized constant.
a.merge(a2)
Result: void
Preconditions: a.get_allocator() == a2.get_allocator().
Effects: Attempts to extract each element in a2 and insert it into a using the comparison object of a.
In containers with unique keys, if there is an element in a with key equivalent to the key of an element from a2, then that element is not extracted from a2.
Postconditions: Pointers and references to the transferred elements of a2 refer to those same elements but as members of a.
Iterators referring to the transferred elements will continue to refer to their elements, but they now behave as iterators into a, not into a2.
Throws: Nothing unless the comparison object throws.
Complexity: , where N has the value a2.size().
a.erase(k)
Result: size_type
Effects: Erases all elements in the container with key equivalent to k.
Returns: The number of erased elements.
Complexity:
a_tran.erase(kx)
Result: size_type
Effects: Erases all elements in the container with key r such that !c(r, kx) && !c(kx, r) is true.
Returns: The number of erased elements.
Complexity:
a.erase(q)
Result: iterator
Effects: Erases the element pointed to by q.
Returns: An iterator pointing to the element immediately following q prior to the element being erased.
If no such element exists, returns a.end().
Complexity: Amortized constant.
a.erase(r)
Result: iterator
Effects: Erases the element pointed to by r.
Returns: An iterator pointing to the element immediately following r prior to the element being erased.
If no such element exists, returns a.end().
Complexity: Amortized constant.
a.erase(q1, q2)
Result: iterator
Effects: Erases all the elements in the range [q1, q2).
Returns: An iterator pointing to the element pointed to by q2 prior to any elements being erased.
If no such element exists, a.end() is returned.
Complexity: , where N has the value distance(q1, q2).
a.clear()
Effects: Equivalent to a.erase(a.begin(), a.end()).
Postconditions: a.empty() is true.
Complexity: Linear in a.size().
b.find(k)
Result: iterator; const_iterator for constant b.
Returns: An iterator pointing to an element with the key equivalent to k, or b.end() if such an element is not found.
Complexity: Logarithmic.
a_tran.find(ke)
Result: iterator; const_iterator for constant a_tran.
Returns: An iterator pointing to an element with key r such that !c(r, ke) && !c(ke, r) is true, or a_tran.end() if such an element is not found.
Complexity: Logarithmic.
b.count(k)
Result: size_type
Returns: The number of elements with key equivalent to k.
Complexity:
a_tran.count(ke)
Result: size_type
Returns: The number of elements with key r such that !c(r, ke) && !c(ke, r).
Complexity:
b.contains(k)
Result: bool
Effects: Equivalent to: return b.find(k) != b.end();
a_tran.contains(ke)
Result: bool
Effects: Equivalent to: return a_tran.find(ke) != a_tran.end();
b.lower_bound(k)
Result: iterator; const_iterator for constant b.
Returns: An iterator pointing to the first element with key not less than k, or b.end() if such an element is not found.
Complexity: Logarithmic.
a_tran.lower_bound(kl)
Result: iterator; const_iterator for constant a_tran.
Returns: An iterator pointing to the first element with key r such that !c(r, kl), or a_tran.end() if such an element is not found.
Complexity: Logarithmic.
b.upper_bound(k)
Result: iterator; const_iterator for constant b.
Returns: An iterator pointing to the first element with key greater than k, or b.end() if such an element is not found.
Complexity: Logarithmic.
a_tran.upper_bound(ku)
Result: iterator; const_iterator for constant a_tran.
Returns: An iterator pointing to the first element with key r such that c(ku, r), or a_tran.end() if such an element is not found.
Complexity: Logarithmic.
b.equal_range(k)
Result: pair<iterator, iterator>; pair<const_iterator, const_iterator> for constant b.
Effects: Equivalent to: return make_pair(b.lower_bound(k), b.upper_bound(k));
Complexity: Logarithmic.
a_tran.equal_range(ke)
Result: pair<iterator, iterator>; pair<const_iterator, const_iterator> for constant a_tran.
Effects: Equivalent to: return make_pair(a_tran.lower_bound(ke), a_tran.upper_bound(ke));
Complexity: Logarithmic.
The insert, insert_range, and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
The 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 node_type is undefined behavior.
References and pointers to an element obtained while it is owned by a node_type are invalidated if the element is successfully inserted.
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 i and j such that distance from i to j is positive, the following condition holds: value_comp(*j, *i) == false
For associative containers with unique keys the stronger condition holds: value_comp(*i, *j) != false
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.
The member function templates find, count, contains, lower_bound, upper_bound, equal_range, erase, and extract shall not participate in overload resolution unless the qualified-id Compare​::​is_transparent is valid and denotes a type ([temp.deduct]).
Additionally, the member function templates extract and erase shall not participate in overload resolution if is_convertible_v<K&&, iterator> || is_convertible_v<K&&, const_iterator> is true, where K is the type substituted as the first template argument.
A deduction guide for an associative container shall not participate in overload resolution if any of the following are true:
  • It has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
  • It has an Allocator template parameter and a type that does not qualify as an allocator is deduced for that parameter.
  • It has a Compare template parameter and a type that qualifies as an allocator is deduced for that parameter.

23.2.7.2 Exception safety guarantees [associative.reqmts.except]

For associative containers, no clear() function throws an exception.
erase(k) does not throw an exception unless that exception is thrown by the container's Compare object (if any).
For associative containers, if an exception is thrown by any operation from within an insert or emplace function inserting a single element, the insertion has no effect.
For associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container's Compare object (if any).

23.2.8 Unordered associative containers [unord.req]

23.2.8.1 General [unord.req.general]

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: unordered_set, unordered_map, unordered_multiset, and unordered_multimap.
Unordered associative containers conform to the requirements for Containers ([container.requirements]), except that the expressions a == b and a != b have different semantics than for the other container types.
Each unordered associative container is parameterized by Key, by a function object type Hash that meets the Cpp17Hash requirements ([hash.requirements]) and acts as a hash function for argument values of type Key, and by a binary predicate Pred that induces an equivalence relation on values of type Key.
Additionally, unordered_map and unordered_multimap associate an arbitrary mapped type T with the Key.
The container's object of type Hash — denoted by hash — is called the hash function of the container.
The container's object of type Pred — denoted by pred — is called the key equality predicate of the container.
Two values k1 and k2 are considered equivalent if the container's key equality predicate pred(k1, k2) is valid and returns true when passed those values.
If k1 and k2 are equivalent, the container's hash function shall return the same value for both.
[Note 1: 
Thus, when an unordered associative container is instantiated with a non-default Pred parameter it usually needs a non-default Hash parameter as well.
— end note]
For any two keys k1 and k2 in the same container, calling pred(k1, k2) shall always return the same value.
For any key k in a container, calling hash(k) shall always return the same value.
An unordered associative container supports unique keys if it may contain at most one element for each key.
Otherwise, it supports equivalent keys.
unordered_set and unordered_map support unique keys.
unordered_multiset and 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 equivalent-key groups 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.
For unordered_set and unordered_multiset the value type is the same as the key type.
For unordered_map and unordered_multimap it is pair<const Key, T>.
For unordered containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators.
It is unspecified whether or not iterator and const_iterator are the same type.
[Note 2: 
iterator and const_iterator have identical semantics in this case, and iterator is convertible to const_iterator.
Users can avoid violating the one-definition rule by always using const_iterator in their function parameter lists.
— end note]
The elements of an unordered associative container are organized into 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 unordered_multiset and unordered_multimap, rehashing preserves the relative ordering of equivalent elements.
In this subclause,
  • X denotes an unordered associative container class,
  • a denotes a value of type X,
  • a2 denotes a value of a type with nodes compatible with type X (Table 70),
  • b denotes a value of type X or const X,
  • a_uniq denotes a value of type X when X supports unique keys,
  • a_eq denotes a value of type X when X supports equivalent keys,
  • a_tran denotes a value of type X or const X when the qualified-ids X​::​key_equal​::​is_transparent and X​::​hasher​::​is_transparent are both valid and denote types ([temp.deduct]),
  • i and j denote input iterators that refer to value_type,
  • [i, j) denotes a valid range,
  • rg denotes a value of a type R that models container-compatible-range<value_type>,
  • p and q2 denote valid constant iterators to a,
  • q and q1 denote valid dereferenceable constant iterators to a,
  • r denotes a valid dereferenceable iterator to a,
  • [q1, q2) denotes a valid range in a,
  • il denotes a value of type initializer_list<value_type>,
  • t denotes a value of type X​::​value_type,
  • k denotes a value of type key_type,
  • hf denotes a value of type hasher or const hasher,
  • eq denotes a value of type key_equal or const key_equal,
  • ke is a value such that
    • eq(r1, ke) == eq(ke, r1),
    • hf(r1) == hf(ke) if eq(r1, ke) is true, and
    • if any two of eq(r1, ke), eq(r2, ke), and eq(r1, r2) are true, then all three are true,
    where r1 and r2 are keys of elements in a_tran,
  • kx is a value such that
    • eq(r1, kx) == eq(kx, r1),
    • hf(r1) == hf(kx) if eq(r1, kx) is true,
    • if any two of eq(r1, kx), eq(r2, kx), and eq(r1, r2) are true, then all three are true, and
    • kx is not convertible to either iterator or const_iterator,
    where r1 and r2 are keys of elements in a_tran,
  • n denotes a value of type size_type,
  • z denotes a value of type float, and
  • nh denotes an rvalue of type X​::​node_type.
A type X meets the unordered associative container requirements if X meets all the requirements of an allocator-aware container ([container.alloc.reqmts]) and the following types, statements, and expressions are well-formed and have the specified semantics, except that for unordered_map and unordered_multimap, the requirements placed on value_type in [container.reqmts] apply instead to key_type and mapped_type.
[Note 3: 
For example, key_type and mapped_type sometimes need to be Cpp17CopyAssignable even though the associated value_type, pair<const key_type, mapped_type>, is not Cpp17CopyAssignable.
— end note]
typename X::key_type
Result: Key.
typename X::mapped_type
Result: T.
Remarks: For unordered_map and unordered_multimap only.
typename X::value_type
Result: Key for unordered_set and unordered_multiset only; pair<const Key, T> for unordered_map and unordered_multimap only.
Preconditions: value_type is Cpp17Erasable from X.
typename X::hasher
Result: Hash.
Preconditions: Hash is a unary function object type such that the expression hf(k) has type size_t.
typename X::key_equal
Result: Pred.
Preconditions: Pred meets the Cpp17CopyConstructible requirements.
Pred is a binary predicate that takes two arguments of type Key.
Pred is an equivalence relation.
typename X::local_iterator
Result: An iterator type whose category, value type, difference type, and pointer and reference types are the same as X​::​iterator's.
[Note 4: 
A local_iterator object can be used to iterate through a single bucket, but cannot be used to iterate across buckets.
— end note]
typename X::const_local_iterator
Result: An iterator type whose category, value type, difference type, and pointer and reference types are the same as X​::​const_iterator's.
[Note 5: 
A const_local_iterator object can be used to iterate through a single bucket, but cannot be used to iterate across buckets.
— end note]
typename X::node_type
Result: A specialization of a node-handle class template ([container.node]), such that the public nested types are the same types as the corresponding types in X.
X(n, hf, eq)
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and eq as the key equality predicate.
Complexity:
X(n, hf)
Preconditions: key_equal meets the Cpp17DefaultConstructible requirements.
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and key_equal() as the key equality predicate.
Complexity:
X(n)
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
Effects: Constructs an empty container with at least n buckets, using hasher() as the hash function and key_equal() as the key equality predicate.
Complexity:
X a = X(); X a;
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
Effects: Constructs an empty container with an unspecified number of buckets, using hasher() as the hash function and key_equal() as the key equality predicate.
Complexity: Constant.
X(i, j, n, hf, eq)
Preconditions: value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and eq as the key equality predicate, and inserts elements from [i, j) into it.
Complexity: Average case (N is distance(i, j)), worst case .
X(i, j, n, hf)
Preconditions: key_equal meets the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and key_equal() as the key equality predicate, and inserts elements from [i, j) into it.
Complexity: Average case (N is distance(i, j)), worst case .
X(i, j, n)
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container with at least n buckets, using hasher() as the hash function and key_equal() as the key equality predicate, and inserts elements from [i, j) into it.
Complexity: Average case (N is distance(i, j)), worst case .
X(i, j)
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *i.
Effects: Constructs an empty container with an unspecified number of buckets, using hasher() as the hash function and key_equal() as the key equality predicate, and inserts elements from [i, j) into it.
Complexity: Average case (N is distance(i, j)), worst case .
X(from_range, rg, n, hf, eq)
Preconditions: value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and eq as the key equality predicate, and inserts elements from rg into it.
Complexity: Average case (N is ranges​::​distance(rg)), worst case .
X(from_range, rg, n, hf)
Preconditions: key_equal meets the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container with at least n buckets, using hf as the hash function and key_equal() as the key equality predicate, and inserts elements from rg into it.
Complexity: Average case (N is ranges​::​distance(rg)), worst case .
X(from_range, rg, n)
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container with at least n buckets, using hasher() as the hash function and key_equal() as the key equality predicate, and inserts elements from rg into it.
Complexity: Average case (N is ranges​::​distance(rg)), worst case .
X(from_range, rg)
Preconditions: hasher and key_equal meet the Cpp17DefaultConstructible requirements.
value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
Effects: Constructs an empty container with an unspecified number of buckets, using hasher() as the hash function and key_equal() as the key equality predicate, and inserts elements from rg into it.
Complexity: Average case (N is ranges​::​distance(rg)), worst case .
X(il)
Effects: Equivalent to X(il.begin(), il.end()).
X(il, n)
Effects: Equivalent to X(il.begin(), il.end(), n).
X(il, n, hf)
Effects: Equivalent to X(il.begin(), il.end(), n, hf).
X(il, n, hf, eq)
Effects: Equivalent to X(il.begin(), il.end(), n, hf, eq).
X(b)
Effects: In addition to the container requirements ([container.reqmts]), copies the hash function, predicate, and maximum load factor.
Complexity: Average case linear in b.size(), worst case quadratic.
a = b
Result: X&
Effects: In addition to the container requirements, copies the hash function, predicate, and maximum load factor.
Complexity: Average case linear in b.size(), worst case quadratic.
a = il
Result: X&
Preconditions: value_type is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Effects: Assigns the range [il.begin(), il.end()) into a.
All existing elements of a are either assigned to or destroyed.
Complexity: Average case linear in il.size(), worst case quadratic.
b.hash_function()
Result: hasher
Returns: b's hash function.
Complexity: Constant.
b.key_eq()
Result: key_equal
Returns: b's key equality predicate.
Complexity: Constant.
a_uniq.emplace(args)
Result: pair<iterator, bool>
Preconditions: value_type is Cpp17EmplaceConstructible into X from args.
Effects: Inserts a value_type object t constructed with std​::​forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t.
Returns: The bool component of the returned pair is 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 t.
Complexity: Average case , worst case .
a_eq.emplace(args)
Result: iterator
Preconditions: value_type is Cpp17EmplaceConstructible into X from args.
Effects: Inserts a value_type object t constructed with std​::​forward<Args>(args)....
Returns: An iterator pointing to the newly inserted element.
Complexity: Average case , worst case .
a.emplace_hint(p, args)
Result: iterator
Preconditions: value_type is Cpp17EmplaceConstructible into X from args.
Effects: Equivalent to a.emplace(std​::​forward<Args>(args)...).
Returns: An iterator pointing to the element with the key equivalent to the newly inserted element.
The const_iterator p is a hint pointing to where the search should start.
Implementations are permitted to ignore the hint.
Complexity: Average case , worst case .
a_uniq.insert(t)
Result: pair<iterator, bool>
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Inserts t if and only if there is no element in the container with key equivalent to the key of t.
Returns: The bool component of the returned pair indicates whether the insertion takes place, and the iterator component points to the element with key equivalent to the key of t.
Complexity: Average case , worst case .
a_eq.insert(t)
Result: iterator
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Inserts t.
Returns: An iterator pointing to the newly inserted element.
Complexity: Average case , worst case .
a.insert(p, t)
Result: iterator
Preconditions: If t is a non-const rvalue, value_type is Cpp17MoveInsertable into X; otherwise, value_type is Cpp17CopyInsertable into X.
Effects: Equivalent to a.insert(t).
The iterator p is a hint pointing to where the search should start.
Implementations are permitted to ignore the hint.
Returns: An iterator pointing to the element with the key equivalent to that of t.
Complexity: Average case , worst case .
a.insert(i, j)
Result: void
Preconditions: value_type is Cpp17EmplaceConstructible into X from *i.
Neither i nor j are iterators into a.
Effects: Equivalent to a.insert(t) for each element in [i,j).
Complexity: Average case , where N is distance(i, j), worst case .
a.insert_range(rg)
Result: void
Preconditions: value_type is Cpp17EmplaceConstructible into X from *ranges​::​begin(rg).
rg and a do not overlap.
Effects: Equivalent to a.insert(t) for each element t in rg.
Complexity: Average case , where N is ranges​::​distance(rg), worst case .
a.insert(il)
Effects: Equivalent to a.insert(il.begin(), il.end()).
a_uniq.insert(nh)
Result: insert_return_type
Preconditions: nh is empty or a_uniq.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect.
Otherwise, inserts the element owned by nh if and only if there is no element in the container with a key equivalent to nh.key().
Postconditions: If nh is empty, inserted is false, position is end(), and node is empty.
Otherwise if the insertion took place, inserted is true, position points to the inserted element, and node is empty; if the insertion failed, inserted is false, node has the previous value of nh, and position points to an element with a key equivalent to nh.key().
Complexity: Average case , worst case .
a_eq.insert(nh)
Result: iterator
Preconditions: nh is empty or a_eq.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect and returns a_eq.end().
Otherwise, inserts the element owned by nh and returns an iterator pointing to the newly inserted element.
Postconditions: nh is empty.
Complexity: Average case , worst case .
a.insert(q, nh)
Result: iterator
Preconditions: nh is empty or a.get_allocator() == nh.get_allocator() is true.
Effects: If nh is empty, has no effect and returns a.end().
Otherwise, inserts the element owned by nh if and only if there is no element with key equivalent to nh.key() in containers with unique keys; always inserts the element owned by nh in containers with equivalent keys.
The iterator q is a hint pointing to where the search should start.
Implementations are permitted to ignore the hint.
Postconditions: nh is empty if insertion succeeds, unchanged if insertion fails.
Returns: An iterator pointing to the element with key equivalent to nh.key().
Complexity: Average case , worst case .
a.extract(k)
Result: node_type
Effects: Removes an element in the container with key equivalent to k.
Returns: A node_type owning the element if found, otherwise an empty node_type.
Complexity: Average case , worst case .
a_tran.extract(kx)
Result: node_type
Effects: Removes an element in the container with key equivalent to kx.
Returns: A node_type owning the element if found, otherwise an empty node_type.
Complexity: Average case , worst case .
a.extract(q)
Result: node_type
Effects: Removes the element pointed to by q.
Returns: A node_type owning that element.
Complexity: Average case , worst case .
a.merge(a2)
Result: void
Preconditions: a.get_allocator() == a2.get_allocator().
Effects: Attempts to extract each element in a2 and insert it into a using the hash function and key equality predicate of a.
In containers with unique keys, if there is an element in a with key equivalent to the key of an element from a2, then that element is not extracted from a2.
Postconditions: Pointers and references to the transferred elements of a2 refer to those same elements but as members of a.
Iterators referring to the transferred elements and all iterators referring to a will be invalidated, but iterators to elements remaining in a2 will remain valid.
Complexity: Average case , where N is a2.size(), worst case .
a.erase(k)
Result: size_type
Effects: Erases all elements with key equivalent to k.
Returns: The number of elements erased.
Complexity: Average case , worst case .
a_tran.erase(kx)
Result: size_type
Effects: Erases all elements with key equivalent to kx.
Returns: The number of elements erased.
Complexity: Average case , worst case .
a.erase(q)
Result: iterator
Effects: Erases the element pointed to by q.
Returns: The iterator immediately following q prior to the erasure.
Complexity: Average case , worst case .
a.erase(r)
Result: iterator
Effects: Erases the element pointed to by r.
Returns: The iterator immediately following r prior to the erasure.
Complexity: Average case , worst case .
a.erase(q1, q2)
Result: iterator
Effects: Erases all elements in the range [q1, q2).
Returns: The iterator immediately following the erased elements prior to the erasure.
Complexity: Average case linear in distance(q1, q2), worst case .
a.clear()
Result: void
Effects: Erases all elements in the container.
Postconditions: a.empty() is true.
Complexity: Linear in a.size().
b.find(k)
Result: iterator; const_iterator for constant b.
Returns: An iterator pointing to an element with key equivalent to k, or b.end() if no such element exists.
Complexity: Average case , worst case .
a_tran.find(ke)
Result: iterator; const_iterator for constant a_tran.
Returns: An iterator pointing to an element with key equivalent to ke, or a_tran.end() if no such element exists.
Complexity: Average case , worst case .
b.count(k)
Result: size_type
Returns: The number of elements with key equivalent to k.
Complexity: Average case , worst case .
a_tran.count(ke)
Result: size_type
Returns: The number of elements with key equivalent to ke.
Complexity: Average case , worst case .
b.contains(k)
Effects: Equivalent to b.find(k) != b.end().
a_tran.contains(ke)
Effects: Equivalent to a_tran.find(ke) != a_tran.end().
b.equal_range(k)
Result: pair<iterator, iterator>; pair<const_iterator, const_iterator> for constant b.
Returns: A range containing all elements with keys equivalent to k.
Returns make_pair(b.end(), b.end()) if no such elements exist.
Complexity: Average case , worst case .
a_tran.equal_range(ke)
Result: pair<iterator, iterator>; pair<const_iterator, const_iterator> for constant a_tran.
Returns: A range containing all elements with keys equivalent to ke.
Returns make_pair(a_tran.end(), a_tran.end()) if no such elements exist.
Complexity: Average case , worst case .
b.bucket_count()
Result: size_type
Returns: The number of buckets that b contains.
Complexity: Constant.
b.max_bucket_count()
Result: size_type
Returns: An upper bound on the number of buckets that b can ever contain.
Complexity: Constant.
b.bucket(k)
Result: size_type
Preconditions: b.bucket_count() > 0.
Returns: The index of the bucket in which elements with keys equivalent to k would be found, if any such element existed.
The return value is in the range [0, b.bucket_count()).
Complexity: Constant.
a_tran.bucket(ke)
Result: size_type
Preconditions: a_tran.bucket_count() > 0.
Postconditions: The return value is in the range [0, a_tran.bucket_count()).
Returns: The index of the bucket in which elements with keys equivalent to ke would be found, if any such element existed.
Complexity: Constant.
b.bucket_size(n)
Result: size_type
Preconditions: n shall be in the range [0, b.bucket_count()).
Returns: The number of elements in the bucket.
Complexity:
b.begin(n)
Result: local_iterator; const_local_iterator for constant b.
Preconditions: n is in the range [0, b.bucket_count()).
Returns: An iterator referring to the first element in the bucket.
If the bucket is empty, then b.begin(n) == b.end(n).
Complexity: Constant.
b.end(n)
Result: local_iterator; const_local_iterator for constant b.
Preconditions: n is in the range [0, b.bucket_count()).
Returns: An iterator which is the past-the-end value for the bucket.
Complexity: Constant.
b.cbegin(n)
Result: const_local_iterator
Preconditions: n shall be in the range [0, b.bucket_count()).
Returns: An iterator referring to the first element in the bucket.
If the bucket is empty, then b.cbegin(n) == b.cend(n).
Complexity: Constant.
b.cend(n)
Result: const_local_iterator
Preconditions: n is in the range [0, b.bucket_count()).
Returns: An iterator which is the past-the-end value for the bucket.
Complexity: Constant.
b.load_factor()
Result: float
Returns: The average number of elements per bucket.
Complexity: Constant.
b.max_load_factor()
Result: 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.
Complexity: Constant.
a.max_load_factor(z)
Result: void
Preconditions: z is positive.
May change the container's maximum load factor, using z as a hint.
Complexity: Constant.
a.rehash(n)
Result: void
Postconditions: a.bucket_count() >= a.size() / a.max_load_factor() and a.bucket_count() >= n.
Complexity: Average case linear in a.size(), worst case quadratic.
a.reserve(n)
Effects: Equivalent to a.rehash(ceil(n / a.max_load_factor())).
Two unordered containers a and b compare equal if a.size() == b.size() and, for every equivalent-key group [Ea1, Ea2) obtained from a.equal_range(Ea1), there exists an equivalent-key group [Eb1, Eb2) obtained from b.equal_range(Ea1), such that is_permutation(Ea1, Ea2, Eb1, Eb2) returns true.
For unordered_set and unordered_map, the complexity of operator== (i.e., the number of calls to the == operator of the value_type, to the predicate returned by key_eq(), and to the hasher returned by hash_function()) is proportional to N in the average case and to in the worst case, where N is a.size().
For unordered_multiset and unordered_multimap, the complexity of operator== is proportional to in the average case and to in the worst case, where N is a.size(), and is the size of the equivalent-key group in a.
However, if the respective elements of each corresponding pair of equivalent-key groups and are arranged in the same order (as is commonly the case, e.g., if a and b are unmodified copies of the same container), then the average-case complexity for unordered_multiset and unordered_multimap becomes proportional to N (but worst-case complexity remains , e.g., for a pathologically bad hash function).
The behavior of a program that uses operator== or operator!= on unordered containers is undefined unless the Pred function object has the same behavior for both containers and the equality comparison function for Key is a refinement197 of the partition into equivalent-key groups produced by Pred.
The iterator types iterator and const_iterator of an unordered associative container are of at least the forward iterator category.
For unordered associative containers where the key type and value type are the same, both iterator and const_iterator are constant iterators.
The insert, insert_range, and emplace members shall not affect the validity of references to container elements, but may invalidate all iterators to the container.
The erase members shall invalidate only iterators and references to the erased elements, and preserve the relative order of the elements that are not erased.
The insert, insert_range, and emplace members shall not affect the validity of iterators if (N+n) <= z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container's bucket count, and z is the container's maximum load factor.
The extract members invalidate only iterators to the removed element, and preserve the relative order of the elements that are not erased; 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 node_type is undefined behavior.
References and pointers to an element obtained while it is owned by a node_type are invalidated if the element is successfully inserted.
The member function templates find, count, equal_range, contains, extract, erase, and bucket shall not participate in overload resolution unless the qualified-ids Pred​::​is_transparent and Hash​::​is_transparent are both valid and denote types ([temp.deduct]).
Additionally, the member function templates extract and erase shall not participate in overload resolution if is_convertible_v<K&&, iterator> || is_convertible_v<K&&, const_iterator> is true, where K is the type substituted as the first template argument.
A deduction guide for an unordered associative container shall not participate in overload resolution if any of the following are true:
  • It has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
  • It has an Allocator template parameter and a type that does not qualify as an allocator is deduced for that parameter.
  • It has a Hash template parameter and an integral type or a type that qualifies as an allocator is deduced for that parameter.
  • It has a Pred template parameter and a type that qualifies as an allocator is deduced for that parameter.
197)197)
Equality comparison is a refinement of partitioning if no two objects that compare equal fall into different partitions.

23.2.8.2 Exception safety guarantees [unord.req.except]

For unordered associative containers, no clear() function throws an exception.
erase(k) does not throw an exception unless that exception is thrown by the container's Hash or Pred object (if any).
For unordered associative containers, if an exception is thrown by any operation other than the container's hash function from within an insert or emplace function inserting a single element, the insertion has no effect.
For unordered associative containers, no swap function throws an exception unless that exception is thrown by the swap of the container's Hash or Pred object (if any).
For unordered associative containers, if an exception is thrown from within a rehash() function other than by the container's hash function or comparison function, the rehash() function has no effect.

23.3 Sequence containers [sequences]

23.3.1 General [sequences.general]

The headers <array>, <deque>, <forward_list>, <inplace_vector>, <list>, and <vector> define class templates that meet the requirements for sequence containers.
The following exposition-only alias template may appear in deduction guides for sequence containers: template<class InputIterator> using iter-value-type = typename iterator_traits<InputIterator>::value_type; // exposition only

23.3.2 Header <array> synopsis [array.syn]

// mostly freestanding #include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [array], class template array template<class T, size_t N> struct array; // partially freestanding template<class T, size_t N> constexpr bool operator==(const array<T, N>& x, const array<T, N>& y); template<class T, size_t N> constexpr synth-three-way-result<T> operator<=>(const array<T, N>& x, const array<T, N>& y); // [array.special], specialized algorithms template<class T, size_t N> constexpr void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y))); // [array.creation], array creation functions template<class T, size_t N> constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]); template<class T, size_t N> constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]); // [array.tuple], tuple interface template<class T> struct tuple_size; template<size_t I, class T> struct tuple_element; template<class T, size_t N> struct tuple_size<array<T, N>>; template<size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>; template<size_t I, class T, size_t N> constexpr T& get(array<T, N>&) noexcept; template<size_t I, class T, size_t N> constexpr T&& get(array<T, N>&&) noexcept; template<size_t I, class T, size_t N> constexpr const T& get(const array<T, N>&) noexcept; template<size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&&) noexcept; }

23.3.3 Class template array [array]

23.3.3.1 Overview [array.overview]

The header <array> defines a class template for storing fixed-size sequences of objects.
An array is a contiguous container.
An instance of array<T, N> stores N elements of type T, so that size() == N is an invariant.
An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.
An array meets all of the requirements of a container ([container.reqmts]) and of a reversible container ([container.rev.reqmts]), except that a default constructed array object is not empty if .
An array meets some of the requirements of a sequence container.
Descriptions are provided here only for operations on array that are not described in one of these tables and for operations where there is additional semantic information.
array<T, N> is a structural type ([temp.param]) if T is a structural type.
Two values a1 and a2 of type array<T, N> are template-argument-equivalent if and only if each pair of corresponding elements in a1 and a2 are template-argument-equivalent.
The types iterator and const_iterator meet the constexpr iterator requirements.
namespace std { template<class T, size_t N> struct array { // types using value_type = T; using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // no explicit construct/copy/destroy for aggregate type constexpr void fill(const T& u); constexpr void swap(array&) noexcept(is_nothrow_swappable_v<T>); // iterators constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacity constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); // freestanding-deleted constexpr const_reference at(size_type n) const; // freestanding-deleted constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; constexpr T * data() noexcept; constexpr const T * data() const noexcept; }; template<class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>; }

23.3.3.2 Constructors, copy, and assignment [array.cons]

An array relies on the implicitly-declared special member functions ([class.default.ctor], [class.dtor], [class.copy.ctor]) to conform to the container requirements table in [container.requirements].
In addition to the requirements specified in the container requirements table, the implicitly-declared move constructor and move assignment operator for array require that T be Cpp17MoveConstructible or Cpp17MoveAssignable, respectively.
template<class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;
Mandates: (is_same_v<T, U> && ...) is true.

23.3.3.3 Member functions [array.members]

constexpr size_type size() const noexcept;
Returns: N.
constexpr T* data() noexcept; constexpr const T* data() const noexcept;
Returns: A pointer such that [data(), data() + size()) is a valid range.
For a non-empty array, data() == addressof(front()) is true.
constexpr void fill(const T& u);
Effects: As if by fill_n(begin(), N, u).
constexpr void swap(array& y) noexcept(is_nothrow_swappable_v<T>);
Effects: Equivalent to swap_ranges(begin(), end(), y.begin()).
[Note 1: 
Unlike the swap function for other containers, array​::​swap takes linear time, can exit via an exception, and does not cause iterators to become associated with the other container.
— end note]

23.3.3.4 Specialized algorithms [array.special]

template<class T, size_t N> constexpr void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y)));
Constraints: N == 0 or is_swappable_v<T> is true.
Effects: As if by x.swap(y).
Complexity: Linear in N.

23.3.3.5 Zero-sized arrays [array.zero]

array shall provide support for the special case N == 0.
In the case that N == 0, begin() == end() == unique value.
The return value of data() is unspecified.
The effect of calling front() or back() for a zero-sized array is undefined.
Member function swap() shall have a non-throwing exception specification.

23.3.3.6 Array creation functions [array.creation]

template<class T, size_t N> constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]);
Mandates: is_array_v<T> is false and is_constructible_v<remove_cv_t<T>, T&> is true.
Preconditions: T meets the Cpp17CopyConstructible requirements.
Returns: {{ a[0], , a[N - 1] }}.
template<class T, size_t N> constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]);
Mandates: is_array_v<T> is false and is_constructible_v<remove_cv_t<T>, T> is true.
Preconditions: T meets the Cpp17MoveConstructible requirements.
Returns: {{ std​::​move(a[0]), , std​::​move(a[N - 1]) }}.

23.3.3.7 Tuple interface [array.tuple]

template<class T, size_t N> struct tuple_size<array<T, N>> : integral_constant<size_t, N> { };
template<size_t I, class T, size_t N> struct tuple_element<I, array<T, N>> { using type = T; };
Mandates: I < N is true.
template<size_t I, class T, size_t N> constexpr T& get(array<T, N>& a) noexcept; template<size_t I, class T, size_t N> constexpr T&& get(array<T, N>&& a) noexcept; template<size_t I, class T, size_t N> constexpr const T& get(const array<T, N>& a) noexcept; template<size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&& a) noexcept;
Mandates: I < N is true.
Returns: A reference to the element of a, where indexing is zero-based.

23.3.4 Header <deque> synopsis [deque.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [deque], class template deque template<class T, class Allocator = allocator<T>> class deque; template<class T, class Allocator> bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y); template<class T, class Allocator> synth-three-way-result<T> operator<=>(const deque<T, Allocator>& x, const deque<T, Allocator>& y); template<class T, class Allocator> void swap(deque<T, Allocator>& x, deque<T, Allocator>& y) noexcept(noexcept(x.swap(y))); // [deque.erasure], erasure template<class T, class Allocator, class U = T> typename deque<T, Allocator>::size_type erase(deque<T, Allocator>& c, const U& value); template<class T, class Allocator, class Predicate> typename deque<T, Allocator>::size_type erase_if(deque<T, Allocator>& c, Predicate pred); namespace pmr { template<class T> using deque = std::deque<T, polymorphic_allocator<T>>; } }

23.3.5 Class template deque [deque]

23.3.5.1 Overview [deque.overview]

A deque is a sequence container that supports random access iterators.
In addition, it supports constant time insert and erase operations at the beginning or the end; insert and erase in the middle take linear time.
That is, a deque is especially optimized for pushing and popping elements at the beginning and end.
Storage management is handled automatically.
A deque meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of a sequence container, including the optional sequence container requirements ([sequence.reqmts]).
Descriptions are provided here only for operations on deque that are not described in one of these tables or for operations where there is additional semantic information.
namespace std { template<class T, class Allocator = allocator<T>> class deque { public: // types using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // [deque.cons], construct/copy/destroy deque() : deque(Allocator()) { } explicit deque(const Allocator&); explicit deque(size_type n, const Allocator& = Allocator()); deque(size_type n, const T& value, const Allocator& = Allocator()); template<class InputIterator> deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); template<container-compatible-range<T> R> deque(from_range_t, R&& rg, const Allocator& = Allocator()); deque(const deque& x); deque(deque&&); deque(const deque&, const type_identity_t<Allocator>&); deque(deque&&, const type_identity_t<Allocator>&); deque(initializer_list<T>, const Allocator& = Allocator()); ~deque(); deque& operator=(const deque& x); deque& operator=(deque&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value); deque& operator=(initializer_list<T>); template<class InputIterator> void assign(InputIterator first, InputIterator last); template<container-compatible-range<T> R> void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list<T>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // [deque.capacity], capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz); void resize(size_type sz, const T& c); void shrink_to_fit(); // element access reference operator[](size_type n); const_reference operator[](size_type n) const; reference at(size_type n); const_reference at(size_type n) const; reference front(); const_reference front() const; reference back(); const_reference back() const; // [deque.modifiers], modifiers template<class... Args> reference emplace_front(Args&&... args); template<class... Args> reference emplace_back(Args&&... args); template<class... Args> iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); template<container-compatible-range<T> R> void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); template<container-compatible-range<T> 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<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list<T>); void pop_front(); void pop_back(); iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void swap(deque&) noexcept(allocator_traits<Allocator>::is_always_equal::value); void clear() noexcept; }; template<class InputIterator, class Allocator = allocator<iter-value-type<InputIterator>>> deque(InputIterator, InputIterator, Allocator = Allocator()) -> deque<iter-value-type<InputIterator>, Allocator>; template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> deque(from_range_t, R&&, Allocator = Allocator()) -> deque<ranges::range_value_t<R>, Allocator>; }

23.3.5.2 Constructors, copy, and assignment [deque.cons]

explicit deque(const Allocator&);
Effects: Constructs an empty deque, using the specified allocator.
Complexity: Constant.
explicit deque(size_type n, const Allocator& = Allocator());
Preconditions: T is Cpp17DefaultInsertable into deque.
Effects: Constructs a deque with n default-inserted elements using the specified allocator.
Complexity: Linear in n.
deque(size_type n, const T& value, const Allocator& = Allocator());
Preconditions: T is Cpp17CopyInsertable into deque.
Effects: Constructs a deque with n copies of value, using the specified allocator.
Complexity: Linear in n.
template<class InputIterator> deque(InputIterator first, InputIterator last, const Allocator& = Allocator());
Effects: Constructs a deque equal to the range [first, last), using the specified allocator.
Complexity: Linear in distance(first, last).
template<container-compatible-range<T> R> deque(from_range_t, R&& rg, const Allocator& = Allocator());
Effects: Constructs a deque with the elements of the range rg, using the specified allocator.
Complexity: Linear in ranges​::​distance(rg).

23.3.5.3 Capacity [deque.capacity]

void resize(size_type sz);
Preconditions: T is Cpp17MoveInsertable and Cpp17DefaultInsertable into deque.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() default-inserted elements to the sequence.
void resize(size_type sz, const T& c);
Preconditions: T is Cpp17CopyInsertable into deque.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() copies of c to the sequence.
void shrink_to_fit();
Preconditions: T is Cpp17MoveInsertable into deque.
Effects: shrink_to_fit is a non-binding request to reduce memory use but does not change the size of the sequence.
[Note 1: 
The request is non-binding to allow latitude for implementation-specific optimizations.
— end note]
If the size is equal to the old capacity, or if an exception is thrown other than by the move constructor of a non-Cpp17CopyInsertable T, then there are no effects.
Complexity: If the size is not equal to the old capacity, linear in the size of the sequence; otherwise constant.
Remarks: If the size is not equal to the old capacity, then invalidates all the references, pointers, and iterators referring to the elements in the sequence, as well as the past-the-end iterator.

23.3.5.4 Modifiers [deque.modifiers]

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<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list<T>); template<class... Args> reference emplace_front(Args&&... args); template<class... Args> reference emplace_back(Args&&... args); template<class... Args> iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); template<container-compatible-range<T> R> void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); template<container-compatible-range<T> R> void append_range(R&& rg);
Effects: An insertion in the middle of the deque invalidates all the iterators and references to elements of the deque.
An insertion at either end of the deque invalidates all the iterators to the deque, but has no effect on the validity of references to elements of the deque.
Complexity: The complexity is linear in the number of elements inserted plus the lesser of the distances to the beginning and end of the deque.
Inserting a single element at either the beginning or end of a deque always takes constant time and causes a single call to a constructor of T.
Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T, there are no effects.
If an exception is thrown while inserting a single element at either end, there are no effects.
Otherwise, if an exception is thrown by the move constructor of a non-Cpp17CopyInsertable T, the effects are unspecified.
iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void pop_front(); void pop_back();
Effects: An erase operation that erases the last element of a deque invalidates only the past-the-end iterator and all iterators and references to the erased elements.
An erase operation that erases the first element of a deque but not the last element invalidates only iterators and references to the erased elements.
An erase operation that erases neither the first element nor the last element of a deque invalidates the past-the-end iterator and all iterators and references to all the elements of the deque.
[Note 1: 
pop_front and pop_back are erase operations.
— end note]
Throws: Nothing unless an exception is thrown by the assignment operator of T.
Complexity: The number of calls to the destructor of T is the same as the number of elements erased, but the number of calls to the assignment operator of T is no more than the lesser of the number of elements before the erased elements and the number of elements after the erased elements.

23.3.5.5 Erasure [deque.erasure]

template<class T, class Allocator, class U = T> typename deque<T, Allocator>::size_type erase(deque<T, Allocator>& c, const U& value);
Effects: Equivalent to: auto it = remove(c.begin(), c.end(), value); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;
template<class T, class Allocator, class Predicate> typename deque<T, Allocator>::size_type erase_if(deque<T, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto it = remove_if(c.begin(), c.end(), pred); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;

23.3.6 Header <forward_list> synopsis [forward.list.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [forward.list], class template forward_list template<class T, class Allocator = allocator<T>> class forward_list; template<class T, class Allocator> bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y); template<class T, class Allocator> synth-three-way-result<T> operator<=>(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y); template<class T, class Allocator> void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) noexcept(noexcept(x.swap(y))); // [forward.list.erasure], erasure template<class T, class Allocator, class U = T> typename forward_list<T, Allocator>::size_type erase(forward_list<T, Allocator>& c, const U& value); template<class T, class Allocator, class Predicate> typename forward_list<T, Allocator>::size_type erase_if(forward_list<T, Allocator>& c, Predicate pred); namespace pmr { template<class T> using forward_list = std::forward_list<T, polymorphic_allocator<T>>; } }

23.3.7 Class template forward_list [forward.list]

23.3.7.1 Overview [forward.list.overview]

A forward_list is a container that supports forward iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically.
Fast random access to list elements is not supported.
[Note 1: 
It is intended that forward_list have zero space or time overhead relative to a hand-written C-style singly linked list.
Features that would conflict with that goal have been omitted.
— end note]
A forward_list meets all of the requirements of a container ([container.reqmts]), except that the size() member function is not provided and operator== has linear complexity.
A forward_list also meets all of the requirements for an allocator-aware container ([container.alloc.reqmts]).
In addition, a forward_list provides the assign member functions and several of the optional sequence container requirements ([sequence.reqmts]).
Descriptions are provided here only for operations on forward_list that are not described in that table or for operations where there is additional semantic information.
[Note 2: 
Modifying any list requires access to the element preceding the first element of interest, but in a forward_list there is no constant-time way to access a preceding element.
For this reason, erase_after and splice_after take fully-open ranges, not semi-open ranges.
— end note]
namespace std { template<class T, class Allocator = allocator<T>> class forward_list { public: // types using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] // [forward.list.cons], construct/copy/destroy forward_list() : forward_list(Allocator()) { } explicit forward_list(const Allocator&); explicit forward_list(size_type n, const Allocator& = Allocator()); forward_list(size_type n, const T& value, const Allocator& = Allocator()); template<class InputIterator> forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); template<container-compatible-range<T> 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<Allocator>&); forward_list(forward_list&& x, const type_identity_t<Allocator>&); forward_list(initializer_list<T>, const Allocator& = Allocator()); ~forward_list(); forward_list& operator=(const forward_list& x); forward_list& operator=(forward_list&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value); forward_list& operator=(initializer_list<T>); template<class InputIterator> void assign(InputIterator first, InputIterator last); template<container-compatible-range<T> R> void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list<T>); allocator_type get_allocator() const noexcept; // [forward.list.iter], iterators iterator before_begin() noexcept; const_iterator before_begin() const noexcept; iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cbefore_begin() const noexcept; const_iterator cend() const noexcept; // capacity bool empty() const noexcept; size_type max_size() const noexcept; // [forward.list.access], element access reference front(); const_reference front() const; // [forward.list.modifiers], modifiers template<class... Args> reference emplace_front(Args&&... args); void push_front(const T& x); void push_front(T&& x); template<container-compatible-range<T> R> void prepend_range(R&& rg); void pop_front(); template<class... Args> iterator emplace_after(const_iterator position, Args&&... args); iterator insert_after(const_iterator position, const T& x); iterator insert_after(const_iterator position, T&& x); iterator insert_after(const_iterator position, size_type n, const T& x); template<class InputIterator> iterator insert_after(const_iterator position, InputIterator first, InputIterator last); iterator insert_after(const_iterator position, initializer_list<T> il); template<container-compatible-range<T> 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); void swap(forward_list&) noexcept(allocator_traits<Allocator>::is_always_equal::value); void resize(size_type sz); void resize(size_type sz, const value_type& c); void clear() noexcept; // [forward.list.ops], forward_list operations void splice_after(const_iterator position, forward_list& x); void splice_after(const_iterator position, forward_list&& x); void splice_after(const_iterator position, forward_list& x, const_iterator i); void splice_after(const_iterator position, forward_list&& x, const_iterator i); void splice_after(const_iterator position, forward_list& x, const_iterator first, const_iterator last); void splice_after(const_iterator position, forward_list&& x, const_iterator first, const_iterator last); size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred); size_type unique(); template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred); void merge(forward_list& x); void merge(forward_list&& x); template<class Compare> void merge(forward_list& x, Compare comp); template<class Compare> void merge(forward_list&& x, Compare comp); void sort(); template<class Compare> void sort(Compare comp); void reverse() noexcept; }; template<class InputIterator, class Allocator = allocator<iter-value-type<InputIterator>>> forward_list(InputIterator, InputIterator, Allocator = Allocator()) -> forward_list<iter-value-type<InputIterator>, Allocator>; template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> forward_list(from_range_t, R&&, Allocator = Allocator()) -> forward_list<ranges::range_value_t<R>, Allocator>; }
An incomplete type T may be used when instantiating forward_list if the allocator meets the allocator completeness requirements.
T shall be complete before any member of the resulting specialization of forward_list is referenced.

23.3.7.2 Constructors, copy, and assignment [forward.list.cons]

explicit forward_list(const Allocator&);
Effects: Constructs an empty forward_list object using the specified allocator.
Complexity: Constant.
explicit forward_list(size_type n, const Allocator& = Allocator());
Preconditions: T is Cpp17DefaultInsertable into forward_list.
Effects: Constructs a forward_list object with n default-inserted elements using the specified allocator.
Complexity: Linear in n.
forward_list(size_type n, const T& value, const Allocator& = Allocator());
Preconditions: T is Cpp17CopyInsertable into forward_list.
Effects: Constructs a forward_list object with n copies of value using the specified allocator.
Complexity: Linear in n.
template<class InputIterator> forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator());
Effects: Constructs a forward_list object equal to the range [first, last).
Complexity: Linear in distance(first, last).
template<container-compatible-range<T> R> forward_list(from_range_t, R&& rg, const Allocator& = Allocator());
Effects: Constructs a forward_list object with the elements of the range rg.
Complexity: Linear in ranges​::​distance(rg).

23.3.7.3 Iterators [forward.list.iter]

iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept;
Effects: cbefore_begin() is equivalent to const_cast<forward_list const&>(*this).before_begin().
Returns: A non-dereferenceable iterator that, when incremented, is equal to the iterator returned by begin().
Remarks: before_begin() == end() shall equal false.

23.3.7.4 Element access [forward.list.access]

reference front(); const_reference front() const;
Returns: *begin()

23.3.7.5 Modifiers [forward.list.modifiers]

The member functions in this subclause do not affect the validity of iterators and references when inserting elements, and when erasing elements invalidate iterators and references to the erased elements only.
If an exception is thrown by any of these member functions there is no effect on the container.
Inserting n elements into a forward_list is linear in n, and the number of calls to the copy or move constructor of T is exactly equal to n.
Erasing n elements from a forward_list is linear in n and the number of calls to the destructor of type T is exactly equal to n.
template<class... Args> reference emplace_front(Args&&... args);
Effects: Inserts an object of type value_type constructed with value_type(std​::​forward<Args>(​args)...) at the beginning of the list.
void push_front(const T& x); void push_front(T&& x);
Effects: Inserts a copy of x at the beginning of the list.
template<container-compatible-range<T> R> void prepend_range(R&& rg);
Effects: Inserts a copy of each element of rg at the beginning of the list.
[Note 1: 
The order of elements is not reversed.
— end note]
void pop_front();
Effects: As if by erase_after(before_begin()).
iterator insert_after(const_iterator position, const T& x);
Preconditions: T is Cpp17CopyInsertable into forward_list.
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
Effects: Inserts a copy of x after position.
Returns: An iterator pointing to the copy of x.
iterator insert_after(const_iterator position, T&& x);
Preconditions: T is Cpp17MoveInsertable into forward_list.
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
Effects: Inserts a copy of x after position.
Returns: An iterator pointing to the copy of x.
iterator insert_after(const_iterator position, size_type n, const T& x);
Preconditions: T is Cpp17CopyInsertable into forward_list.
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
Effects: Inserts n copies of x after position.
Returns: An iterator pointing to the last inserted copy of x, or position if n == 0 is true.
template<class InputIterator> iterator insert_after(const_iterator position, InputIterator first, InputIterator last);
Preconditions: T is Cpp17EmplaceConstructible into forward_list from *first.
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
Neither first nor last are iterators in *this.
Effects: Inserts copies of elements in [first, last) after position.
Returns: An iterator pointing to the last inserted element, or position if first == last is true.
template<container-compatible-range<T> R> iterator insert_range_after(const_iterator position, R&& rg);
Preconditions: T is Cpp17EmplaceConstructible into forward_list from *ranges​::​begin(rg).
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
rg and *this do not overlap.
Effects: Inserts copies of elements in the range rg after position.
Returns: An iterator pointing to the last inserted element, or position if rg is empty.
iterator insert_after(const_iterator position, initializer_list<T> il);
Effects: Equivalent to: return insert_after(position, il.begin(), il.end());
template<class... Args> iterator emplace_after(const_iterator position, Args&&... args);
Preconditions: T is Cpp17EmplaceConstructible into forward_list from std​::​forward<Args>(args)....
position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
Effects: Inserts an object of type value_type direct-non-list-initialized with std​::​forward<Args>(args)... after position.
Returns: An iterator pointing to the new object.
iterator erase_after(const_iterator position);
Preconditions: The iterator following position is dereferenceable.
Effects: Erases the element pointed to by the iterator following position.
Returns: An iterator pointing to the element following the one that was erased, or end() if no such element exists.
Throws: Nothing.
iterator erase_after(const_iterator position, const_iterator last);
Preconditions: All iterators in the range (position, last) are dereferenceable.
Effects: Erases the elements in the range (position, last).
Returns: last.
Throws: Nothing.
void resize(size_type sz);
Preconditions: T is Cpp17DefaultInsertable into forward_list.
Effects: If sz < distance(begin(), end()), erases the last distance(begin(), end()) - sz elements from the list.
Otherwise, inserts sz - distance(begin(), end()) default-inserted elements at the end of the list.
void resize(size_type sz, const value_type& c);
Preconditions: T is Cpp17CopyInsertable into forward_list.
Effects: If sz < distance(begin(), end()), erases the last distance(begin(), end()) - sz elements from the list.
Otherwise, inserts sz - distance(begin(), end()) copies of c at the end of the list.
void clear() noexcept;
Effects: Erases all elements in the range [begin(), end()).
Remarks: Does not invalidate past-the-end iterators.

23.3.7.6 Operations [forward.list.ops]

In this subclause, arguments for a template parameter named Predicate or BinaryPredicate shall meet the corresponding requirements in [algorithms.requirements].
The semantics of i + n, where i is an iterator into the list and n is an integer, are the same as those of next(i, n).
The expression i - n, where i is an iterator into the list and n is an integer, means an iterator j such that j + n == i is true.
For merge and sort, the definitions and requirements in [alg.sorting] apply.
void splice_after(const_iterator position, forward_list& x); void splice_after(const_iterator position, forward_list&& x);
Preconditions: position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
get_allocator() == x.get_allocator() is true.
addressof(x) != this is true.
Effects: Inserts the contents of x after position, and x becomes empty.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Throws: Nothing.
Complexity:
void splice_after(const_iterator position, forward_list& x, const_iterator i); void splice_after(const_iterator position, forward_list&& x, const_iterator i);
Preconditions: position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
The iterator following i is a dereferenceable iterator in x.
get_allocator() == x.get_allocator() is true.
Effects: Inserts the element following i into *this, following position, and removes it from x.
The result is unchanged if position == i or position == ++i.
Pointers and references to *++i continue to refer to the same element but as a member of *this.
Iterators to *++i continue to refer to the same element, but now behave as iterators into *this, not into x.
Throws: Nothing.
Complexity:
void splice_after(const_iterator position, forward_list& x, const_iterator first, const_iterator last); void splice_after(const_iterator position, forward_list&& x, const_iterator first, const_iterator last);
Preconditions: position is before_begin() or is a dereferenceable iterator in the range [begin(), end()).
(first, last) is a valid range in x, and all iterators in the range (first, last) are dereferenceable.
position is not an iterator in the range (first, last).
get_allocator() == x.get_allocator() is true.
Effects: Inserts elements in the range (first, last) after position and removes the elements from x.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Complexity:
size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred);
Effects: Erases all the elements in the list referred to by a list iterator i for which the following conditions hold: *i == value (for remove()), pred(*i) is true (for remove_if()).
Invalidates only the iterators and references to the erased elements.
Returns: The number of elements erased.
Throws: Nothing unless an exception is thrown by the equality comparison or the predicate.
Complexity: Exactly distance(begin(), end()) applications of the corresponding predicate.
Remarks: Stable.
size_type unique(); template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
Let binary_pred be equal_to<>{} for the first overload.
Preconditions: binary_pred is an equivalence relation.
Effects: Erases all but the first element from every consecutive group of equivalent elements.
That is, for a nonempty list, erases all elements referred to by the iterator i in the range [begin() + 1, end()) for which binary_pred(*i, *(i - 1)) is true.
Invalidates only the iterators and references to the erased elements.
Returns: The number of elements erased.
Throws: Nothing unless an exception is thrown by the predicate.
Complexity: If empty() is false, exactly distance(begin(), end()) - 1 applications of the corresponding predicate, otherwise no applications of the predicate.
void merge(forward_list& x); void merge(forward_list&& x); template<class Compare> void merge(forward_list& x, Compare comp); template<class Compare> void merge(forward_list&& x, Compare comp);
Let comp be less<> for the first two overloads.
Preconditions: *this and x are both sorted with respect to the comparator comp, and get_allocator() == x.get_allocator() is true.
Effects: If addressof(x) == this, there are no effects.
Otherwise, merges the two sorted ranges [begin(), end()) and [x.begin(), x.end()).
The result is a range that is sorted with respect to the comparator comp.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Complexity: At most distance(begin(), end()) + distance(x.begin(), x.end()) - 1 comparisons if addressof(x) != this; otherwise, no comparisons are performed.
Remarks: Stable ([algorithm.stable]).
If addressof(x) != this, 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.
void sort(); template<class Compare> void sort(Compare comp);
Effects: Sorts the list according to the operator< or the comp function object.
If an exception is thrown, the order of the elements in *this is unspecified.
Does not affect the validity of iterators and references.
Complexity: Approximately comparisons, where N is distance(begin(), end()).
Remarks: Stable.
void reverse() noexcept;
Effects: Reverses the order of the elements in the list.
Does not affect the validity of iterators and references.
Complexity: Linear time.

23.3.7.7 Erasure [forward.list.erasure]

template<class T, class Allocator, class U = T> typename forward_list<T, Allocator>::size_type erase(forward_list<T, Allocator>& c, const U& value);
Effects: Equivalent to: return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
template<class T, class Allocator, class Predicate> typename forward_list<T, Allocator>::size_type erase_if(forward_list<T, Allocator>& c, Predicate pred);
Effects: Equivalent to: return c.remove_if(pred);

23.3.8 Header <list> synopsis [list.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [list], class template list template<class T, class Allocator = allocator<T>> class list; template<class T, class Allocator> bool operator==(const list<T, Allocator>& x, const list<T, Allocator>& y); template<class T, class Allocator> synth-three-way-result<T> operator<=>(const list<T, Allocator>& x, const list<T, Allocator>& y); template<class T, class Allocator> void swap(list<T, Allocator>& x, list<T, Allocator>& y) noexcept(noexcept(x.swap(y))); // [list.erasure], erasure template<class T, class Allocator, class U = T> typename list<T, Allocator>::size_type erase(list<T, Allocator>& c, const U& value); template<class T, class Allocator, class Predicate> typename list<T, Allocator>::size_type erase_if(list<T, Allocator>& c, Predicate pred); namespace pmr { template<class T> using list = std::list<T, polymorphic_allocator<T>>; } }

23.3.9 Class template list [list]

23.3.9.1 Overview [list.overview]

A list is a sequence container that supports bidirectional iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically.
Unlike vectors and deques, fast random access to list elements is not supported, but many algorithms only need sequential access anyway.
A list meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of a sequence container, including most of the optional sequence container requirements ([sequence.reqmts]).
The exceptions are the operator[] and at member functions, which are not provided.198
Descriptions are provided here only for operations on list that are not described in one of these tables or for operations where there is additional semantic information.
namespace std { template<class T, class Allocator = allocator<T>> class list { public: // types using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // [list.cons], construct/copy/destroy list() : list(Allocator()) { } explicit list(const Allocator&); explicit list(size_type n, const Allocator& = Allocator()); list(size_type n, const T& value, const Allocator& = Allocator()); template<class InputIterator> list(InputIterator first, InputIterator last, const Allocator& = Allocator()); template<container-compatible-range<T> R> list(from_range_t, R&& rg, const Allocator& = Allocator()); list(const list& x); list(list&& x); list(const list&, const type_identity_t<Allocator>&); list(list&&, const type_identity_t<Allocator>&); list(initializer_list<T>, const Allocator& = Allocator()); ~list(); list& operator=(const list& x); list& operator=(list&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value); list& operator=(initializer_list<T>); template<class InputIterator> void assign(InputIterator first, InputIterator last); template<container-compatible-range<T> R> void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list<T>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // [list.capacity], capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz); void resize(size_type sz, const T& c); // element access reference front(); const_reference front() const; reference back(); const_reference back() const; // [list.modifiers], modifiers template<class... Args> reference emplace_front(Args&&... args); template<class... Args> reference emplace_back(Args&&... args); void push_front(const T& x); void push_front(T&& x); template<container-compatible-range<T> R> void prepend_range(R&& rg); void pop_front(); void push_back(const T& x); void push_back(T&& x); template<container-compatible-range<T> R> void append_range(R&& rg); void pop_back(); template<class... Args> iterator emplace(const_iterator position, Args&&... args); iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list<T> il); iterator erase(const_iterator position); iterator erase(const_iterator position, const_iterator last); void swap(list&) noexcept(allocator_traits<Allocator>::is_always_equal::value); void clear() noexcept; // [list.ops], list operations void splice(const_iterator position, list& x); void splice(const_iterator position, list&& x); void splice(const_iterator position, list& x, const_iterator i); void splice(const_iterator position, list&& x, const_iterator i); void splice(const_iterator position, list& x, const_iterator first, const_iterator last); void splice(const_iterator position, list&& x, const_iterator first, const_iterator last); size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred); size_type unique(); template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred); void merge(list& x); void merge(list&& x); template<class Compare> void merge(list& x, Compare comp); template<class Compare> void merge(list&& x, Compare comp); void sort(); template<class Compare> void sort(Compare comp); void reverse() noexcept; }; template<class InputIterator, class Allocator = allocator<iter-value-type<InputIterator>>> list(InputIterator, InputIterator, Allocator = Allocator()) -> list<iter-value-type<InputIterator>, Allocator>; template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> list(from_range_t, R&&, Allocator = Allocator()) -> list<ranges::range_value_t<R>, Allocator>; }
An incomplete type T may be used when instantiating list if the allocator meets the allocator completeness requirements.
T shall be complete before any member of the resulting specialization of list is referenced.
198)198)
These member functions are only provided by containers whose iterators are random access iterators.

23.3.9.2 Constructors, copy, and assignment [list.cons]

explicit list(const Allocator&);
Effects: Constructs an empty list, using the specified allocator.
Complexity: Constant.
explicit list(size_type n, const Allocator& = Allocator());
Preconditions: T is Cpp17DefaultInsertable into list.
Effects: Constructs a list with n default-inserted elements using the specified allocator.
Complexity: Linear in n.
list(size_type n, const T& value, const Allocator& = Allocator());
Preconditions: T is Cpp17CopyInsertable into list.
Effects: Constructs a list with n copies of value, using the specified allocator.
Complexity: Linear in n.
template<class InputIterator> list(InputIterator first, InputIterator last, const Allocator& = Allocator());
Effects: Constructs a list equal to the range [first, last).
Complexity: Linear in distance(first, last).
template<container-compatible-range<T> R> list(from_range_t, R&& rg, const Allocator& = Allocator());
Effects: Constructs a list object with the elements of the range rg.
Complexity: Linear in ranges​::​distance(rg).

23.3.9.3 Capacity [list.capacity]

void resize(size_type sz);
Preconditions: T is Cpp17DefaultInsertable into list.
Effects: If size() < sz, appends sz - size() default-inserted elements to the sequence.
If sz <= size(), equivalent to: list<T>::iterator it = begin(); advance(it, sz); erase(it, end());
void resize(size_type sz, const T& c);
Preconditions: T is Cpp17CopyInsertable into list.
Effects: As if by: if (sz > size()) insert(end(), sz-size(), c); else if (sz < size()) { iterator i = begin(); advance(i, sz); erase(i, end()); } else ; // do nothing

23.3.9.4 Modifiers [list.modifiers]

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<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list<T>); template<class... Args> reference emplace_front(Args&&... args); template<class... Args> reference emplace_back(Args&&... args); template<class... Args> iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); template<container-compatible-range<T> R> void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); template<container-compatible-range<T> R> void append_range(R&& rg);
Complexity: Insertion of a single element into a list takes constant time and exactly one call to a constructor of T.
Insertion of multiple elements into a list is linear in the number of elements inserted, and the number of calls to the copy constructor or move constructor of T is exactly equal to the number of elements inserted.
Remarks: Does not affect the validity of iterators and references.
If an exception is thrown, there are no effects.
iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void pop_front(); void pop_back(); void clear() noexcept;
Effects: Invalidates only the iterators and references to the erased elements.
Throws: Nothing.
Complexity: Erasing a single element is a constant time operation with a single call to the destructor of T.
Erasing a range in a list is linear time in the size of the range and the number of calls to the destructor of type T is exactly equal to the size of the range.

23.3.9.5 Operations [list.ops]

Since lists allow fast insertion and erasing from the middle of a list, certain operations are provided specifically for them.199
In this subclause, arguments for a template parameter named Predicate or BinaryPredicate shall meet the corresponding requirements in [algorithms.requirements].
The semantics of i + n and i - n, where i is an iterator into the list and n is an integer, are the same as those of next(i, n) and prev(i, n), respectively.
For merge and sort, the definitions and requirements in [alg.sorting] apply.
list provides three splice operations that destructively move elements from one list to another.
The behavior of splice operations is undefined if get_allocator() != x.get_allocator().
void splice(const_iterator position, list& x); void splice(const_iterator position, list&& x);
Preconditions: addressof(x) != this is true.
Effects: Inserts the contents of x before position and x becomes empty.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Throws: Nothing.
Complexity: Constant time.
void splice(const_iterator position, list& x, const_iterator i); void splice(const_iterator position, list&& x, const_iterator i);
Preconditions: i is a valid dereferenceable iterator of x.
Effects: Inserts an element pointed to by i from list x before position and removes the element from x.
The result is unchanged if position == i or position == ++i.
Pointers and references to *i continue to refer to this same element but as a member of *this.
Iterators to *i (including i itself) continue to refer to the same element, but now behave as iterators into *this, not into x.
Throws: Nothing.
Complexity: Constant time.
void splice(const_iterator position, list& x, const_iterator first, const_iterator last); void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);
Preconditions: [first, last) is a valid range in x.
position is not an iterator in the range [first, last).
Effects: Inserts elements in the range [first, last) before position and removes the elements from x.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Throws: Nothing.
Complexity: Constant time if addressof(x) == this; otherwise, linear time.
size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred);
Effects: Erases all the elements in the list referred to by a list iterator i for which the following conditions hold: *i == value, pred(*i) != false.
Invalidates only the iterators and references to the erased elements.
Returns: The number of elements erased.
Throws: Nothing unless an exception is thrown by *i == value or pred(*i) != false.
Complexity: Exactly size() applications of the corresponding predicate.
Remarks: Stable.
size_type unique(); template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
Let binary_pred be equal_to<>{} for the first overload.
Preconditions: binary_pred is an equivalence relation.
Effects: Erases all but the first element from every consecutive group of equivalent elements.
That is, for a nonempty list, erases all elements referred to by the iterator i in the range [begin() + 1, end()) for which binary_pred(*i, *(i - 1)) is true.
Invalidates only the iterators and references to the erased elements.
Returns: The number of elements erased.
Throws: Nothing unless an exception is thrown by the predicate.
Complexity: If empty() is false, exactly size() - 1 applications of the corresponding predicate, otherwise no applications of the predicate.
void merge(list& x); void merge(list&& x); template<class Compare> void merge(list& x, Compare comp); template<class Compare> void merge(list&& x, Compare comp);
Let comp be less<> for the first two overloads.
Preconditions: *this and x are both sorted with respect to the comparator comp, and get_allocator() == x.get_allocator() is true.
Effects: If addressof(x) == this, there are no effects.
Otherwise, merges the two sorted ranges [begin(), end()) and [x.begin(), x.end()).
The result is a range that is sorted with respect to the comparator comp.
Pointers and references to the moved elements of x now refer to those same elements but as members of *this.
Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into *this, not into x.
Complexity: At most size() + x.size() - 1 comparisons if addressof(x) != this; otherwise, no comparisons are performed.
Remarks: Stable ([algorithm.stable]).
If addressof(x) != this, 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.
void reverse() noexcept;
Effects: Reverses the order of the elements in the list.
Does not affect the validity of iterators and references.
Complexity: Linear time.
void sort(); template<class Compare> void sort(Compare comp);
Effects: Sorts the list according to the operator< or a Compare function object.
If an exception is thrown, the order of the elements in *this is unspecified.
Does not affect the validity of iterators and references.
Complexity: Approximately comparisons, where N == size().
Remarks: Stable.
199)199)
As specified in [allocator.requirements], the requirements in this Clause apply only to lists whose allocators compare equal.

23.3.9.6 Erasure [list.erasure]

template<class T, class Allocator, class U = T> typename list<T, Allocator>::size_type erase(list<T, Allocator>& c, const U& value);
Effects: Equivalent to: return erase_if(c, [&](const auto& elem) -> bool { return elem == value; });
template<class T, class Allocator, class Predicate> typename list<T, Allocator>::size_type erase_if(list<T, Allocator>& c, Predicate pred);
Effects: Equivalent to: return c.remove_if(pred);

23.3.10 Header <vector> synopsis [vector.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [vector], class template vector template<class T, class Allocator = allocator<T>> class vector; template<class T, class Allocator> constexpr bool operator==(const vector<T, Allocator>& x, const vector<T, Allocator>& y); template<class T, class Allocator> constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x, const vector<T, Allocator>& y); template<class T, class Allocator> constexpr void swap(vector<T, Allocator>& x, vector<T, Allocator>& y) noexcept(noexcept(x.swap(y))); // [vector.erasure], erasure template<class T, class Allocator, class U = T> constexpr typename vector<T, Allocator>::size_type erase(vector<T, Allocator>& c, const U& value); template<class T, class Allocator, class Predicate> constexpr typename vector<T, Allocator>::size_type erase_if(vector<T, Allocator>& c, Predicate pred); namespace pmr { template<class T> using vector = std::vector<T, polymorphic_allocator<T>>; } // [vector.bool], specialization of vector for bool // [vector.bool.pspc], partial class template specialization vector<bool, Allocator> template<class Allocator> class vector<bool, Allocator>; template<class T> constexpr bool is-vector-bool-reference = see below; // exposition only // hash support template<class T> struct hash; template<class Allocator> struct hash<vector<bool, Allocator>>; // [vector.bool.fmt], formatter specialization for vector<bool> template<class T, class charT> requires is-vector-bool-reference<T> struct formatter<T, charT>; }

23.3.11 Class template vector [vector]

23.3.11.1 Overview [vector.overview]

A vector is a sequence container that supports (amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time.
Storage management is handled automatically, though hints can be given to improve efficiency.
A vector meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), of a sequence container, including most of the optional sequence container requirements ([sequence.reqmts]), and, for an element type other than bool, of a contiguous container.
The exceptions are the push_front, prepend_range, pop_front, and emplace_front member functions, which are not provided.
Descriptions are provided here only for operations on vector that are not described in one of these tables or for operations where there is additional semantic information.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).
namespace std { template<class T, class Allocator = allocator<T>> class vector { public: // types using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // [vector.cons], construct/copy/destroy constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } constexpr explicit vector(const Allocator&) noexcept; constexpr explicit vector(size_type n, const Allocator& = Allocator()); constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); template<class InputIterator> constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); template<container-compatible-range<T> 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<Allocator>&); constexpr vector(vector&&, const type_identity_t<Allocator>&); constexpr vector(initializer_list<T>, const Allocator& = Allocator()); constexpr ~vector(); constexpr vector& operator=(const vector& x); constexpr vector& operator=(vector&& x) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); constexpr vector& operator=(initializer_list<T>); template<class InputIterator> constexpr void assign(InputIterator first, InputIterator last); template<container-compatible-range<T> R> constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const T& u); constexpr void assign(initializer_list<T>); constexpr allocator_type get_allocator() const noexcept; // iterators constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // [vector.capacity], capacity constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; constexpr size_type capacity() const noexcept; constexpr void resize(size_type sz); constexpr void resize(size_type sz, const T& c); constexpr void reserve(size_type n); constexpr void shrink_to_fit(); // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); constexpr const_reference at(size_type n) const; constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; // [vector.data], data access constexpr T* data() noexcept; constexpr const T* data() const noexcept; // [vector.modifiers], modifiers template<class... Args> constexpr reference emplace_back(Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); template<container-compatible-range<T> R> constexpr void append_range(R&& rg); constexpr void pop_back(); template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args); constexpr iterator insert(const_iterator position, const T& x); constexpr iterator insert(const_iterator position, T&& x); constexpr iterator insert(const_iterator position, size_type n, const T& x); template<class InputIterator> constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list<T> il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(vector&) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value); constexpr void clear() noexcept; }; template<class InputIterator, class Allocator = allocator<iter-value-type<InputIterator>>> vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector<iter-value-type<InputIterator>, Allocator>; template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> vector(from_range_t, R&&, Allocator = Allocator()) -> vector<ranges::range_value_t<R>, Allocator>; }
An incomplete type T may be used when instantiating vector if the allocator meets the allocator completeness requirements.
T shall be complete before any member of the resulting specialization of vector is referenced.

23.3.11.2 Constructors [vector.cons]

constexpr explicit vector(const Allocator&) noexcept;
Effects: Constructs an empty vector, using the specified allocator.
Complexity: Constant.
constexpr explicit vector(size_type n, const Allocator& = Allocator());
Preconditions: T is Cpp17DefaultInsertable into vector.
Effects: Constructs a vector with n default-inserted elements using the specified allocator.
Complexity: Linear in n.
constexpr vector(size_type n, const T& value, const Allocator& = Allocator());
Preconditions: T is Cpp17CopyInsertable into vector.
Effects: Constructs a vector with n copies of value, using the specified allocator.
Complexity: Linear in n.
template<class InputIterator> constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
Effects: Constructs a vector equal to the range [first, last), using the specified allocator.
Complexity: Makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories.
It makes order N calls to the copy constructor of T and order reallocations if they are just input iterators.
template<container-compatible-range<T> R> constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator());
Effects: Constructs a vector object with the elements of the range rg, using the specified allocator.
Complexity: Initializes exactly N elements from the results of dereferencing successive iterators of rg, where N is ranges​::​distance(rg).
Performs no reallocations if R models ranges​::​forward_range or ranges​::​sized_range; otherwise, performs order reallocations and order N calls to the copy or move constructor of T.

23.3.11.3 Capacity [vector.capacity]

constexpr size_type capacity() const noexcept;
Returns: The total number of elements that the vector can hold without requiring reallocation.
Complexity: Constant time.
constexpr void reserve(size_type n);
Preconditions: T is Cpp17MoveInsertable into vector.
Effects: A directive that informs a vector of a planned change in size, so that it can manage the storage allocation accordingly.
After reserve(), capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise.
Reallocation happens at this point if and only if the current capacity is less than the argument of reserve().
If an exception is thrown other than by the move constructor of a non-Cpp17CopyInsertable type, there are no effects.
Throws: length_error if n > max_size().200
Complexity: It does not change the size of the sequence and takes at most linear time in the size of the sequence.
Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence, as well as the past-the-end iterator.
[Note 1: 
If no reallocation happens, they remain valid.
— end note]
No reallocation shall take place during insertions that happen after a call to reserve() until an insertion would make the size of the vector greater than the value of capacity().
constexpr void shrink_to_fit();
Preconditions: T is Cpp17MoveInsertable into vector.
Effects: shrink_to_fit is a non-binding request to reduce capacity() to size().
[Note 2: 
The request is non-binding to allow latitude for implementation-specific optimizations.
— end note]
It does not increase capacity(), but may reduce capacity() by causing reallocation.
If an exception is thrown other than by the move constructor of a non-Cpp17CopyInsertable T, there are no effects.
Complexity: If reallocation happens, linear in the size of the sequence.
Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence as well as the past-the-end iterator.
[Note 3: 
If no reallocation happens, they remain valid.
— end note]
constexpr void swap(vector& x) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value);
Effects: Exchanges the contents and capacity() of *this with that of x.
Complexity: Constant time.
constexpr void resize(size_type sz);
Preconditions: T is Cpp17MoveInsertable and Cpp17DefaultInsertable into vector.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() default-inserted elements to the sequence.
Remarks: If an exception is thrown other than by the move constructor of a non-Cpp17CopyInsertable T, there are no effects.
constexpr void resize(size_type sz, const T& c);
Preconditions: T is Cpp17CopyInsertable into vector.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() copies of c to the sequence.
Remarks: If an exception is thrown, there are no effects.
200)200)
reserve() uses Allocator​::​allocate() which can throw an appropriate exception.

23.3.11.4 Data [vector.data]

constexpr T* data() noexcept; constexpr const T* data() const noexcept;
Returns: A pointer such that [data(), data() + size()) is a valid range.
For a non-empty vector, data() == addressof(front()) is true.
Complexity: Constant time.

23.3.11.5 Modifiers [vector.modifiers]

constexpr iterator insert(const_iterator position, const T& x); constexpr iterator insert(const_iterator position, T&& x); constexpr iterator insert(const_iterator position, size_type n, const T& x); template<class InputIterator> constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list<T>); template<class... Args> constexpr reference emplace_back(Args&&... args); template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); template<container-compatible-range<T> R> constexpr void append_range(R&& rg);
Complexity: If reallocation happens, linear in the number of elements of the resulting vector; otherwise, linear in the number of elements inserted plus the distance to the end of the vector.
Remarks: Causes reallocation if the new size is greater than the old capacity.
Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence, as well as the past-the-end iterator.
If no reallocation happens, then references, pointers, and iterators before the insertion point remain valid but those at or after the insertion point, including the past-the-end iterator, are invalidated.
If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation, there are no effects.
If an exception is thrown while inserting a single element at the end and T is Cpp17CopyInsertable or is_nothrow_move_constructible_v<T> is true, there are no effects.
Otherwise, if an exception is thrown by the move constructor of a non-Cpp17CopyInsertable T, the effects are unspecified.
constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void pop_back();
Effects: Invalidates iterators and references at or after the point of the erase.
Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the assignment operator of T is called the number of times equal to the number of elements in the vector after the erased elements.

23.3.11.6 Erasure [vector.erasure]

template<class T, class Allocator, class U = T> constexpr typename vector<T, Allocator>::size_type erase(vector<T, Allocator>& c, const U& value);
Effects: Equivalent to: auto it = remove(c.begin(), c.end(), value); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;
template<class T, class Allocator, class Predicate> constexpr typename vector<T, Allocator>::size_type erase_if(vector<T, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto it = remove_if(c.begin(), c.end(), pred); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;

23.3.12 Specialization of vector for bool [vector.bool]

23.3.12.1 Partial class template specialization vector<bool, Allocator> [vector.bool.pspc]

To optimize space allocation, a partial specialization of vector for bool elements is provided: namespace std { template<class Allocator> class vector<bool, Allocator> { public: // types using value_type = bool; using allocator_type = Allocator; using pointer = implementation-defined; using const_pointer = implementation-defined; using const_reference = bool; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // bit reference class reference { public: constexpr reference(const reference&) = default; constexpr ~reference(); constexpr operator bool() const noexcept; constexpr reference& operator=(bool x) noexcept; constexpr reference& operator=(const reference& x) noexcept; constexpr const reference& operator=(bool x) const noexcept; constexpr void flip() noexcept; // flips the bit }; // construct/copy/destroy constexpr vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } constexpr explicit vector(const Allocator&) noexcept; constexpr explicit vector(size_type n, const Allocator& = Allocator()); constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); template<class InputIterator> constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); template<container-compatible-range<bool> R> constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&& x) noexcept; constexpr vector(const vector&, const type_identity_t<Allocator>&); constexpr vector(vector&&, const type_identity_t<Allocator>&); constexpr vector(initializer_list<bool>, const Allocator& = Allocator()); constexpr ~vector(); constexpr vector& operator=(const vector& x); constexpr vector& operator=(vector&& x) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); constexpr vector& operator=(initializer_list<bool>); template<class InputIterator> constexpr void assign(InputIterator first, InputIterator last); template<container-compatible-range<bool> R> constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const bool& t); constexpr void assign(initializer_list<bool>); constexpr allocator_type get_allocator() const noexcept; // iterators constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // capacity constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; constexpr size_type max_size() const noexcept; constexpr size_type capacity() const noexcept; constexpr void resize(size_type sz, bool c = false); constexpr void reserve(size_type n); constexpr void shrink_to_fit(); // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); constexpr const_reference at(size_type n) const; constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; // modifiers template<class... Args> constexpr reference emplace_back(Args&&... args); constexpr void push_back(const bool& x); template<container-compatible-range<bool> R> constexpr void append_range(R&& rg); constexpr void pop_back(); template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args); constexpr iterator insert(const_iterator position, const bool& x); constexpr iterator insert(const_iterator position, size_type n, const bool& x); template<class InputIterator> constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<bool> R> constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list<bool> il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(vector&) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value); static constexpr void swap(reference x, reference y) noexcept; constexpr void flip() noexcept; // flips all bits constexpr void clear() noexcept; }; }
Unless described below, all operations have the same requirements and semantics as the primary vector template, except that operations dealing with the bool value type map to bit values in the container storage and allocator_traits​::​construct is not used to construct these values.
There is no requirement that the data be stored as a contiguous allocation of bool values.
A space-optimized representation of bits is recommended instead.
reference is a class that simulates the behavior of references of a single bit in vector<bool>.
The conversion function returns true when the bit is set, and false otherwise.
The assignment operators set the bit when the argument is (convertible to) true and clear it otherwise.
flip reverses the state of the bit.
constexpr void flip() noexcept;
Effects: Replaces each element in the container with its complement.
static constexpr void swap(reference x, reference y) noexcept;
Effects: Exchanges the contents of x and y as if by: bool b = x; x = y; y = b;
template<class Allocator> struct hash<vector<bool, Allocator>>;
The specialization is enabled ([unord.hash]).
template<class T> constexpr bool is-vector-bool-reference = see below;
The expression is-vector-bool-reference<T> is true if T denotes the type vector<bool, Alloc>​::​reference for some type Alloc and vector<bool, Alloc> is not a program-defined specialization.

23.3.12.2 Formatter specialization for vector<bool> [vector.bool.fmt]

namespace std { template<class T, class charT> requires is-vector-bool-reference<T> struct formatter<T, charT> { private: formatter<bool, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(const T& ref, FormatContext& ctx) const; }; }
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(const T& ref, FormatContext& ctx) const;
Equivalent to: return underlying_.format(ref, ctx);

23.3.13 Header <inplace_vector> synopsis [inplace.vector.syn]

// mostly freestanding #include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [inplace.vector], class template inplace_vector template<class T, size_t N> class inplace_vector; // partially freestanding // [inplace.vector.erasure], erasure template<class T, size_t N, class U = T> constexpr typename inplace_vector<T, N>::size_type erase(inplace_vector<T, N>& c, const U& value); template<class T, size_t N, class Predicate> constexpr typename inplace_vector<T, N>::size_type erase_if(inplace_vector<T, N>& c, Predicate pred); }

23.3.14 Class template inplace_vector [inplace.vector]

23.3.14.1 Overview [inplace.vector.overview]

An inplace_vector is a contiguous container.
Its capacity is fixed and its elements are stored within the inplace_vector object itself.
An inplace_vector meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of a contiguous container, and of a sequence container, including most of the optional sequence container requirements ([sequence.reqmts]).
The exceptions are the push_front, prepend_range, pop_front, and emplace_front member functions, which are not provided.
Descriptions are provided here only for operations on inplace_vector that are not described in one of these tables or for operations where there is additional semantic information.
For any N, inplace_vector<T, N>​::​iterator and inplace_vector<T, N>​::​const_iterator meet the constexpr iterator requirements.
For any , if T is not trivially copyable or is_trivially_default_constructible_v<T> is false, then no inplace_vector<T, N> member functions are usable in constant expressions.
Any member function of inplace_vector<T, N> that would cause the size to exceed N throws an exception of type bad_alloc.
Let IV denote a specialization of inplace_vector<T, N>.
If N is zero, then IV is trivially copyable and empty, and std​::​is_trivially_default_constructible_v<IV> is true.
Otherwise:
  • If is_trivially_copy_constructible_v<T> is true, then IV has a trivial copy constructor.
  • If is_trivially_move_constructible_v<T> is true, then IV has a trivial move constructor.
  • If is_trivially_destructible_v<T> is true, then:
    • IV has a trivial destructor.
    • If is_trivially_copy_constructible_v<T> && is_trivially_copy_assignable_v<T> is true, then IV has a trivial copy assignment operator.
    • If is_trivially_move_constructible_v<T> && is_trivially_move_assignable_v<T> is true, then IV has a trivial move assignment operator.
namespace std { template<class T, size_t N> class inplace_vector { public: // types: using value_type = T; using pointer = T*; using const_pointer = const T*; using reference = value_type&; using const_reference = const value_type&; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; // [inplace.vector.cons], construct/copy/destroy constexpr inplace_vector() noexcept; constexpr explicit inplace_vector(size_type n); // freestanding-deleted constexpr inplace_vector(size_type n, const T& value); // freestanding-deleted template<class InputIterator> constexpr inplace_vector(InputIterator first, InputIterator last); // freestanding-deleted template<container-compatible-range<T> R> constexpr inplace_vector(from_range_t, R&& rg); // freestanding-deleted constexpr inplace_vector(const inplace_vector&); constexpr inplace_vector(inplace_vector&&) noexcept(N == 0 || is_nothrow_move_constructible_v<T>); constexpr inplace_vector(initializer_list<T> il); // freestanding-deleted constexpr ~inplace_vector(); constexpr inplace_vector& operator=(const inplace_vector& other); constexpr inplace_vector& operator=(inplace_vector&& other) noexcept(N == 0 || (is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>)); constexpr inplace_vector& operator=(initializer_list<T>); // freestanding-deleted template<class InputIterator> constexpr void assign(InputIterator first, InputIterator last); // freestanding-deleted template<container-compatible-range<T> R> constexpr void assign_range(R&& rg); // freestanding-deleted constexpr void assign(size_type n, const T& u); // freestanding-deleted constexpr void assign(initializer_list<T> il); // freestanding-deleted // iterators constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // [inplace.vector.capacity], size/capacity constexpr bool empty() const noexcept; constexpr size_type size() const noexcept; static constexpr size_type max_size() noexcept; static constexpr size_type capacity() noexcept; constexpr void resize(size_type sz); // freestanding-deleted constexpr void resize(size_type sz, const T& c); // freestanding-deleted static constexpr void reserve(size_type n); // freestanding-deleted static constexpr void shrink_to_fit() noexcept; // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; constexpr reference at(size_type n); // freestanding-deleted constexpr const_reference at(size_type n) const; // freestanding-deleted constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); constexpr const_reference back() const; // [inplace.vector.data], data access constexpr T* data() noexcept; constexpr const T* data() const noexcept; // [inplace.vector.modifiers], modifiers template<class... Args> constexpr reference emplace_back(Args&&... args); // freestanding-deleted constexpr reference push_back(const T& x); // freestanding-deleted constexpr reference push_back(T&& x); // freestanding-deleted template<container-compatible-range<T> R> constexpr void append_range(R&& rg); // freestanding-deleted constexpr void pop_back(); template<class... Args> constexpr pointer try_emplace_back(Args&&... args); constexpr pointer try_push_back(const T& x); constexpr pointer try_push_back(T&& x); template<container-compatible-range<T> R> constexpr ranges::borrowed_iterator_t<R> try_append_range(R&& rg); template<class... Args> constexpr reference unchecked_emplace_back(Args&&... args); constexpr reference unchecked_push_back(const T& x); constexpr reference unchecked_push_back(T&& x); template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args); // freestanding-deleted constexpr iterator insert(const_iterator position, const T& x); // freestanding-deleted constexpr iterator insert(const_iterator position, T&& x); // freestanding-deleted constexpr iterator insert(const_iterator position, size_type n, // freestanding-deleted const T& x); template<class InputIterator> constexpr iterator insert(const_iterator position, // freestanding-deleted InputIterator first, InputIterator last); template<container-compatible-range<T> R> constexpr iterator insert_range(const_iterator position, R&& rg); // freestanding-deleted constexpr iterator insert(const_iterator position, // freestanding-deleted initializer_list<T> il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void swap(inplace_vector& x) noexcept(N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>)); constexpr void clear() noexcept; constexpr friend bool operator==(const inplace_vector& x, const inplace_vector& y); constexpr friend synth-three-way-result<T> operator<=>(const inplace_vector& x, const inplace_vector& y); constexpr friend void swap(inplace_vector& x, inplace_vector& y) noexcept(N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>)) { x.swap(y); } }; };

23.3.14.2 Constructors [inplace.vector.cons]

constexpr explicit inplace_vector(size_type n);
Preconditions: T is Cpp17DefaultInsertable into inplace_vector.
Effects: Constructs an inplace_vector with n default-inserted elements.
Complexity: Linear in n.
constexpr inplace_vector(size_type n, const T& value);
Preconditions: T is Cpp17CopyInsertable into inplace_vector.
Effects: Constructs an inplace_vector with n copies of value.
Complexity: Linear in n.
template<class InputIterator> constexpr inplace_vector(InputIterator first, InputIterator last);
Effects: Constructs an inplace_vector equal to the range [first, last).
Complexity: Linear in distance(first, last).
template<container-compatible-range<T> R> constexpr inplace_vector(from_range_t, R&& rg);
Effects: Constructs an inplace_vector with the elements of the range rg.
Complexity: Linear in ranges​::​distance(rg).

23.3.14.3 Size and capacity [inplace.vector.capacity]

static constexpr size_type capacity() noexcept; static constexpr size_type max_size() noexcept;
Returns: N.
constexpr void resize(size_type sz);
Preconditions: T is Cpp17DefaultInsertable into inplace_vector.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() default-inserted elements to the sequence.
Remarks: If an exception is thrown, there are no effects on *this.
constexpr void resize(size_type sz, const T& c);
Preconditions: T is Cpp17CopyInsertable into inplace_vector.
Effects: If sz < size(), erases the last size() - sz elements from the sequence.
Otherwise, appends sz - size() copies of c to the sequence.
Remarks: If an exception is thrown, there are no effects on *this.

23.3.14.4 Data [inplace.vector.data]

constexpr T* data() noexcept; constexpr const T* data() const noexcept;
Returns: A pointer such that [data(), data() + size()) is a valid range.
For a non-empty inplace_vector, data() == addressof(front()) is true.
Complexity: Constant time.

23.3.14.5 Modifiers [inplace.vector.modifiers]

constexpr iterator insert(const_iterator position, const T& x); constexpr iterator insert(const_iterator position, T&& x); constexpr iterator insert(const_iterator position, size_type n, const T& x); template<class InputIterator> constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); template<container-compatible-range<T> R> constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list<T> il); template<class... Args> constexpr iterator emplace(const_iterator position, Args&&... args); template<container-compatible-range<T> R> constexpr void append_range(R&& rg);
Let n be the value of size() before this call for the append_range overload, and distance(begin, position) otherwise.
Complexity: Linear in the number of elements inserted plus the distance to the end of the vector.
Remarks: If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation, there are no effects.
Otherwise, if an exception is thrown, then size()  ≥ n and elements in the range begin() + [0, n) are not modified.
constexpr reference push_back(const T& x); constexpr reference push_back(T&& x); template<class... Args> constexpr reference emplace_back(Args&&... args);
Returns: back().
Throws: bad_alloc or any exception thrown by the initialization of the inserted element.
Complexity: Constant.
Remarks: If an exception is thrown, there are no effects on *this.
template<class... Args> constexpr pointer try_emplace_back(Args&&... args); constexpr pointer try_push_back(const T& x); constexpr pointer try_push_back(T&& x);
Let vals denote a pack:
  • std​::​forward<Args>(args)... for the first overload,
  • x for the second overload,
  • std​::​move(x) for the third overload.
Preconditions: value_type is Cpp17EmplaceConstructible into inplace_vector from vals....
Effects: If size() < capacity() is true, appends an object of type T direct-non-list-initialized with vals....
Otherwise, there are no effects.
Returns: nullptr if size() == capacity() is true, otherwise addressof(back()).
Throws: Nothing unless an exception is thrown by the initialization of the inserted element.
Complexity: Constant.
Remarks: If an exception is thrown, there are no effects on *this.
template<container-compatible-range<T> R> constexpr ranges::borrowed_iterator_t<R> try_append_range(R&& rg);
Preconditions: value_type is Cpp17EmplaceConstructible into inplace_vector from
*ranges​::​begin(rg).
Effects: Appends copies of initial elements in rg before end(), until all elements are inserted or size() == capacity() is true.
Each iterator in the range rg is dereferenced at most once.
Returns: An iterator pointing to the first element of rg that was not inserted into *this, or ranges​::​end(rg) if no such element exists.
Complexity: Linear in the number of elements inserted.
Remarks: Let n be the value of size() prior to this call.
If an exception is thrown after the insertion of k elements, then size() equals , elements in the range begin() + [0, n) are not modified, and elements in the range begin() + [n, ) correspond to the inserted elements.
template<class... Args> constexpr reference unchecked_emplace_back(Args&&... args);
Preconditions: size() < capacity() is true.
Effects: Equivalent to: return *try_emplace_back(std​::​forward<Args>(args)...);
constexpr reference unchecked_push_back(const T& x); constexpr reference unchecked_push_back(T&& x);
Preconditions: size() < capacity() is true.
Effects: Equivalent to: return *try_push_back(std​::​forward<decltype(x)>(x));
static constexpr void reserve(size_type n);
Effects: None.
Throws: bad_alloc if n > capacity() is true.
static constexpr void shrink_to_fit() noexcept;
Effects: None.
constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void pop_back();
Effects: Invalidates iterators and references at or after the point of the erase.
Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
Complexity: The destructor of T is called the number of times equal to the number of the elements erased, but the assignment operator of T is called the number of times equal to the number of elements after the erased elements.

23.3.14.6 Erasure [inplace.vector.erasure]

template<class T, size_t N, class U = T> constexpr size_t erase(inplace_vector<T, N>& c, const U& value);
Effects: Equivalent to: auto it = remove(c.begin(), c.end(), value); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;
template<class T, size_t N, class Predicate> constexpr size_t erase_if(inplace_vector<T, N>& c, Predicate pred);
Effects: Equivalent to: auto it = remove_if(c.begin(), c.end(), pred); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;

23.4 Associative containers [associative]

23.4.1 General [associative.general]

The header <map> defines the class templates map and multimap; the header <set> defines the class templates set and multiset.
The following exposition-only alias templates may appear in deduction guides for associative containers: template<class InputIterator> using iter-value-type = typename iterator_traits<InputIterator>::value_type; // exposition only template<class InputIterator> using iter-key-type = remove_const_t< tuple_element_t<0, iter-value-type<InputIterator>>>; // exposition only template<class InputIterator> using iter-mapped-type = tuple_element_t<1, iter-value-type<InputIterator>>; // exposition only template<class InputIterator> using iter-to-alloc-type = pair< add_const_t<tuple_element_t<0, iter-value-type<InputIterator>>>, tuple_element_t<1, iter-value-type<InputIterator>>>; // exposition only template<ranges::input_range Range> using range-key-type = remove_const_t<typename ranges::range_value_t<Range>::first_type>; // exposition only template<ranges::input_range Range> using range-mapped-type = typename ranges::range_value_t<Range>::second_type; // exposition only template<ranges::input_range Range> using range-to-alloc-type = pair<add_const_t<typename ranges::range_value_t<Range>::first_type>, typename ranges::range_value_t<Range>::second_type>; // exposition only

23.4.2 Header <map> synopsis [associative.map.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [map], class template map template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> class map; template<class Key, class T, class Compare, class Allocator> bool operator==(const map<Key, T, Compare, Allocator>& x, const map<Key, T, Compare, Allocator>& y); template<class Key, class T, class Compare, class Allocator> synth-three-way-result<pair<const Key, T>> operator<=>(const map<Key, T, Compare, Allocator>& x, const map<Key, T, Compare, Allocator>& y); template<class Key, class T, class Compare, class Allocator> void swap(map<Key, T, Compare, Allocator>& x, map<Key, T, Compare, Allocator>& y) noexcept(noexcept(x.swap(y))); // [map.erasure], erasure for map template<class Key, class T, class Compare, class Allocator, class Predicate> typename map<Key, T, Compare, Allocator>::size_type erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred); // [multimap], class template multimap template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> class multimap; template<class Key, class T, class Compare, class Allocator> bool operator==(const multimap<Key, T, Compare, Allocator>& x, const multimap<Key, T, Compare, Allocator>& y); template<class Key, class T, class Compare, class Allocator> synth-three-way-result<pair<const Key, T>> operator<=>(const multimap<Key, T, Compare, Allocator>& x, const multimap<Key, T, Compare, Allocator>& y); template<class Key, class T, class Compare, class Allocator> void swap(multimap<Key, T, Compare, Allocator>& x, multimap<Key, T, Compare, Allocator>& y) noexcept(noexcept(x.swap(y))); // [multimap.erasure], erasure for multimap template<class Key, class T, class Compare, class Allocator, class Predicate> typename multimap<Key, T, Compare, Allocator>::size_type erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); namespace pmr { template<class Key, class T, class Compare = less<Key>> using map = std::map<Key, T, Compare, polymorphic_allocator<pair<const Key, T>>>; template<class Key, class T, class Compare = less<Key>> using multimap = std::multimap<Key, T, Compare, polymorphic_allocator<pair<const Key, T>>>; } }

23.4.3 Class template map [map]

23.4.3.1 Overview [map.overview]

A map is an associative container that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of values of another type T based on the keys.
The map class supports bidirectional iterators.
A map meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]).
and of an associative container ([associative.reqmts]).
A map also provides most operations described in [associative.reqmts] for unique keys.
This means that a map supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a map<Key,T> the key_type is Key and the value_type is pair<const Key,T>.
Descriptions are provided here only for operations on map that are not described in one of those tables or for operations where there is additional semantic information.
namespace std { template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> class map { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<const Key, T>; using key_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = unspecified; using insert_return_type = insert-return-type<iterator, node_type>; class value_compare { protected: Compare comp; value_compare(Compare c) : comp(c) {} public: bool operator()(const value_type& x, const value_type& y) const { return comp(x.first, y.first); } }; // [map.cons], construct/copy/destroy map() : map(Compare()) { } explicit map(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator> map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<container-compatible-range<value_type> R> map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); map(const map& x); map(map&& x); explicit map(const Allocator&); map(const map&, const type_identity_t<Allocator>&); map(map&&, const type_identity_t<Allocator>&); map(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator> map(InputIterator first, InputIterator last, const Allocator& a) : map(first, last, Compare(), a) { } template<container-compatible-range<value_type> R> map(from_range_t, R&& rg, const Allocator& a)) : map(from_range, std::forward<R>(rg), Compare(), a) { } map(initializer_list<value_type> il, const Allocator& a) : map(il, Compare(), a) { } ~map(); map& operator=(const map& x); map& operator=(map&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); map& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [map.access], element access mapped_type& operator[](const key_type& x); mapped_type& operator[](key_type&& x); template<class K> mapped_type& operator[](K&& x); mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const; template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const; // [map.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& x); pair<iterator, bool> insert(value_type&& x); template<class P> pair<iterator, bool> insert(P&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template<class P> iterator insert(const_iterator position, P&&); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); insert_return_type insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args); template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(map&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); void clear() noexcept; template<class C2> void merge(map<Key, T, C2, Allocator>& source); template<class C2> void merge(map<Key, T, C2, Allocator>&& source); template<class C2> void merge(multimap<Key, T, C2, Allocator>& source); template<class C2> void merge(multimap<Key, T, C2, Allocator>&& source); // observers key_compare key_comp() const; value_compare value_comp() const; // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>, class Allocator = allocator<iter-to-alloc-type<InputIterator>>> map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare, Allocator>; template<ranges::input_range R, class Compare = less<range-key-type<R>, class Allocator = allocator<range-to-alloc-type<R>>> map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> map<range-key-type<R>, range-mapped-type<R>, Compare, Allocator>; template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator()) -> map<Key, T, Compare, Allocator>; template<class InputIterator, class Allocator> map(InputIterator, InputIterator, Allocator) -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, less<iter-key-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> map(from_range_t, R&&, Allocator) -> map<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, Allocator>; template<class Key, class T, class Allocator> map(initializer_list<pair<Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; }

23.4.3.2 Constructors, copy, and assignment [map.cons]

explicit map(const Compare& comp, const Allocator& = Allocator());
Effects: Constructs an empty map using the specified comparison object and allocator.
Complexity: Constant.
template<class InputIterator> map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty map using the specified comparison object and allocator, and inserts elements from the range [first, last).
Complexity: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise , where N is last - first.
template<container-compatible-range<value_type> R> map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty map using the specified comparison object and allocator, and inserts elements from the range rg.
Complexity: Linear in N if rg is already sorted with respect to comp and otherwise , where N is ranges​::​distance(rg).

23.4.3.3 Element access [map.access]

mapped_type& operator[](const key_type& x);
Effects: Equivalent to: return try_emplace(x).first->second;
mapped_type& operator[](key_type&& x);
Effects: Equivalent to: return try_emplace(std​::​move(x)).first->second;
template<class K> mapped_type& operator[](K&& x);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
Effects: Equivalent to: return try_emplace(std​::​forward<K>(x)).first->second;
mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const;
Returns: A reference to the mapped_type corresponding to x in *this.
Throws: An exception object of type out_of_range if no such element is present.
Complexity: Logarithmic.
template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const;
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
Preconditions: The expression find(x) is well-formed and has well-defined behavior.
Returns: A reference to find(x)->second.
Throws: An exception object of type out_of_range if find(x) == end() is true.
Complexity: Logarithmic.

23.4.3.4 Modifiers [map.modifiers]

template<class P> pair<iterator, bool> insert(P&& x); template<class P> iterator insert(const_iterator position, P&& x);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: The first form is equivalent to return emplace(std​::​forward<P>(x)).
The second form is equivalent to return emplace_hint(position, std​::​forward<P>(x)).
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
Preconditions: value_type is Cpp17EmplaceConstructible into map from piecewise_construct, forward_as_tuple(k), forward_as_tuple(std​::​forward<Args>(args)...).
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k), forward_as_tuple(std​::​forward<Args>(args)...).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
Preconditions: value_type is Cpp17EmplaceConstructible into map from piecewise_construct, forward_as_tuple(std​::​move(k)), forward_as_tuple(std​::​forward<Args>(args)...).
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(std​::​move(k)), forward_as_tuple(std​::​forward<Args>(args)...).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
For the first overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false.
Preconditions: value_type is Cpp17EmplaceConstructible into map from piecewise_construct, forward_as_tuple(std​::​forward<K>(k)), forward_as_tuple(std​::​forward<Args>(args)...).
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise, let r be equal_range(k).
Constructs an object u of type value_type with piecewise_construct, forward_as_tuple(std​::​forward<K>(k)), forward_as_tuple(std​::​forward<Args>(args)...).
If equal_range(u.first) == r is false, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into map from k, std​::​forward<M>(obj).
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise inserts an object of type value_type constructed with k, std​::​forward<M>(obj).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into map from std​::​move(k), std​::​forward<M>(obj).
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise inserts an object of type value_type constructed with std​::​​move(k), std​::​forward<M>(obj).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into map from std​::​forward<K>(k), std​::​
forward<M>(obj)
.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>
(obj)
to e.second.
Otherwise, let r be equal_range(k).
Constructs an object u of type value_type with std​::​forward<K>(k), std​::​forward<M>(obj).
If equal_range(u.first) == r is false, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.

23.4.3.5 Erasure [map.erasure]

template<class Key, class T, class Compare, class Allocator, class Predicate> typename map<Key, T, Compare, Allocator>::size_type erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.4.4 Class template multimap [multimap]

23.4.4.1 Overview [multimap.overview]

A multimap is an associative container that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type T based on the keys.
The multimap class supports bidirectional iterators.
A multimap meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of an associative container ([associative.reqmts]).
A multimap also provides most operations described in [associative.reqmts] for equal keys.
This means that a multimap supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a multimap<Key,T> the key_type is Key and the value_type is pair<const Key,T>.
Descriptions are provided here only for operations on multimap that are not described in one of those tables or for operations where there is additional semantic information.
namespace std { template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> class multimap { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<const Key, T>; using key_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = unspecified; class value_compare { protected: Compare comp; value_compare(Compare c) : comp(c) { } public: bool operator()(const value_type& x, const value_type& y) const { return comp(x.first, y.first); } }; // [multimap.cons], construct/copy/destroy multimap() : multimap(Compare()) { } explicit multimap(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator> multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<container-compatible-range<value_type> R> multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); multimap(const multimap& x); multimap(multimap&& x); explicit multimap(const Allocator&); multimap(const multimap&, const type_identity_t<Allocator>&); multimap(multimap&&, const type_identity_t<Allocator>&); multimap(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator> multimap(InputIterator first, InputIterator last, const Allocator& a) : multimap(first, last, Compare(), a) { } template<container-compatible-range<value_type> R> multimap(from_range_t, R&& rg, const Allocator& a)) : multimap(from_range, std::forward<R>(rg), Compare(), a) { } multimap(initializer_list<value_type> il, const Allocator& a) : multimap(il, Compare(), a) { } ~multimap(); multimap& operator=(const multimap& x); multimap& operator=(multimap&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); multimap& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [multimap.modifiers], modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x); iterator insert(value_type&& x); template<class P> iterator insert(P&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template<class P> iterator insert(const_iterator position, P&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); iterator insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(multimap&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); void clear() noexcept; template<class C2> void merge(multimap<Key, T, C2, Allocator>& source); template<class C2> void merge(multimap<Key, T, C2, Allocator>&& source); template<class C2> void merge(map<Key, T, C2, Allocator>& source); template<class C2> void merge(map<Key, T, C2, Allocator>&& source); // observers key_compare key_comp() const; value_compare value_comp() const; // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>, class Allocator = allocator<iter-to-alloc-type<InputIterator>>> multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare, Allocator>; template<ranges::input_range R, class Compare = less<range-key-type<R>>, class Allocator = allocator<range-to-alloc-type<R>>> multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> multimap<range-key-type<R>, range-mapped-type<R>, Compare, Allocator>; template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> multimap(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator()) -> multimap<Key, T, Compare, Allocator>; template<class InputIterator, class Allocator> multimap(InputIterator, InputIterator, Allocator) -> multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, less<iter-key-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> multimap(from_range_t, R&&, Allocator) -> multimap<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, Allocator>; template<class Key, class T, class Allocator> multimap(initializer_list<pair<Key, T>>, Allocator) -> multimap<Key, T, less<Key>, Allocator>; }

23.4.4.2 Constructors [multimap.cons]

explicit multimap(const Compare& comp, const Allocator& = Allocator());
Effects: Constructs an empty multimap using the specified comparison object and allocator.
Complexity: Constant.
template<class InputIterator> multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty multimap using the specified comparison object and allocator, and inserts elements from the range [first, last).
Complexity: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise , where N is last - first.
template<container-compatible-range<value_type> R> multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty multimap using the specified comparison object and allocator, and inserts elements from the range rg.
Complexity: Linear in N if rg is already sorted with respect to comp and otherwise , where N is ranges​::​distance(rg).

23.4.4.3 Modifiers [multimap.modifiers]

template<class P> iterator insert(P&& x); template<class P> iterator insert(const_iterator position, P&& x);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: The first form is equivalent to return emplace(std​::​forward<P>(x)).
The second form is equivalent to return emplace_hint(position, std​::​forward<P>(x)).

23.4.4.4 Erasure [multimap.erasure]

template<class Key, class T, class Compare, class Allocator, class Predicate> typename multimap<Key, T, Compare, Allocator>::size_type erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.4.5 Header <set> synopsis [associative.set.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [set], class template set template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> class set; template<class Key, class Compare, class Allocator> bool operator==(const set<Key, Compare, Allocator>& x, const set<Key, Compare, Allocator>& y); template<class Key, class Compare, class Allocator> synth-three-way-result<Key> operator<=>(const set<Key, Compare, Allocator>& x, const set<Key, Compare, Allocator>& y); template<class Key, class Compare, class Allocator> void swap(set<Key, Compare, Allocator>& x, set<Key, Compare, Allocator>& y) noexcept(noexcept(x.swap(y))); // [set.erasure], erasure for set template<class Key, class Compare, class Allocator, class Predicate> typename set<Key, Compare, Allocator>::size_type erase_if(set<Key, Compare, Allocator>& c, Predicate pred); // [multiset], class template multiset template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> class multiset; template<class Key, class Compare, class Allocator> bool operator==(const multiset<Key, Compare, Allocator>& x, const multiset<Key, Compare, Allocator>& y); template<class Key, class Compare, class Allocator> synth-three-way-result<Key> operator<=>(const multiset<Key, Compare, Allocator>& x, const multiset<Key, Compare, Allocator>& y); template<class Key, class Compare, class Allocator> void swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y) noexcept(noexcept(x.swap(y))); // [multiset.erasure], erasure for multiset template<class Key, class Compare, class Allocator, class Predicate> typename multiset<Key, Compare, Allocator>::size_type erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); namespace pmr { template<class Key, class Compare = less<Key>> using set = std::set<Key, Compare, polymorphic_allocator<Key>>; template<class Key, class Compare = less<Key>> using multiset = std::multiset<Key, Compare, polymorphic_allocator<Key>>; } }

23.4.6 Class template set [set]

23.4.6.1 Overview [set.overview]

A set is an associative container that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of the keys themselves.
The set class supports bidirectional iterators.
A set meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]).
and of an associative container ([associative.reqmts]).
A set also provides most operations described in [associative.reqmts] for unique keys.
This means that a set supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a set<Key> both the key_type and value_type are Key.
Descriptions are provided here only for operations on set that are not described in one of these tables and for operations where there is additional semantic information.
namespace std { template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> class set { public: // types using key_type = Key; using key_compare = Compare; using value_type = Key; using value_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = unspecified; using insert_return_type = insert-return-type<iterator, node_type>; // [set.cons], construct/copy/destroy set() : set(Compare()) { } explicit set(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<container-compatible-range<value_type> R> set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); set(const set& x); set(set&& x); explicit set(const Allocator&); set(const set&, const type_identity_t<Allocator>&); set(set&&, const type_identity_t<Allocator>&); set(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator> set(InputIterator first, InputIterator last, const Allocator& a) : set(first, last, Compare(), a) { } template<container-compatible-range<value_type> R> set(from_range_t, R&& rg, const Allocator& a)) : set(from_range, std::forward<R>(rg), Compare(), a) { } set(initializer_list<value_type> il, const Allocator& a) : set(il, Compare(), a) { } ~set(); set& operator=(const set& x); set& operator=(set&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); set& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [set.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator,bool> insert(const value_type& x); pair<iterator,bool> insert(value_type&& x); template<class K> pair<iterator, bool> insert(K&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template<class K> iterator insert(const_iterator position, K&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); insert_return_type insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position) requires (!same_as<iterator, const_iterator>); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(set&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); void clear() noexcept; template<class C2> void merge(set<Key, C2, Allocator>& source); template<class C2> void merge(set<Key, C2, Allocator>&& source); template<class C2> void merge(multiset<Key, C2, Allocator>& source); template<class C2> void merge(multiset<Key, C2, Allocator>&& source); // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>, class Allocator = allocator<iter-value-type<InputIterator>>> set(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> set<iter-value-type<InputIterator>, Compare, Allocator>; template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> set<ranges::range_value_t<R>, Compare, Allocator>; template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) -> set<Key, Compare, Allocator>; template<class InputIterator, class Allocator> set(InputIterator, InputIterator, Allocator) -> set<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> set(from_range_t, R&&, Allocator) -> set<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>; template<class Key, class Allocator> set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>; }

23.4.6.2 Constructors, copy, and assignment [set.cons]

explicit set(const Compare& comp, const Allocator& = Allocator());
Effects: Constructs an empty set using the specified comparison object and allocator.
Complexity: Constant.
template<class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range [first, last).
Complexity: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise , where N is last - first.
template<container-compatible-range<value_type> R> set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range rg.
Complexity: Linear in N if rg is already sorted with respect to comp and otherwise , where N is ranges​::​distance(rg).

23.4.6.3 Erasure [set.erasure]

template<class Key, class Compare, class Allocator, class Predicate> typename set<Key, Compare, Allocator>::size_type erase_if(set<Key, Compare, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.4.6.4 Modifiers [set.modifiers]

template<class K> pair<iterator, bool> insert(K&& x); template<class K> iterator insert(const_iterator hint, K&& x);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
For the second overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false.
Preconditions: value_type is Cpp17EmplaceConstructible into set from std​::​forward<K>(x).
Effects: If the set already contains an element that is equivalent to x, there is no effect.
Otherwise, let r be equal_range(x).
Constructs an object u of type value_type with std​::​forward<K>(x).
If equal_range(u) == r is false, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the set element that is equivalent to x.
Complexity: Logarithmic.

23.4.7 Class template multiset [multiset]

23.4.7.1 Overview [multiset.overview]

A multiset is an associative container that supports equivalent keys (i.e., possibly contains multiple copies of the same key value) and provides for fast retrieval of the keys themselves.
The multiset class supports bidirectional iterators.
A multiset meets all of the requirements of a container ([container.reqmts]), of a reversible container ([container.rev.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), of an associative container ([associative.reqmts]).
multiset also provides most operations described in [associative.reqmts] for duplicate keys.
This means that a multiset supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a multiset<Key> both the key_type and value_type are Key.
Descriptions are provided here only for operations on multiset that are not described in one of these tables and for operations where there is additional semantic information.
namespace std { template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> class multiset { public: // types using key_type = Key; using key_compare = Compare; using value_type = Key; using value_compare = Compare; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using node_type = unspecified; // [multiset.cons], construct/copy/destroy multiset() : multiset(Compare()) { } explicit multiset(const Compare& comp, const Allocator& = Allocator()); template<class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); template<container-compatible-range<value_type> R> multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); multiset(const multiset& x); multiset(multiset&& x); explicit multiset(const Allocator&); multiset(const multiset&, const type_identity_t<Allocator>&); multiset(multiset&&, const type_identity_t<Allocator>&); multiset(initializer_list<value_type>, const Compare& = Compare(), const Allocator& = Allocator()); template<class InputIterator> multiset(InputIterator first, InputIterator last, const Allocator& a) : multiset(first, last, Compare(), a) { } template<container-compatible-range<value_type> R> multiset(from_range_t, R&& rg, const Allocator& a)) : multiset(from_range, std::forward<R>(rg), Compare(), a) { } multiset(initializer_list<value_type> il, const Allocator& a) : multiset(il, Compare(), a) { } ~multiset(); multiset& operator=(const multiset& x); multiset& operator=(multiset&& x) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>); multiset& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x); iterator insert(value_type&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); iterator insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position) requires (!same_as<iterator, const_iterator>); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(multiset&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>); void clear() noexcept; template<class C2> void merge(multiset<Key, C2, Allocator>& source); template<class C2> void merge(multiset<Key, C2, Allocator>&& source); template<class C2> void merge(set<Key, C2, Allocator>& source); template<class C2> void merge(set<Key, C2, Allocator>&& source); // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; }; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>, class Allocator = allocator<iter-value-type<InputIterator>>> multiset(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> multiset<iter-value-type<InputIterator>, Compare, Allocator>; template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> multiset<ranges::range_value_t<R>, Compare, Allocator>; template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) -> multiset<Key, Compare, Allocator>; template<class InputIterator, class Allocator> multiset(InputIterator, InputIterator, Allocator) -> multiset<iter-value-type<InputIterator>, less<iter-value-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> multiset(from_range_t, R&&, Allocator) -> multiset<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>; template<class Key, class Allocator> multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>; }

23.4.7.2 Constructors [multiset.cons]

explicit multiset(const Compare& comp, const Allocator& = Allocator());
Effects: Constructs an empty multiset using the specified comparison object and allocator.
Complexity: Constant.
template<class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty multiset using the specified comparison object and allocator, and inserts elements from the range [first, last).
Complexity: Linear in N if the range [first, last) is already sorted with respect to comp and otherwise , where N is last - first.
template<container-compatible-range<value_type> R> multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator());
Effects: Constructs an empty multiset using the specified comparison object and allocator, and inserts elements from the range rg.
Complexity: Linear in N if rg is already sorted with respect to comp and otherwise , where N is ranges​::​distance(rg).

23.4.7.3 Erasure [multiset.erasure]

template<class Key, class Compare, class Allocator, class Predicate> typename multiset<Key, Compare, Allocator>::size_type erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.5 Unordered associative containers [unord]

23.5.1 General [unord.general]

The header <unordered_map> defines the class templates unordered_map and unordered_multimap; the header <unordered_set> defines the class templates unordered_set and unordered_multiset.
The exposition-only alias templates iter-value-type, iter-key-type, iter-mapped-type, iter-to-alloc-type, range-key-type, range-mapped-type, and range-to-alloc-type defined in [associative.general] may appear in deduction guides for unordered containers.

23.5.2 Header <unordered_map> synopsis [unord.map.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [unord.map], class template unordered_map template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Alloc = allocator<pair<const Key, T>>> class unordered_map; // [unord.multimap], class template unordered_multimap template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Alloc = allocator<pair<const Key, T>>> class unordered_multimap; template<class Key, class T, class Hash, class Pred, class Alloc> bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& a, const unordered_map<Key, T, Hash, Pred, Alloc>& b); template<class Key, class T, class Hash, class Pred, class Alloc> bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a, const unordered_multimap<Key, T, Hash, Pred, Alloc>& b); template<class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x, unordered_map<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); template<class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x, unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); // [unord.map.erasure], erasure for unordered_map template<class K, class T, class H, class P, class A, class Predicate> typename unordered_map<K, T, H, P, A>::size_type erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred); // [unord.multimap.erasure], erasure for unordered_multimap template<class K, class T, class H, class P, class A, class Predicate> typename unordered_multimap<K, T, H, P, A>::size_type erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred); namespace pmr { template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>> using unordered_map = std::unordered_map<Key, T, Hash, Pred, polymorphic_allocator<pair<const Key, T>>>; template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>> using unordered_multimap = std::unordered_multimap<Key, T, Hash, Pred, polymorphic_allocator<pair<const Key, T>>>; } }

23.5.3 Class template unordered_map [unord.map]

23.5.3.1 Overview [unord.map.overview]

An unordered_map is an unordered associative container that supports unique keys (an unordered_map contains at most one of each key value) and that associates values of another type mapped_type with the keys.
The unordered_map class supports forward iterators.
An unordered_map meets all of the requirements of a container ([container.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of an unordered associative container ([unord.req]).
It provides the operations described in the preceding requirements table for unique keys; that is, an unordered_map supports the a_uniq operations in that table, not the a_eq operations.
For an unordered_map<Key, T> the key_type is Key, the mapped_type is T, and the value_type is pair<const Key, T>.
Subclause [unord.map] only describes operations on unordered_map that are not described in one of the requirement tables, or for which there is additional semantic information.
namespace std { template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> class unordered_map { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<const Key, T>; using hasher = Hash; using key_equal = Pred; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using local_iterator = implementation-defined; // see [container.requirements] using const_local_iterator = implementation-defined; // see [container.requirements] using node_type = unspecified; using insert_return_type = insert-return-type<iterator, node_type>; // [unord.map.cnstr], construct/copy/destroy unordered_map(); explicit unordered_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<class InputIterator> unordered_map(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_map(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(const unordered_map&); unordered_map(unordered_map&&); explicit unordered_map(const Allocator&); unordered_map(const unordered_map&, const type_identity_t<Allocator>&); unordered_map(unordered_map&&, const type_identity_t<Allocator>&); unordered_map(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(size_type n, const allocator_type& a) : unordered_map(n, hasher(), key_equal(), a) { } unordered_map(size_type n, const hasher& hf, const allocator_type& a) : unordered_map(n, hf, key_equal(), a) { } template<class InputIterator> unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_map(f, l, n, hasher(), key_equal(), a) { } template<class InputIterator> 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<container-compatible-range<value_type> R> unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) : unordered_map(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } template<container-compatible-range<value_type> R> unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) { } unordered_map(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(il, n, hf, key_equal(), a) { } ~unordered_map(); unordered_map& operator=(const unordered_map&); unordered_map& operator=(unordered_map&&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>); unordered_map& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [unord.map.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& obj); pair<iterator, bool> insert(value_type&& obj); template<class P> pair<iterator, bool> insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template<class P> iterator insert(const_iterator hint, P&& obj); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); insert_return_type insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args); template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& k); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(unordered_map&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>); void clear() noexcept; template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>&& source); template<class H2, class P2> void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source); // observers hasher hash_function() const; key_equal key_eq() const; // map operations iterator find(const key_type& k); const_iterator find(const key_type& k) const; template<class K> iterator find(const K& k); template<class K> const_iterator find(const K& k) const; size_type count(const key_type& k) const; template<class K> size_type count(const K& k) const; bool contains(const key_type& k) const; template<class K> bool contains(const K& k) const; pair<iterator, iterator> equal_range(const key_type& k); pair<const_iterator, const_iterator> equal_range(const key_type& k) const; template<class K> pair<iterator, iterator> equal_range(const K& k); template<class K> pair<const_iterator, const_iterator> equal_range(const K& k) const; // [unord.map.elem], element access mapped_type& operator[](const key_type& k); mapped_type& operator[](key_type&& k); template<class K> mapped_type& operator[](K&& k); mapped_type& at(const key_type& k); const mapped_type& at(const key_type& k) const; template<class K> mapped_type& at(const K& k); template<class K> const mapped_type& at(const K& k) const; // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; template<class K> size_type bucket(const K& k) const; local_iterator begin(size_type n); const_local_iterator begin(size_type n) const; local_iterator end(size_type n); const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template<class InputIterator, class Hash = hash<iter-key-type<InputIterator>>, class Pred = equal_to<iter-key-type<InputIterator>>, class Allocator = allocator<iter-to-alloc-type<InputIterator>>> unordered_map(InputIterator, InputIterator, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, Pred, Allocator>; template<ranges::input_range R, class Hash = hash<range-key-type<R>>, class Pred = equal_to<range-key-type<R>>, class Allocator = allocator<range-to-alloc-type<R>>> unordered_map(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_map(initializer_list<pair<Key, T>>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map<Key, T, Hash, Pred, Allocator>; template<class InputIterator, class Allocator> unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, hash<iter-key-type<InputIterator>>, equal_to<iter-key-type<InputIterator>>, Allocator>; template<class InputIterator, class Allocator> unordered_map(InputIterator, InputIterator, Allocator) -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, hash<iter-key-type<InputIterator>>, equal_to<iter-key-type<InputIterator>>, Allocator>; template<class InputIterator, class Hash, class Allocator> unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, equal_to<iter-key-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_map(from_range_t, R&&, typename see below::size_type, Allocator) -> unordered_map<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, equal_to<range-key-type<R>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_map(from_range_t, R&&, Allocator) -> unordered_map<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, equal_to<range-key-type<R>>, Allocator>; template<ranges::input_range R, class Hash, class Allocator> unordered_map(from_range_t, R&&, typename see below::size_type, Hash, Allocator) -> unordered_map<range-key-type<R>, range-mapped-type<R>, Hash, equal_to<range-key-type<R>>, Allocator>; template<class Key, class T, class Allocator> unordered_map(initializer_list<pair<Key, T>>, typename see below::size_type, Allocator) -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Allocator> unordered_map(initializer_list<pair<Key, T>>, Allocator) -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Hash, class Allocator> unordered_map(initializer_list<pair<Key, T>>, typename see below::size_type, Hash, Allocator) -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>; }
A size_type parameter type in an unordered_map deduction guide refers to the size_type member type of the type deduced by the deduction guide.

23.5.3.2 Constructors [unord.map.cnstr]

unordered_map() : unordered_map(size_type(see below)) { } explicit unordered_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_map using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
For the default constructor, the number of buckets is implementation-defined.
max_load_factor() returns 1.0.
Complexity: Constant.
template<class InputIterator> unordered_map(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_map(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_map using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
If n is not provided, the number of buckets is implementation-defined.
Then inserts elements from the range [f, l), rg, or il, respectively.
max_load_factor() returns 1.0.
Complexity: Average case linear, worst case quadratic.

23.5.3.3 Element access [unord.map.elem]

mapped_type& operator[](const key_type& k);
Effects: Equivalent to: return try_emplace(k).first->second;
mapped_type& operator[](key_type&& k);
Effects: Equivalent to: return try_emplace(std​::​move(k)).first->second;
template<class K> mapped_type& operator[](K&& k);
Constraints: The qualified-ids Hash​::​is_transparent and Pred​::​is_transparent are valid and denote types.
Effects: Equivalent to: return try_emplace(std​::​forward<K>(k)).first->second;
mapped_type& at(const key_type& k); const mapped_type& at(const key_type& k) const;
Returns: A reference to x.second, where x is the (unique) element whose key is equivalent to k.
Throws: An exception object of type out_of_range if no such element is present.
template<class K> mapped_type& at(const K& k); template<class K> const mapped_type& at(const K& k) const;
Constraints: The qualified-ids Hash​::​is_transparent and Pred​::​is_transparent are valid and denote types.
Preconditions: The expression find(k) is well-formed and has well-defined behavior.
Returns: A reference to find(k)->second.
Throws: An exception object of type out_of_range if find(k) == end() is true.

23.5.3.4 Modifiers [unord.map.modifiers]

template<class P> pair<iterator, bool> insert(P&& obj);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: Equivalent to: return emplace(std​::​forward<P>(obj));
template<class P> iterator insert(const_iterator hint, P&& obj);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: Equivalent to: return emplace_hint(hint, std​::​forward<P>(obj));
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from piecewise_construct, forward_as_tuple(k), forward_as_tuple(std​::​forward<Args>(args)...).
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k), forward_as_tuple(std​::​forward<Args>(args)...).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from piecewise_construct, forward_as_tuple(std​::​move(k)), forward_as_tuple(std​::​forward<Args>(args)...).
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(std​::​move(k)), forward_as_tuple(std​::​forward<Args>(args)...).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
Constraints: The qualified-ids Hash​::​is_transparent and Pred​::​is_transparent are valid and denote types.
For the first overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false.
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from piecewise_construct, forward_as_tuple(std​::​forward<K>(k)), forward_as_tuple(std​::​forward<Args>
(args)...)
.
Effects: If the map already contains an element whose key is equivalent to k, there is no effect.
Otherwise, let h be hash_function()(k).
Constructs an object u of type value_type with piecewise_construct, forward_as_tuple(std​::​forward<K>(k)), forward_as_tuple(std​::​forward<Args>(args)...).

If hash_function()(u.first) != h || contains(u.first) is true, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from k, std​::​forward<M>(obj).
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise inserts an object of type value_type constructed with k, std​::​forward<M>(obj).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from std​::​move(k), std​::​​forward<M>(obj).
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise inserts an object of type value_type constructed with std​::​​move(k), std​::​forward<M>(obj).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
Constraints: The qualified-ids Hash​::​is_transparent and Pred​::​is_transparent are valid and denote types.
Mandates: is_assignable_v<mapped_type&, M&&> is true.
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_map from std​::​forward<K>
(k), std​::​forward<M>(obj)
.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>
(obj)
to e.second.
Otherwise, let h be hash_function()(k).
Constructs an object u of type value_type with std​::​forward<K>(k), std​::​forward<M>(obj).
If hash_function()(u.first) != h || contains(u.first) is true, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.

23.5.3.5 Erasure [unord.map.erasure]

template<class K, class T, class H, class P, class A, class Predicate> typename unordered_map<K, T, H, P, A>::size_type erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.5.4 Class template unordered_multimap [unord.multimap]

23.5.4.1 Overview [unord.multimap.overview]

An unordered_multimap is an unordered associative container that supports equivalent keys (an instance of unordered_multimap may contain multiple copies of each key value) and that associates values of another type mapped_type with the keys.
The unordered_multimap class supports forward iterators.
An unordered_multimap meets all of the requirements of a container ([container.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of an unordered associative container ([unord.req]).
It provides the operations described in the preceding requirements table for equivalent keys; that is, an unordered_multimap supports the a_eq operations in that table, not the a_uniq operations.
For an unordered_multimap<Key, T> the key_type is Key, the mapped_type is T, and the value_type is pair<const Key, T>.
Subclause [unord.multimap] only describes operations on unordered_multimap that are not described in one of the requirement tables, or for which there is additional semantic information.
namespace std { template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> class unordered_multimap { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<const Key, T>; using hasher = Hash; using key_equal = Pred; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using local_iterator = implementation-defined; // see [container.requirements] using const_local_iterator = implementation-defined; // see [container.requirements] using node_type = unspecified; // [unord.multimap.cnstr], construct/copy/destroy unordered_multimap(); explicit unordered_multimap(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<class InputIterator> unordered_multimap(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_multimap(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(const unordered_multimap&); unordered_multimap(unordered_multimap&&); explicit unordered_multimap(const Allocator&); unordered_multimap(const unordered_multimap&, const type_identity_t<Allocator>&); unordered_multimap(unordered_multimap&&, const type_identity_t<Allocator>&); unordered_multimap(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(size_type n, const allocator_type& a) : unordered_multimap(n, hasher(), key_equal(), a) { } unordered_multimap(size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(n, hf, key_equal(), a) { } template<class InputIterator> unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_multimap(f, l, n, hasher(), key_equal(), a) { } template<class InputIterator> 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<container-compatible-range<value_type> R> unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a) : unordered_multimap(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } template<container-compatible-range<value_type> R> unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) { } unordered_multimap(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(il, n, hf, key_equal(), a) { } ~unordered_multimap(); unordered_multimap& operator=(const unordered_multimap&); unordered_multimap& operator=(unordered_multimap&&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>); unordered_multimap& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [unord.multimap.modifiers], modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& obj); iterator insert(value_type&& obj); template<class P> iterator insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template<class P> iterator insert(const_iterator hint, P&& obj); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); iterator insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& k); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(unordered_multimap&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>); void clear() noexcept; template<class H2, class P2> void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source); template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>&& source); // observers hasher hash_function() const; key_equal key_eq() const; // map operations iterator find(const key_type& k); const_iterator find(const key_type& k) const; template<class K> iterator find(const K& k); template<class K> const_iterator find(const K& k) const; size_type count(const key_type& k) const; template<class K> size_type count(const K& k) const; bool contains(const key_type& k) const; template<class K> bool contains(const K& k) const; pair<iterator, iterator> equal_range(const key_type& k); pair<const_iterator, const_iterator> equal_range(const key_type& k) const; template<class K> pair<iterator, iterator> equal_range(const K& k); template<class K> pair<const_iterator, const_iterator> equal_range(const K& k) const; // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; template<class K> size_type bucket(const K& k) const; local_iterator begin(size_type n); const_local_iterator begin(size_type n) const; local_iterator end(size_type n); const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template<class InputIterator, class Hash = hash<iter-key-type<InputIterator>>, class Pred = equal_to<iter-key-type<InputIterator>>, class Allocator = allocator<iter-to-alloc-type<InputIterator>>> unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, Pred, Allocator>; template<ranges::input_range R, class Hash = hash<range-key-type<R>>, class Pred = equal_to<range-key-type<R>>, class Allocator = allocator<range-to-alloc-type<R>>> unordered_multimap(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap<Key, T, Hash, Pred, Allocator>; template<class InputIterator, class Allocator> unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, hash<iter-key-type<InputIterator>>, equal_to<iter-key-type<InputIterator>>, Allocator>; template<class InputIterator, class Allocator> unordered_multimap(InputIterator, InputIterator, Allocator) -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, hash<iter-key-type<InputIterator>>, equal_to<iter-key-type<InputIterator>>, Allocator>; template<class InputIterator, class Hash, class Allocator> unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, equal_to<iter-key-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_multimap(from_range_t, R&&, typename see below::size_type, Allocator) -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, equal_to<range-key-type<R>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_multimap(from_range_t, R&&, Allocator) -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, equal_to<range-key-type<R>>, Allocator>; template<ranges::input_range R, class Hash, class Allocator> unordered_multimap(from_range_t, R&&, typename see below::size_type, Hash, Allocator) -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, equal_to<range-key-type<R>>, Allocator>; template<class Key, class T, class Allocator> unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type, Allocator) -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Allocator> unordered_multimap(initializer_list<pair<Key, T>>, Allocator) -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Hash, class Allocator> unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type, Hash, Allocator) -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>; }
A size_type parameter type in an unordered_multimap deduction guide refers to the size_type member type of the type deduced by the deduction guide.

23.5.4.2 Constructors [unord.multimap.cnstr]

unordered_multimap() : unordered_multimap(size_type(see below)) { } explicit unordered_multimap(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_multimap using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
For the default constructor, the number of buckets is implementation-defined.
max_load_factor() returns 1.0.
Complexity: Constant.
template<class InputIterator> unordered_multimap(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_multimap(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_multimap using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
If n is not provided, the number of buckets is implementation-defined.
Then inserts elements from the range [f, l), rg, or il, respectively.
max_load_factor() returns 1.0.
Complexity: Average case linear, worst case quadratic.

23.5.4.3 Modifiers [unord.multimap.modifiers]

template<class P> iterator insert(P&& obj);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: Equivalent to: return emplace(std​::​forward<P>(obj));
template<class P> iterator insert(const_iterator hint, P&& obj);
Constraints: is_constructible_v<value_type, P&&> is true.
Effects: Equivalent to: return emplace_hint(hint, std​::​forward<P>(obj));

23.5.4.4 Erasure [unord.multimap.erasure]

template<class K, class T, class H, class P, class A, class Predicate> typename unordered_multimap<K, T, H, P, A>::size_type erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.5.5 Header <unordered_set> synopsis [unord.set.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [unord.set], class template unordered_set template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>, class Alloc = allocator<Key>> class unordered_set; // [unord.multiset], class template unordered_multiset template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>, class Alloc = allocator<Key>> class unordered_multiset; template<class Key, class Hash, class Pred, class Alloc> bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& a, const unordered_set<Key, Hash, Pred, Alloc>& b); template<class Key, class Hash, class Pred, class Alloc> bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& a, const unordered_multiset<Key, Hash, Pred, Alloc>& b); template<class Key, class Hash, class Pred, class Alloc> void swap(unordered_set<Key, Hash, Pred, Alloc>& x, unordered_set<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); template<class Key, class Hash, class Pred, class Alloc> void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x, unordered_multiset<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); // [unord.set.erasure], erasure for unordered_set template<class K, class H, class P, class A, class Predicate> typename unordered_set<K, H, P, A>::size_type erase_if(unordered_set<K, H, P, A>& c, Predicate pred); // [unord.multiset.erasure], erasure for unordered_multiset template<class K, class H, class P, class A, class Predicate> typename unordered_multiset<K, H, P, A>::size_type erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred); namespace pmr { template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>> using unordered_set = std::unordered_set<Key, Hash, Pred, polymorphic_allocator<Key>>; template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>> using unordered_multiset = std::unordered_multiset<Key, Hash, Pred, polymorphic_allocator<Key>>; } }

23.5.6 Class template unordered_set [unord.set]

23.5.6.1 Overview [unord.set.overview]

An unordered_set is an unordered associative container that supports unique keys (an unordered_set contains at most one of each key value) and in which the elements' keys are the elements themselves.
The unordered_set class supports forward iterators.
An unordered_set meets all of the requirements of a container ([container.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), of an unordered associative container ([unord.req]).
It provides the operations described in the preceding requirements table for unique keys; that is, an unordered_set supports the a_uniq operations in that table, not the a_eq operations.
For an unordered_set<Key> the key_type and the value_type are both Key.
The iterator and const_iterator types are both constant iterator types.
It is unspecified whether they are the same type.
Subclause [unord.set] only describes operations on unordered_set that are not described in one of the requirement tables, or for which there is additional semantic information.
namespace std { template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<Key>> class unordered_set { public: // types using key_type = Key; using value_type = Key; using hasher = Hash; using key_equal = Pred; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using local_iterator = implementation-defined; // see [container.requirements] using const_local_iterator = implementation-defined; // see [container.requirements] using node_type = unspecified; using insert_return_type = insert-return-type<iterator, node_type>; // [unord.set.cnstr], construct/copy/destroy unordered_set(); explicit unordered_set(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_set(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_set(const unordered_set&); unordered_set(unordered_set&&); explicit unordered_set(const Allocator&); unordered_set(const unordered_set&, const type_identity_t<Allocator>&); unordered_set(unordered_set&&, const type_identity_t<Allocator>&); unordered_set(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_set(size_type n, const allocator_type& a) : unordered_set(n, hasher(), key_equal(), a) { } unordered_set(size_type n, const hasher& hf, const allocator_type& a) : unordered_set(n, hf, key_equal(), a) { } template<class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_set(f, l, n, hasher(), key_equal(), a) { } template<class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(f, l, n, hf, key_equal(), a) { } unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_set(il, n, hasher(), key_equal(), a) { } template<container-compatible-range<value_type> R> unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a) : unordered_set(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } template<container-compatible-range<value_type> R> unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } unordered_set(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(il, n, hf, key_equal(), a) { } ~unordered_set(); unordered_set& operator=(const unordered_set&); unordered_set& operator=(unordered_set&&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>); unordered_set& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [unord.set.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& obj); pair<iterator, bool> insert(value_type&& obj); template<class K> pair<iterator, bool> insert(K&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template<class K> iterator insert(const_iterator hint, K&& obj); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); insert_return_type insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position) requires (!same_as<iterator, const_iterator>); iterator erase(const_iterator position); size_type erase(const key_type& k); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(unordered_set&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>); void clear() noexcept; template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>&& source); template<class H2, class P2> void merge(unordered_multiset<Key, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_multiset<Key, H2, P2, Allocator>&& source); // observers hasher hash_function() const; key_equal key_eq() const; // set operations iterator find(const key_type& k); const_iterator find(const key_type& k) const; template<class K> iterator find(const K& k); template<class K> const_iterator find(const K& k) const; size_type count(const key_type& k) const; template<class K> size_type count(const K& k) const; bool contains(const key_type& k) const; template<class K> bool contains(const K& k) const; pair<iterator, iterator> equal_range(const key_type& k); pair<const_iterator, const_iterator> equal_range(const key_type& k) const; template<class K> pair<iterator, iterator> equal_range(const K& k); template<class K> pair<const_iterator, const_iterator> equal_range(const K& k) const; // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; template<class K> size_type bucket(const K& k) const; local_iterator begin(size_type n); const_local_iterator begin(size_type n) const; local_iterator end(size_type n); const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template<class InputIterator, class Hash = hash<iter-value-type<InputIterator>>, class Pred = equal_to<iter-value-type<InputIterator>>, class Allocator = allocator<iter-value-type<InputIterator>>> unordered_set(InputIterator, InputIterator, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_set<iter-value-type<InputIterator>, Hash, Pred, Allocator>; template<ranges::input_range R, class Hash = hash<ranges::range_value_t<R>>, class Pred = equal_to<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> unordered_set(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_set<ranges::range_value_t<R>, Hash, Pred, Allocator>; template<class T, class Hash = hash<T>, class Pred = equal_to<T>, class Allocator = allocator<T>> unordered_set(initializer_list<T>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_set<T, Hash, Pred, Allocator>; template<class InputIterator, class Allocator> unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_set<iter-value-type<InputIterator>, hash<iter-value-type<InputIterator>>, equal_to<iter-value-type<InputIterator>>, Allocator>; template<class InputIterator, class Hash, class Allocator> unordered_set(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_set<iter-value-type<InputIterator>, Hash, equal_to<iter-value-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_set(from_range_t, R&&, typename see below::size_type, Allocator) -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, equal_to<ranges::range_value_t<R>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_set(from_range_t, R&&, Allocator) -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, equal_to<ranges::range_value_t<R>>, Allocator>; template<ranges::input_range R, class Hash, class Allocator> unordered_set(from_range_t, R&&, typename see below::size_type, Hash, Allocator) -> unordered_set<ranges::range_value_t<R>, Hash, equal_to<ranges::range_value_t<R>>, Allocator>; template<class T, class Allocator> unordered_set(initializer_list<T>, typename see below::size_type, Allocator) -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; template<class T, class Hash, class Allocator> unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator) -> unordered_set<T, Hash, equal_to<T>, Allocator>; }
A size_type parameter type in an unordered_set deduction guide refers to the size_type member type of the type deduced by the deduction guide.

23.5.6.2 Constructors [unord.set.cnstr]

unordered_set() : unordered_set(size_type(see below)) { } explicit unordered_set(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_set using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
For the default constructor, the number of buckets is implementation-defined.
max_load_factor() returns 1.0.
Complexity: Constant.
template<class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_multiset(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_set(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_set using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
If n is not provided, the number of buckets is implementation-defined.
Then inserts elements from the range [f, l), rg, or il, respectively.
max_load_factor() returns 1.0.
Complexity: Average case linear, worst case quadratic.

23.5.6.3 Erasure [unord.set.erasure]

template<class K, class H, class P, class A, class Predicate> typename unordered_set<K, H, P, A>::size_type erase_if(unordered_set<K, H, P, A>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.5.6.4 Modifiers [unord.set.modifiers]

template<class K> pair<iterator, bool> insert(K&& obj); template<class K> iterator insert(const_iterator hint, K&& obj);
Constraints: The qualified-ids Hash​::​is_transparent and Pred​::​is_transparent are valid and denote types.
For the second overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false.
Preconditions: value_type is Cpp17EmplaceConstructible into unordered_set from std​::​forward<K>
(obj)
.
Effects: If the set already contains an element that is equivalent to obj, there is no effect.
Otherwise, let h be hash_function()(obj).
Constructs an object u of type value_type with std​::​forward<K>(obj).
If hash_function()(u) != h || contains(u) is true, the behavior is undefined.
Inserts u into *this.
Returns: For the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the set element that is equivalent to obj.
Complexity: Average case constant, worst case linear.

23.5.7 Class template unordered_multiset [unord.multiset]

23.5.7.1 Overview [unord.multiset.overview]

An unordered_multiset is an unordered associative container that supports equivalent keys (an instance of unordered_multiset may contain multiple copies of the same key value) and in which each element's key is the element itself.
The unordered_multiset class supports forward iterators.
An unordered_multiset meets all of the requirements of a container ([container.reqmts]), of an allocator-aware container ([container.alloc.reqmts]), and of an unordered associative container ([unord.req]).
It provides the operations described in the preceding requirements table for equivalent keys; that is, an unordered_multiset supports the a_eq operations in that table, not the a_uniq operations.
For an unordered_multiset<Key> the key_type and the value_type are both Key.
The iterator and const_iterator types are both constant iterator types.
It is unspecified whether they are the same type.
Subclause [unord.multiset] only describes operations on unordered_multiset that are not described in one of the requirement tables, or for which there is additional semantic information.
namespace std { template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<Key>> class unordered_multiset { public: // types using key_type = Key; using value_type = Key; using hasher = Hash; using key_equal = Pred; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using size_type = implementation-defined; // see [container.requirements] using difference_type = implementation-defined; // see [container.requirements] using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using local_iterator = implementation-defined; // see [container.requirements] using const_local_iterator = implementation-defined; // see [container.requirements] using node_type = unspecified; // [unord.multiset.cnstr], construct/copy/destroy unordered_multiset(); explicit unordered_multiset(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<class InputIterator> unordered_multiset(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_multiset(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multiset(const unordered_multiset&); unordered_multiset(unordered_multiset&&); explicit unordered_multiset(const Allocator&); unordered_multiset(const unordered_multiset&, const type_identity_t<Allocator>&); unordered_multiset(unordered_multiset&&, const type_identity_t<Allocator>&); unordered_multiset(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multiset(size_type n, const allocator_type& a) : unordered_multiset(n, hasher(), key_equal(), a) { } unordered_multiset(size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(n, hf, key_equal(), a) { } template<class InputIterator> unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a) : unordered_multiset(f, l, n, hasher(), key_equal(), a) { } template<class InputIterator> 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<container-compatible-range<value_type> R> unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a) : unordered_multiset(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } template<container-compatible-range<value_type> R> unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_multiset(il, n, hasher(), key_equal(), a) { } unordered_multiset(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(il, n, hf, key_equal(), a) { } ~unordered_multiset(); unordered_multiset& operator=(const unordered_multiset&); unordered_multiset& operator=(unordered_multiset&&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>); unordered_multiset& operator=(initializer_list<value_type>); allocator_type get_allocator() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& obj); iterator insert(value_type&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type>); node_type extract(const_iterator position); node_type extract(const key_type& x); template<class K> node_type extract(K&& x); iterator insert(node_type&& nh); iterator insert(const_iterator hint, node_type&& nh); iterator erase(iterator position) requires (!same_as<iterator, const_iterator>); iterator erase(const_iterator position); size_type erase(const key_type& k); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(unordered_multiset&) noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>); void clear() noexcept; template<class H2, class P2> void merge(unordered_multiset<Key, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_multiset<Key, H2, P2, Allocator>&& source); template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>& source); template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>&& source); // observers hasher hash_function() const; key_equal key_eq() const; // set operations iterator find(const key_type& k); const_iterator find(const key_type& k) const; template<class K> iterator find(const K& k); template<class K> const_iterator find(const K& k) const; size_type count(const key_type& k) const; template<class K> size_type count(const K& k) const; bool contains(const key_type& k) const; template<class K> bool contains(const K& k) const; pair<iterator, iterator> equal_range(const key_type& k); pair<const_iterator, const_iterator> equal_range(const key_type& k) const; template<class K> pair<iterator, iterator> equal_range(const K& k); template<class K> pair<const_iterator, const_iterator> equal_range(const K& k) const; // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) const; size_type bucket(const key_type& k) const; template<class K> size_type bucket(const K& k) const; local_iterator begin(size_type n); const_local_iterator begin(size_type n) const; local_iterator end(size_type n); const_local_iterator end(size_type n) const; const_local_iterator cbegin(size_type n) const; const_local_iterator cend(size_type n) const; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z); void rehash(size_type n); void reserve(size_type n); }; template<class InputIterator, class Hash = hash<iter-value-type<InputIterator>>, class Pred = equal_to<iter-value-type<InputIterator>>, class Allocator = allocator<iter-value-type<InputIterator>>> unordered_multiset(InputIterator, InputIterator, see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multiset<iter-value-type<InputIterator>, Hash, Pred, Allocator>; template<ranges::input_range R, class Hash = hash<ranges::range_value_t<R>>, class Pred = equal_to<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> unordered_multiset(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multiset<ranges::range_value_t<R>, Hash, Pred, Allocator>; template<class T, class Hash = hash<T>, class Pred = equal_to<T>, class Allocator = allocator<T>> unordered_multiset(initializer_list<T>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multiset<T, Hash, Pred, Allocator>; template<class InputIterator, class Allocator> unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator) -> unordered_multiset<iter-value-type<InputIterator>, hash<iter-value-type<InputIterator>>, equal_to<iter-value-type<InputIterator>>, Allocator>; template<class InputIterator, class Hash, class Allocator> unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) -> unordered_multiset<iter-value-type<InputIterator>, Hash, equal_to<iter-value-type<InputIterator>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_multiset(from_range_t, R&&, typename see below::size_type, Allocator) -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, equal_to<ranges::range_value_t<R>>, Allocator>; template<ranges::input_range R, class Allocator> unordered_multiset(from_range_t, R&&, Allocator) -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, equal_to<ranges::range_value_t<R>>, Allocator>; template<ranges::input_range R, class Hash, class Allocator> unordered_multiset(from_range_t, R&&, typename see below::size_type, Hash, Allocator) -> unordered_multiset<ranges::range_value_t<R>, Hash, equal_to<ranges::range_value_t<R>>, Allocator>; template<class T, class Allocator> unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator) -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; template<class T, class Hash, class Allocator> unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator) -> unordered_multiset<T, Hash, equal_to<T>, Allocator>; }
A size_type parameter type in an unordered_multiset deduction guide refers to the size_type member type of the type deduced by the deduction guide.

23.5.7.2 Constructors [unord.multiset.cnstr]

unordered_multiset() : unordered_multiset(size_type(see below)) { } explicit unordered_multiset(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_multiset using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
For the default constructor, the number of buckets is implementation-defined.
max_load_factor() returns 1.0.
Complexity: Constant.
template<class InputIterator> unordered_multiset(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); template<container-compatible-range<value_type> R> unordered_multiset(from_range_t, R&& rg, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multiset(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());
Effects: Constructs an empty unordered_multiset using the specified hash function, key equality predicate, and allocator, and using at least n buckets.
If n is not provided, the number of buckets is implementation-defined.
Then inserts elements from the range [f, l), rg, or il, respectively.
max_load_factor() returns 1.0.
Complexity: Average case linear, worst case quadratic.

23.5.7.3 Erasure [unord.multiset.erasure]

template<class K, class H, class P, class A, class Predicate> typename unordered_multiset<K, H, P, A>::size_type erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);
Effects: Equivalent to: auto original_size = c.size(); for (auto i = c.begin(), last = c.end(); i != last; ) { if (pred(*i)) { i = c.erase(i); } else { ++i; } } return original_size - c.size();

23.6 Container adaptors [container.adaptors]

23.6.1 General [container.adaptors.general]

The headers <queue>, <stack>, <flat_map>, and <flat_set> define the container adaptors queue and priority_queue, stack, flat_map and flat_multimap, and flat_set and flat_multiset, respectively.
Each container adaptor takes one or more template parameters named Container, KeyContainer, or MappedContainer that denote the types of containers that the container adaptor adapts.
Each container adaptor has at least one constructor that takes a reference argument to one or more such template parameters.
For each constructor reference argument to a container C, the constructor copies the container into the container adaptor.
If C takes an allocator, then a compatible allocator may be passed in to the adaptor's constructor.
Otherwise, normal copy or move construction is used for the container argument.
For the container adaptors that take a single container template parameter Container, the first template parameter T of the container adaptor shall denote the same type as Container​::​value_type.
For container adaptors, no swap function throws an exception unless that exception is thrown by the swap of the adaptor's Container, KeyContainer, MappedContainer, or Compare object (if any).
A constructor template of a container adaptor shall not participate in overload resolution if it has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
For container adaptors that have them, the insert, emplace, and erase members affect the validity of iterators, references, and pointers to the adaptor's container(s) in the same way that the containers' respective insert, emplace, and erase members do.
[Example 1: 
A call to flat_map<Key, T>​::​insert can invalidate all iterators to the flat_map.
— end example]
A deduction guide for a container adaptor shall not participate in overload resolution if any of the following are true:
  • It has an InputIterator template parameter and a type that does not qualify as an input iterator is deduced for that parameter.
  • It has a Compare template parameter and a type that qualifies as an allocator is deduced for that parameter.
  • It has a Container, KeyContainer, or MappedContainer template parameter and a type that qualifies as an allocator is deduced for that parameter.
  • It has no Container, KeyContainer, or MappedContainer template parameter, and it has an Allocator template parameter, and a type that does not qualify as an allocator is deduced for that parameter.
  • It has both Container and Allocator template parameters, and uses_allocator_v<Container, Allocator> is false.
  • It has both KeyContainer and Allocator template parameters, and uses_allocator_v<KeyContainer, Allocator> is false.
  • It has both KeyContainer and Compare template parameters, and is_invocable_v<const Compare&, const typename KeyContainer::value_type&, const typename KeyContainer::value_type&> is not a valid expression or is false.
  • It has both MappedContainer and Allocator template parameters, and uses_allocator_v<MappedContainer, Allocator> is false.
The exposition-only alias template iter-value-type defined in [sequences.general] and the exposition-only alias templates iter-key-type, iter-mapped-type, range-key-type, and range-mapped-type defined in [associative.general] may appear in deduction guides for container adaptors.
The following exposition-only alias template may appear in deduction guides for container adaptors: template<class Allocator, class T> using alloc-rebind = // exposition only typename allocator_traits<Allocator>::template rebind_alloc<T>;

23.6.2 Header <queue> synopsis [queue.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [queue], class template queue template<class T, class Container = deque<T>> class queue; template<class T, class Container> bool operator==(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator< (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator> (const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, three_way_comparable Container> compare_three_way_result_t<Container> operator<=>(const queue<T, Container>& x, const queue<T, Container>& y); template<class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc> struct uses_allocator<queue<T, Container>, Alloc>; // [container.adaptors.format], formatter specialization for queue template<class charT, class T, formattable<charT> Container> struct formatter<queue<T, Container>, charT>; // [priority.queue], class template priority_queue template<class T, class Container = vector<T>, class Compare = less<typename Container::value_type>> class priority_queue; template<class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Compare, class Alloc> struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>; // [container.adaptors.format], formatter specialization for priority_queue template<class charT, class T, formattable<charT> Container, class Compare> struct formatter<priority_queue<T, Container, Compare>, charT>; }

23.6.3 Class template queue [queue]

23.6.3.1 Definition [queue.defn]

Any sequence container supporting operations front(), back(), push_back() and pop_front() can be used to instantiate queue.
In particular, list and deque can be used.
namespace std { template<class T, class Container = deque<T>> class queue { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public: queue() : queue(Container()) {} explicit queue(const Container&); explicit queue(Container&&); template<class InputIterator> queue(InputIterator first, InputIterator last); template<container-compatible-range<T> R> queue(from_range_t, R&& rg); template<class Alloc> explicit queue(const Alloc&); template<class Alloc> queue(const Container&, const Alloc&); template<class Alloc> queue(Container&&, const Alloc&); template<class Alloc> queue(const queue&, const Alloc&); template<class Alloc> queue(queue&&, const Alloc&); template<class InputIterator, class Alloc> queue(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range<T> R, class Alloc> queue(from_range_t, R&& rg, const Alloc&); bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference front() { return c.front(); } const_reference front() const { return c.front(); } reference back() { return c.back(); } const_reference back() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } template<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); } void pop() { c.pop_front(); } void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>) { using std::swap; swap(c, q.c); } }; template<class Container> queue(Container) -> queue<typename Container::value_type, Container>; template<class InputIterator> queue(InputIterator, InputIterator) -> queue<iter-value-type<InputIterator>>; template<ranges::input_range R> queue(from_range_t, R&&) -> queue<ranges::range_value_t<R>>; template<class Container, class Allocator> queue(Container, Allocator) -> queue<typename Container::value_type, Container>; template<class InputIterator, class Allocator> queue(InputIterator, InputIterator, Allocator) -> queue<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; template<ranges::input_range R, class Allocator> queue(from_range_t, R&&, Allocator) -> queue<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; template<class T, class Container, class Alloc> struct uses_allocator<queue<T, Container>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

23.6.3.2 Constructors [queue.cons]

explicit queue(const Container& cont);
Effects: Initializes c with cont.
explicit queue(Container&& cont);
Effects: Initializes c with std​::​move(cont).
template<class InputIterator> queue(InputIterator first, InputIterator last);
Effects: Initializes c with first as the first argument and last as the second argument.
template<container-compatible-range<T> R> queue(from_range_t, R&& rg);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg)).

23.6.3.3 Constructors with allocators [queue.cons.alloc]

If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit queue(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> queue(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> queue(container_type&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument.
template<class Alloc> queue(const queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument.
template<class Alloc> queue(queue&& q, const Alloc& a);
Effects: Initializes c with std​::​move(q.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> queue(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c with first as the first argument, last as the second argument, and alloc as the third argument.
template<container-compatible-range<T> R, class Alloc> queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a).

23.6.3.4 Modifiers [queue.mod]

template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Equivalent to c.append_range(std​::​forward<R>(rg)) if that is a valid expression, otherwise ranges​::​copy(rg, back_inserter(c)).

23.6.3.5 Operators [queue.ops]

template<class T, class Container> bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c >= y.c.
template<class T, three_way_comparable Container> compare_three_way_result_t<Container> operator<=>(const queue<T, Container>& x, const queue<T, Container>& y);
Returns: x.c <=> y.c.

23.6.3.6 Specialized algorithms [queue.special]

template<class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v<Container> is true.
Effects: As if by x.swap(y).

23.6.4 Class template priority_queue [priority.queue]

23.6.4.1 Overview [priqueue.overview]

Any sequence container with random access iterator and supporting operations front(), push_back() and pop_back() can be used to instantiate priority_queue.
In particular, vector and deque can be used.
Instantiating priority_queue also involves supplying a function or function object for making priority comparisons; the library assumes that the function or function object defines a strict weak ordering.
namespace std { template<class T, class Container = vector<T>, class Compare = less<typename Container::value_type>> class priority_queue { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; using value_compare = Compare; protected: Container c; Compare comp; public: priority_queue() : priority_queue(Compare()) {} explicit priority_queue(const Compare& x) : priority_queue(x, Container()) {} priority_queue(const Compare& x, const Container&); priority_queue(const Compare& x, Container&&); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare()); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container&); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); template<container-compatible-range<T> R> priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template<class Alloc> explicit priority_queue(const Alloc&); template<class Alloc> priority_queue(const Compare&, const Alloc&); template<class Alloc> priority_queue(const Compare&, const Container&, const Alloc&); template<class Alloc> priority_queue(const Compare&, Container&&, const Alloc&); template<class Alloc> priority_queue(const priority_queue&, const Alloc&); template<class Alloc> priority_queue(priority_queue&&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, const Container&, const Alloc&); template<class InputIterator, class Alloc> priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Alloc&); 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<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> void emplace(Args&&... args); void pop(); void swap(priority_queue& q) noexcept(is_nothrow_swappable_v<Container> && is_nothrow_swappable_v<Compare>) { using std::swap; swap(c, q.c); swap(comp, q.comp); } }; template<class Compare, class Container> priority_queue(Compare, Container) -> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>, class Container = vector<iter-value-type<InputIterator>>> priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<iter-value-type<InputIterator>, Container, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>> priority_queue(from_range_t, R&&, Compare = Compare()) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>>, Compare>; template<class Compare, class Container, class Allocator> priority_queue(Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; template<class InputIterator, class Allocator> priority_queue(InputIterator, InputIterator, Allocator) -> priority_queue<iter-value-type<InputIterator>, vector<iter-value-type<InputIterator>, Allocator>, less<iter-value-type<InputIterator>>>; template<class InputIterator, class Compare, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Allocator) -> priority_queue<iter-value-type<InputIterator>, vector<iter-value-type<InputIterator>, Allocator>, Compare>; template<class InputIterator, class Compare, class Container, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; template<ranges::input_range R, class Compare, class Allocator> priority_queue(from_range_t, R&&, Compare, Allocator) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>, Compare>; template<ranges::input_range R, class Allocator> priority_queue(from_range_t, R&&, Allocator) -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>>; // no equality is provided template<class T, class Container, class Compare, class Alloc> struct uses_allocator<priority_queue<T, Container, Compare>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

23.6.4.2 Constructors [priqueue.cons]

priority_queue(const Compare& x, const Container& y); priority_queue(const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with y (copy constructing or move constructing as appropriate); calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes c with first as the first argument and last as the second argument, and initializes comp with x; then calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y); template<class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&& y);
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with y (copy constructing or move constructing as appropriate); calls c.insert(c.end(), first, last); and finally calls make_heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R> priority_queue(from_range_t, R&& rg, const Compare& x = Compare());
Preconditions: x defines a strict weak ordering ([alg.sorting]).
Effects: Initializes comp with x and c with ranges​::​to<Container>(std​::​forward<R>(rg)) and finally calls make_heap(c.begin(), c.end(), comp).

23.6.4.3 Constructors with allocators [priqueue.cons.alloc]

If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit priority_queue(const Alloc& a);
Effects: Initializes c with a and value-initializes comp.
template<class Alloc> priority_queue(const Compare& compare, const Alloc& a);
Effects: Initializes c with a and initializes comp with compare.
template<class Alloc> priority_queue(const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class Alloc> priority_queue(const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class Alloc> priority_queue(const priority_queue& q, const Alloc& a);
Effects: Initializes c with q.c as the first argument and a as the second argument, and initializes comp with q.comp.
template<class Alloc> priority_queue(priority_queue&& q, const Alloc& a);
Effects: Initializes c with std​::​move(q.c) as the first argument and a as the second argument, and initializes comp with std​::​move(q.comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Alloc& a);
Effects: Initializes c with first as the first argument, last as the second argument, and a as the third argument, and value-initializes comp; calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Alloc& a);
Effects: Initializes c with first as the first argument, last as the second argument, and a as the third argument, and initializes comp with compare; calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, const Container& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_heap(c.begin(), c.end(), comp).
template<class InputIterator, class Alloc> priority_queue(InputIterator first, InputIterator last, const Compare& compare, Container&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument, and initializes comp with compare; calls c.insert(c.end(), first, last); and finally calls make_heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a);
Effects: Initializes comp with compare and c with ranges​::​to<Container>(std​::​forward<R>(rg), a); calls make_heap(c.begin(), c.end(), comp).
template<container-compatible-range<T> R, class Alloc> priority_queue(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a) and value-initializes comp; calls make_heap(c.begin(), c.end(), comp).

23.6.4.4 Members [priqueue.members]

void push(const value_type& x);
Effects: As if by: c.push_back(x); push_heap(c.begin(), c.end(), comp);
void push(value_type&& x);
Effects: As if by: c.push_back(std::move(x)); push_heap(c.begin(), c.end(), comp);
template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Inserts all elements of rg in c via c.append_range(std​::​forward<R>(rg)) if that is a valid expression, or ranges​::​copy(rg, back_inserter(c)) otherwise.
Then restores the heap property as if by make_heap(c.begin(), c.end(), comp).
Postconditions: is_heap(c.begin(), c.end(), comp) is true.
template<class... Args> void emplace(Args&&... args);
Effects: As if by: c.emplace_back(std::forward<Args>(args)...); push_heap(c.begin(), c.end(), comp);
void pop();
Effects: As if by: pop_heap(c.begin(), c.end(), comp); c.pop_back();

23.6.4.5 Specialized algorithms [priqueue.special]

template<class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v<Container> is true and is_swappable_v<Compare> is true.
Effects: As if by x.swap(y).

23.6.5 Header <stack> synopsis [stack.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [stack], class template stack template<class T, class Container = deque<T>> class stack; template<class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator< (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator> (const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, three_way_comparable Container> compare_three_way_result_t<Container> operator<=>(const stack<T, Container>& x, const stack<T, Container>& y); template<class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y))); template<class T, class Container, class Alloc> struct uses_allocator<stack<T, Container>, Alloc>; // [container.adaptors.format], formatter specialization for stack template<class charT, class T, formattable<charT> Container> struct formatter<stack<T, Container>, charT>; }

23.6.6 Class template stack [stack]

23.6.6.1 General [stack.general]

Any sequence container supporting operations back(), push_back() and pop_back() can be used to instantiate stack.
In particular, vector, list and deque can be used.

23.6.6.2 Definition [stack.defn]

namespace std { template<class T, class Container = deque<T>> class stack { public: using value_type = typename Container::value_type; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using size_type = typename Container::size_type; using container_type = Container; protected: Container c; public: stack() : stack(Container()) {} explicit stack(const Container&); explicit stack(Container&&); template<class InputIterator> stack(InputIterator first, InputIterator last); template<container-compatible-range<T> R> stack(from_range_t, R&& rg); template<class Alloc> explicit stack(const Alloc&); template<class Alloc> stack(const Container&, const Alloc&); template<class Alloc> stack(Container&&, const Alloc&); template<class Alloc> stack(const stack&, const Alloc&); template<class Alloc> stack(stack&&, const Alloc&); template<class InputIterator, class Alloc> stack(InputIterator first, InputIterator last, const Alloc&); template<container-compatible-range<T> R, class Alloc> stack(from_range_t, R&& rg, const Alloc&); bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference top() { return c.back(); } const_reference top() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } template<container-compatible-range<T> R> void push_range(R&& rg); template<class... Args> decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); } void pop() { c.pop_back(); } void swap(stack& s) noexcept(is_nothrow_swappable_v<Container>) { using std::swap; swap(c, s.c); } }; template<class Container> stack(Container) -> stack<typename Container::value_type, Container>; template<class InputIterator> stack(InputIterator, InputIterator) -> stack<iter-value-type<InputIterator>>; template<ranges::input_range R> stack(from_range_t, R&&) -> stack<ranges::range_value_t<R>>; template<class Container, class Allocator> stack(Container, Allocator) -> stack<typename Container::value_type, Container>; template<class InputIterator, class Allocator> stack(InputIterator, InputIterator, Allocator) -> stack<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; template<ranges::input_range R, class Allocator> stack(from_range_t, R&&, Allocator) -> stack<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; template<class T, class Container, class Alloc> struct uses_allocator<stack<T, Container>, Alloc> : uses_allocator<Container, Alloc>::type { }; }

23.6.6.3 Constructors [stack.cons]

explicit stack(const Container& cont);
Effects: Initializes c with cont.
explicit stack(Container&& cont);
Effects: Initializes c with std​::​move(cont).
template<class InputIterator> stack(InputIterator first, InputIterator last);
Effects: Initializes c with first as the first argument and last as the second argument.
template<container-compatible-range<T> R> stack(from_range_t, R&& rg);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg)).

23.6.6.4 Constructors with allocators [stack.cons.alloc]

If uses_allocator_v<container_type, Alloc> is false the constructors in this subclause shall not participate in overload resolution.
template<class Alloc> explicit stack(const Alloc& a);
Effects: Initializes c with a.
template<class Alloc> stack(const container_type& cont, const Alloc& a);
Effects: Initializes c with cont as the first argument and a as the second argument.
template<class Alloc> stack(container_type&& cont, const Alloc& a);
Effects: Initializes c with std​::​move(cont) as the first argument and a as the second argument.
template<class Alloc> stack(const stack& s, const Alloc& a);
Effects: Initializes c with s.c as the first argument and a as the second argument.
template<class Alloc> stack(stack&& s, const Alloc& a);
Effects: Initializes c with std​::​move(s.c) as the first argument and a as the second argument.
template<class InputIterator, class Alloc> stack(InputIterator first, InputIterator last, const Alloc& alloc);
Effects: Initializes c with first as the first argument, last as the second argument, and alloc as the third argument.
template<container-compatible-range<T> R, class Alloc> stack(from_range_t, R&& rg, const Alloc& a);
Effects: Initializes c with ranges​::​to<Container>(std​::​forward<R>(rg), a).

23.6.6.5 Modifiers [stack.mod]

template<container-compatible-range<T> R> void push_range(R&& rg);
Effects: Equivalent to c.append_range(std​::​forward<R>(rg)) if that is a valid expression, otherwise ranges​::​copy(rg, back_inserter(c)).

23.6.6.6 Operators [stack.ops]

template<class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c == y.c.
template<class T, class Container> bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c != y.c.
template<class T, class Container> bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c < y.c.
template<class T, class Container> bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c > y.c.
template<class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <= y.c.
template<class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c >= y.c.
template<class T, three_way_comparable Container> compare_three_way_result_t<Container> operator<=>(const stack<T, Container>& x, const stack<T, Container>& y);
Returns: x.c <=> y.c.

23.6.6.7 Specialized algorithms [stack.special]

template<class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));
Constraints: is_swappable_v<Container> is true.
Effects: As if by x.swap(y).

23.6.7 Header <flat_map> synopsis [flat.map.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [flat.map], class template flat_map template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_map; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.map.erasure], erasure for flat_map template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred); // [flat.multimap], class template flat_multimap template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_multimap; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator>; // [flat.multimap.erasure], erasure for flat_multimap template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred); }

23.6.8 Class template flat_map [flat.map]

23.6.8.1 Overview [flat.map.overview]

A flat_map is a container adaptor that provides an associative container interface that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of values of another type T based on the keys.
flat_map supports iterators that meet the Cpp17InputIterator requirements and model the random_access_iterator concept ([iterator.concept.random.access]).
A flat_map meets all of the requirements of a container ([container.reqmts]) and of a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_map meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1: 
A flat_map does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
— end note]
A flat_map also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_map supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a flat_map<Key, T> the key_type is Key and the value_type is pair<Key, T>.
Descriptions are provided here only for operations on flat_map that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_map maintains the following invariants:
  • it contains the same number of keys and values;
  • the keys are sorted with respect to the comparison object; and
  • the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.map.defn] exits via an exception the invariants are restored.
[Note 2: 
This can result in the flat_map being emptied.
— end note]
Any type C that meets the sequence container requirements ([sequence.reqmts]) can be used to instantiate flat_map, as long as C​::​iterator meets the Cpp17RandomAccessIterator requirements and invocations of member functions C​::​size and C​::​max_size do not exit via an exception.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3: 
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_type or T is not the same type as MappedContainer​::​value_type.
The effect of calling a constructor that takes both key_container_type and mapped_container_type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_unique_t argument with a container, containers, or range that is not sorted with respect to key_comp(), or that contains equal elements, is undefined.

23.6.8.2 Definition [flat.map.defn]

namespace std { template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_map { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare { private: key_compare comp; // exposition only value_compare(key_compare c) : comp(c) { } // exposition only public: bool operator()(const_reference x, const_reference y) const { return comp(x.first, y.first); } }; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.map.cons], constructors flat_map() : flat_map(key_compare()) { } explicit flat_map(const key_compare& comp) : c(), compare(comp) { } flat_map(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); template<class InputIterator> flat_map(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator> flat_map(sorted_unique_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(s, first, last); } template<container-compatible-range<value_type> R> flat_map(from_range_t, R&& rg) : flat_map(from_range, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R> flat_map(from_range_t, R&& rg, const key_compare& comp) : flat_map(comp) { insert_range(std::forward<R>(rg)); } flat_map(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_map(il.begin(), il.end(), comp) { } flat_map(sorted_unique_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_map(s, il.begin(), il.end(), comp) { } // [flat.map.cons.alloc], constructors with allocators template<class Alloc> explicit flat_map(const Alloc& a); template<class Alloc> flat_map(const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(const flat_map&, const Alloc& a); template<class Alloc> flat_map(flat_map&&, const Alloc& a); template<class InputIterator, class Alloc> flat_map(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_map(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_map(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); flat_map& operator=(initializer_list<value_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // [flat.map.capacity], capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.map.access], element access mapped_type& operator[](const key_type& x); mapped_type& operator[](key_type&& x); template<class K> mapped_type& operator[](K&& x); mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const; template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const; // [flat.map.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& x) { return emplace(x); } pair<iterator, bool> insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class P> pair<iterator, bool> insert(P&& x); template<class P> iterator insert(const_iterator position, P&&); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_unique_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } containers extract() &&; void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args); template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_map& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; const key_container_type& keys() const noexcept { return c.keys; } const mapped_container_type& values() const noexcept { return c.values; } // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_map& x, const flat_map& y); friend synth-three-way-result<value_type> operator<=>(const flat_map& x, const flat_map& y); friend void swap(flat_map& x, flat_map& y) noexcept { x.swap(y); } private: containers c; // exposition only key_compare compare; // exposition only struct key-equiv { // exposition only key-equiv(key_compare c) : comp(c) { } bool operator()(const_reference x, const_reference y) const { return !comp(x.first, y.first) && !comp(y.first, x.first); } key_compare comp; }; }; template<class KeyContainer, class MappedContainer, class Compare = less<typename KeyContainer::value_type>> flat_map(KeyContainer, MappedContainer, Compare = Compare()) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(KeyContainer, MappedContainer, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_map(KeyContainer, MappedContainer, Compare, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare = less<typename KeyContainer::value_type>> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare = Compare()) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator) -> flat_map<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_map(InputIterator, InputIterator, Compare = Compare()) -> flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_map(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) -> flat_map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<ranges::input_range R, class Compare = less<range-key-type<R>>, class Allocator = allocator<byte>> flat_map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_map<range-key-type<R>, range-mapped-type<R>, Compare, vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>, vector<range-mapped-type<R>, alloc-rebind<Allocator, range-mapped-type<R>>>>; template<ranges::input_range R, class Allocator> flat_map(from_range_t, R&&, Allocator) -> flat_map<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>, vector<range-mapped-type<R>, alloc-rebind<Allocator, range-mapped-type<R>>>>; template<class Key, class T, class Compare = less<Key>> flat_map(initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_map<Key, T, Compare>; template<class Key, class T, class Compare = less<Key>> flat_map(sorted_unique_t, initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_map<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_map<Key, T, Compare, KeyContainer, MappedContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { }; }
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.

23.6.8.3 Constructors [flat.map.cons]

flat_map(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializes c.keys with std​::​move(key_cont), c.values with std​::​move(mapped_cont), and compare with comp; sorts the range [begin(), end()) with respect to value_comp(); and finally erases the duplicate elements as if by: auto zv = views::zip(c.keys, c.values); auto it = ranges::unique(zv, key-equiv(compare)).begin(); auto dist = distance(zv.begin(), it); c.keys.erase(c.keys.begin() + dist, c.keys.end()); c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in N if the container arguments are already sorted with respect to value_comp() and otherwise , where N is the value of key_cont.size() before this call.
flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializes c.keys with std​::​move(key_cont), c.values with std​::​move(mapped_cont), and compare with comp.
Complexity: Constant.

23.6.8.4 Constructors with allocators [flat.map.cons.alloc]

The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<key_container_type, Alloc> is true and uses_allocator_v<mapped_container_type, Alloc> is true.
template<class Alloc> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_map(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_map(key_cont, mapped_cont) and flat_map(key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_map(key_cont, mapped_cont) and flat_map(key_cont, mapped_cont, comp), respectively.
template<class Alloc> flat_map(sorted_unique_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_map(s, key_cont, mapped_cont) and flat_map(s, key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> explicit flat_map(const Alloc& a); template<class Alloc> flat_map(const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(const flat_map&, const Alloc& a); template<class Alloc> flat_map(flat_map&&, const Alloc& a); template<class InputIterator, class Alloc> flat_map(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_map(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_map(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_map(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_map(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_map(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_map(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).

23.6.8.5 Capacity [flat.map.capacity]

size_type size() const noexcept;
Returns: c.keys.size().
size_type max_size() const noexcept;
Returns: min<size_type>(c.keys.max_size(), c.values.max_size()).

23.6.8.6 Access [flat.map.access]

mapped_type& operator[](const key_type& x);
Effects: Equivalent to: return try_emplace(x).first->second;
mapped_type& operator[](key_type&& x);
Effects: Equivalent to: return try_emplace(std​::​move(x)).first->second;
template<class K> mapped_type& operator[](K&& x);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
Effects: Equivalent to: return try_emplace(std​::​forward<K>(x)).first->second;
mapped_type& at(const key_type& x); const mapped_type& at(const key_type& x) const;
Returns: A reference to the mapped_type corresponding to x in *this.
Throws: An exception object of type out_of_range if no such element is present.
Complexity: Logarithmic.
template<class K> mapped_type& at(const K& x); template<class K> const mapped_type& at(const K& x) const;
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
Preconditions: The expression find(x) is well-formed and has well-defined behavior.
Returns: A reference to the mapped_type corresponding to x in *this.
Throws: An exception object of type out_of_range if no such element is present.
Complexity: Logarithmic.

23.6.8.7 Modifiers [flat.map.modifiers]

template<class... Args> pair<iterator, bool> emplace(Args&&... args);
Constraints: is_constructible_v<pair<key_type, mapped_type>, Args...> is true.
Effects: Initializes an object t of type pair<key_type, mapped_type> with std​::​forward<Args>(args)...; if the map already contains an element whose key is equivalent to t.first, *this is unchanged.
Otherwise, equivalent to: auto key_it = ranges::upper_bound(c.keys, t.first, compare); auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); c.keys.insert(key_it, std::move(t.first)); c.values.insert(value_it, std::move(t.second));
Returns: The bool component of the returned pair is true if and only if the insertion took place, and the iterator component of the pair points to the element with key equivalent to t.first.
template<class P> pair<iterator, bool> insert(P&& x); template<class P> iterator insert(const_iterator position, P&& x);
Constraints: is_constructible_v<pair<key_type, mapped_type>, P> is true.
Effects: The first form is equivalent to return emplace(std​::​forward<P>(x));.
The second form is equivalent to return emplace_hint(position, std​::​forward<P>(x));.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: for (; first != last; ++first) { value_type value = *first; c.keys.insert(c.keys.end(), std::move(value.first)); c.values.insert(c.values.end(), std::move(value.second)); }
Then, sorts the range of newly inserted elements with respect to value_comp(); merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: auto zv = views::zip(c.keys, c.values); auto it = ranges::unique(zv, key-equiv(compare)).begin(); auto dist = distance(zv.begin(), it); c.keys.erase(c.keys.begin() + dist, c.keys.end()); c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: for (; first != last; ++first) { value_type value = *first; c.keys.insert(c.keys.end(), std::move(value.first)); c.values.insert(c.values.end(), std::move(value.second)); }
Then, merges the sorted range of newly added elements and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: auto zv = views::zip(c.keys, c.values); auto it = ranges::unique(zv, key-equiv(compare)).begin(); auto dist = distance(zv.begin(), it); c.keys.erase(c.keys.begin() + dist, c.keys.end()); c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: Linear in N, where N is size() after the operation.
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<container-compatible-range<value_type> R> void insert_range(R&& rg);
Effects: Adds elements to c as if by: for (const auto& e : rg) { c.keys.insert(c.keys.end(), e.first); c.values.insert(c.values.end(), e.second); }
Then, sorts the range of newly inserted elements with respect to value_comp(); merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases the duplicate elements as if by: auto zv = views::zip(c.keys, c.values); auto it = ranges::unique(zv, key-equiv(compare)).begin(); auto dist = distance(zv.begin(), it); c.keys.erase(c.keys.begin() + dist, c.keys.end()); c.values.erase(c.values.begin() + dist, c.values.end());
Complexity: N + , where N is size() before the operation and M is ranges​::​distance(rg).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
Constraints: is_constructible_v<mapped_type, Args...> is true.
Effects: If the map already contains an element whose key is equivalent to k, *this and args... are unchanged.
Otherwise equivalent to: auto key_it = ranges::upper_bound(c.keys, k, compare); auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); c.keys.insert(key_it, std::forward<decltype(k)>(k)); c.values.emplace(value_it, std::forward<Args>(args)...);
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads, and the same as emplace_hint for the last two overloads.
template<class K, class... Args> pair<iterator, bool> try_emplace(K&& k, Args&&... args); template<class K, class... Args> iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
Constraints:
  • The qualified-id Compare​::​is_transparent is valid and denotes a type.
  • is_constructible_v<key_type, K> is true.
  • is_constructible_v<mapped_type, Args...> is true.
  • For the first overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false.
Preconditions: The conversion from k into key_type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element whose key is equivalent to k, *this and args... are unchanged.
Otherwise equivalent to: auto key_it = ranges::upper_bound(c.keys, k, compare); auto value_it = c.values.begin() + distance(c.keys.begin(), key_it); c.keys.emplace(key_it, std::forward<K>(k)); c.values.emplace(value_it, std::forward<Args>(args)...);
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
Constraints: is_assignable_v<mapped_type&, M> is true and is_constructible_v<mapped_type, M> is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise, equivalent to try_emplace(std::forward<decltype(k)>(k), std::forward<M>(obj)) for the first two overloads or try_emplace(hint, std::forward<decltype(k)>(k), std::forward<M>(obj)) for the last two overloads.
Returns: In the first two overloads, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace for the first two overloads and the same as emplace_hint for the last two overloads.
template<class K, class M> pair<iterator, bool> insert_or_assign(K&& k, M&& obj); template<class K, class M> iterator insert_or_assign(const_iterator hint, K&& k, M&& obj);
Constraints:
  • The qualified-id Compare​::​is_transparent is valid and denotes a type.
  • is_constructible_v<key_type, K> is true.
  • is_assignable_v<mapped_type&, M> is true.
  • is_constructible_v<mapped_type, M> is true.
Preconditions: The conversion from k into key_type constructs an object u, for which find(k) == find(u) is true.
Effects: If the map already contains an element e whose key is equivalent to k, assigns std​::​forward<M>(obj) to e.second.
Otherwise, equivalent to try_emplace(std::forward<K>(k), std::forward<M>(obj)) for the first overload or try_emplace(hint, std::forward<K>(k), std::forward<M>(obj)) for the second overload.
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the map element whose key is equivalent to k.
Complexity: The same as emplace and emplace_hint, respectively.
void swap(flat_map& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c.keys, y.c.keys); ranges::swap(c.values, y.c.values);
containers extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont);
Preconditions: key_cont.size() == mapped_cont.size() is true, the elements of key_cont are sorted with respect to compare, and key_cont contains no equal elements.
Effects: Equivalent to: c.keys = std::move(key_cont); c.values = std::move(mapped_cont);

23.6.8.8 Erasure [flat.map.erasure]

template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1: 
c still meets its invariants, but can be empty.
— end note]

23.6.9 Class template flat_multimap [flat.multimap]

23.6.9.1 Overview [flat.multimap.overview]

A flat_multimap is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type T based on the keys.
flat_multimap supports iterators that meet the Cpp17InputIterator requirements and model the random_access_iterator concept ([iterator.concept.random.access]).
A flat_multimap meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_multimap meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the map is linear, including the ones that take an insertion position iterator.
[Note 1: 
A flat_multimap does not meet the additional requirements of an allocator-aware container ([container.alloc.reqmts]).
— end note]
A flat_multimap also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_multimap supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a flat_multimap<Key, T> the key_type is Key and the value_type is pair<Key, T>.
Except as otherwise noted, operations on flat_multimap are equivalent to those of flat_map, except that flat_multimap operations do not remove or replace elements with equal keys.
[Example 1: 
flat_multimap constructors and emplace do not erase non-unique elements after sorting them.
— end example]
A flat_multimap maintains the following invariants:
  • it contains the same number of keys and values;
  • the keys are sorted with respect to the comparison object; and
  • the value at offset off within the value container is the value associated with the key at offset off within the key container.
If any member function in [flat.multimap.defn] exits via an exception, the invariants are restored.
[Note 2: 
This can result in the flat_multimap being emptied.
— end note]
Any type C that meets the sequence container requirements ([sequence.reqmts]) can be used to instantiate flat_multimap, as long as C​::​iterator meets the Cpp17RandomAccessIterator requirements and invocations of member functions C​::​size and C​::​max_size do not exit via an exception.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3: 
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_type or T is not the same type as MappedContainer​::​value_type.
The effect of calling a constructor that takes both key_container_type and mapped_container_type arguments with containers of different sizes is undefined.
The effect of calling a constructor or member function that takes a sorted_equivalent_t argument with a container, containers, or range that are not sorted with respect to key_comp() is undefined.

23.6.9.2 Definition [flat.multimap.defn]

namespace std { template<class Key, class T, class Compare = less<Key>, class KeyContainer = vector<Key>, class MappedContainer = vector<T>> class flat_multimap { public: // types using key_type = Key; using mapped_type = T; using value_type = pair<key_type, mapped_type>; using key_compare = Compare; using reference = pair<const key_type&, mapped_type&>; using const_reference = pair<const key_type&, const mapped_type&>; using size_type = size_t; using difference_type = ptrdiff_t; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; class value_compare { private: key_compare comp; // exposition only value_compare(key_compare c) : comp(c) { } // exposition only public: bool operator()(const_reference x, const_reference y) const { return comp(x.first, y.first); } }; struct containers { key_container_type keys; mapped_container_type values; }; // [flat.multimap.cons], constructors flat_multimap() : flat_multimap(key_compare()) { } explicit flat_multimap(const key_compare& comp) : c(), compare(comp) { } flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare()); template<class InputIterator> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator> flat_multimap(sorted_equivalent_t s, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(s, first, last); } template<container-compatible-range<value_type> R> flat_multimap(from_range_t, R&& rg) : flat_multimap(from_range, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R> flat_multimap(from_range_t, R&& rg, const key_compare& comp) : flat_multimap(comp) { insert_range(std::forward<R>(rg)); } flat_multimap(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multimap(il.begin(), il.end(), comp) { } flat_multimap(sorted_equivalent_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multimap(s, il.begin(), il.end(), comp) { } // [flat.multimap.cons.alloc], constructors with allocators template<class Alloc> explicit flat_multimap(const Alloc& a); template<class Alloc> flat_multimap(const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(const flat_multimap&, const Alloc& a); template<class Alloc> flat_multimap(flat_multimap&&, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multimap(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); flat_multimap& operator=(initializer_list<value_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x) { return emplace(x); } iterator insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class P> iterator insert(P&& x); template<class P> iterator insert(const_iterator position, P&&); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_equivalent_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } containers extract() &&; void replace(key_container_type&& key_cont, mapped_container_type&& mapped_cont); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_multimap&) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; const key_container_type& keys() const noexcept { return c.keys; } const mapped_container_type& values() const noexcept { return c.values; } // map operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_multimap& x, const flat_multimap& y); friend synth-three-way-result<value_type> operator<=>(const flat_multimap& x, const flat_multimap& y); friend void swap(flat_multimap& x, flat_multimap& y) noexcept { x.swap(y); } private: containers c; // exposition only key_compare compare; // exposition only }; template<class KeyContainer, class MappedContainer, class Compare = less<typename KeyContainer::value_type>> flat_multimap(KeyContainer, MappedContainer, Compare = Compare()) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(KeyContainer, MappedContainer, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_multimap(KeyContainer, MappedContainer, Compare, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare = less<typename KeyContainer::value_type>> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare = Compare()) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Allocator> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer, MappedContainer>; template<class KeyContainer, class MappedContainer, class Compare, class Allocator> flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator) -> flat_multimap<typename KeyContainer::value_type, typename MappedContainer::value_type, Compare, KeyContainer, MappedContainer>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_multimap(InputIterator, InputIterator, Compare = Compare()) -> flat_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-key-type<InputIterator>>> flat_multimap(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) -> flat_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Compare>; template<ranges::input_range R, class Compare = less<range-key-type<R>>, class Allocator = allocator<byte>> flat_multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_multimap<range-key-type<R>, range-mapped-type<R>, Compare, vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>, vector<range-mapped-type<R>, alloc-rebind<Allocator, range-mapped-type<R>>>>; template<ranges::input_range R, class Allocator> flat_multimap(from_range_t, R&&, Allocator) -> flat_multimap<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, vector<range-key-type<R>, alloc-rebind<Allocator, range-key-type<R>>>, vector<range-mapped-type<R>, alloc-rebind<Allocator, range-mapped-type<R>>>>; template<class Key, class T, class Compare = less<Key>> flat_multimap(initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare = less<Key>> flat_multimap(sorted_equivalent_t, initializer_list<pair<Key, T>>, Compare = Compare()) -> flat_multimap<Key, T, Compare>; template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Allocator> struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator> && uses_allocator_v<MappedContainer, Allocator>> { }; }
The member type containers has the data members and special members specified above.
It has no base classes or members other than those specified.

23.6.9.3 Constructors [flat.multimap.cons]

flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializes c.keys with std​::​move(key_cont), c.values with std​::​move(mapped_cont), and compare with comp; sorts the range [begin(), end()) with respect to value_comp().
Complexity: Linear in N if the container arguments are already sorted with respect to value_comp() and otherwise , where N is the value of key_cont.size() before this call.
flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont, const key_compare& comp = key_compare());
Effects: Initializes c.keys with std​::​move(key_cont), c.values with std​::​move(mapped_cont), and compare with comp.
Complexity: Constant.

23.6.9.4 Constructors with allocators [flat.multimap.cons.alloc]

The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<key_container_type, Alloc> is true and uses_allocator_v<mapped_container_type, Alloc> is true.
template<class Alloc> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_multimap(const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multimap(key_cont, mapped_cont) and flat_multimap(key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_multimap(key_cont, mapped_cont) and flat_multimap(key_cont, mapped_cont, comp), respectively.
template<class Alloc> flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t s, const key_container_type& key_cont, const mapped_container_type& mapped_cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multimap(s, key_cont, mapped_cont) and flat_multimap(s, key_cont, mapped_cont, comp), respectively, except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> explicit flat_multimap(const Alloc& a); template<class Alloc> flat_multimap(const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(const flat_multimap&, const Alloc& a); template<class Alloc> flat_multimap(flat_multimap&&, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multimap(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multimap(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multimap(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multimap(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multimap(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c.keys and c.values are constructed with uses-allocator construction ([allocator.uses.construction]).

23.6.9.5 Erasure [flat.multimap.erasure]

template<class Key, class T, class Compare, class KeyContainer, class MappedContainer, class Predicate> typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
Preconditions: Key and T meet the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(pair<const Key&, const T&>(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1: 
c still meets its invariants, but can be empty.
— end note]

23.6.10 Header <flat_set> synopsis [flat.set.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [flat.set], class template flat_set template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_set; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique{}; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator>; // [flat.set.erasure], erasure for flat_set template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred); // [flat.multiset], class template flat_multiset template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_multiset; struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; }; inline constexpr sorted_equivalent_t sorted_equivalent{}; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>; // [flat.multiset.erasure], erasure for flat_multiset template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred); }

23.6.11 Class template flat_set [flat.set]

23.6.11.1 Overview [flat.set.overview]

A flat_set is a container adaptor that provides an associative container interface that supports unique keys (i.e., contains at most one of each key value) and provides for fast retrieval of the keys themselves.
flat_set supports iterators that model the random_access_iterator concept ([iterator.concept.random.access]).
A flat_set meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_set meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node.overview]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1: 
A flat_set does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
— end note]
A flat_set also provides most operations described in [associative.reqmts] for unique keys.
This means that a flat_set supports the a_uniq operations in [associative.reqmts] but not the a_eq operations.
For a flat_set<Key>, both the key_type and value_type are Key.
Descriptions are provided here only for operations on flat_set that are not described in one of those sets of requirements or for operations where there is additional semantic information.
A flat_set maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.set.defn] exits via an exception, the invariant is restored.
[Note 2: 
This can result in the flat_set's being emptied.
— end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_set.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3: 
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_type.
The effect of calling a constructor or member function that takes a sorted_unique_t argument with a range that is not sorted with respect to key_comp(), or that contains equal elements, is undefined.

23.6.11.2 Definition [flat.set.defn]

namespace std { template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_set { public: // types using key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.set.cons], constructors flat_set() : flat_set(key_compare()) { } explicit flat_set(const key_compare& comp) : c(), compare(comp) { } explicit flat_set(container_type cont, const key_compare& comp = key_compare()); flat_set(sorted_unique_t, container_type cont, const key_compare& comp = key_compare()) : c(std::move(cont)), compare(comp) { } template<class InputIterator> flat_set(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(first, last), compare(comp) { } template<container-compatible-range<value_type> R> flat_set(from_range_t, R&& rg) : flat_set(from_range, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R> flat_set(from_range_t, R&& rg, const key_compare& comp) : flat_set(comp) { insert_range(std::forward<R>(rg)); } flat_set(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_set(il.begin(), il.end(), comp) { } flat_set(sorted_unique_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_set(s, il.begin(), il.end(), comp) { } // [flat.set.cons.alloc], constructors with allocators template<class Alloc> explicit flat_set(const Alloc& a); template<class Alloc> flat_set(const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(const container_type& cont, const Alloc& a); template<class Alloc> flat_set(const container_type& cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, const container_type& cont, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, const container_type& cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(const flat_set&, const Alloc& a); template<class Alloc> flat_set(flat_set&&, const Alloc& a); template<class InputIterator, class Alloc> flat_set(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_set(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_set(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); flat_set& operator=(initializer_list<value_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.set.modifiers], modifiers template<class... Args> pair<iterator, bool> emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); pair<iterator, bool> insert(const value_type& x) { return emplace(x); } pair<iterator, bool> insert(value_type&& x) { return emplace(std::move(x)); } template<class K> pair<iterator, bool> insert(K&& x); iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class K> iterator insert(const_iterator hint, K&& x); template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_unique_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } container_type extract() &&; void replace(container_type&&); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_set& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_set& x, const flat_set& y); friend synth-three-way-result<value_type> operator<=>(const flat_set& x, const flat_set& y); friend void swap(flat_set& x, flat_set& y) noexcept { x.swap(y); } private: container_type c; // exposition only key_compare compare; // exposition only }; template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>> flat_set(KeyContainer, Compare = Compare()) -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_set(KeyContainer, Allocator) -> flat_set<typename KeyContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_set(KeyContainer, Compare, Allocator) -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>> flat_set(sorted_unique_t, KeyContainer, Compare = Compare()) -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_set(sorted_unique_t, KeyContainer, Allocator) -> flat_set<typename KeyContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_set(sorted_unique_t, KeyContainer, Compare, Allocator) -> flat_set<typename KeyContainer::value_type, Compare, KeyContainer>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_set(InputIterator, InputIterator, Compare = Compare()) -> flat_set<iter-value-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_set(sorted_unique_t, InputIterator, InputIterator, Compare = Compare()) -> flat_set<iter-value-type<InputIterator>, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> flat_set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_set<ranges::range_value_t<R>, Compare, vector<ranges::range_value_t<R>, alloc-rebind<Allocator, ranges::range_value_t<R>>>>; template<ranges::input_range R, class Allocator> flat_set(from_range_t, R&&, Allocator) -> flat_set<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, vector<ranges::range_value_t<R>, alloc-rebind<Allocator, ranges::range_value_t<R>>>>; template<class Key, class Compare = less<Key>> flat_set(initializer_list<Key>, Compare = Compare()) -> flat_set<Key, Compare>; template<class Key, class Compare = less<Key>> flat_set(sorted_unique_t, initializer_list<Key>, Compare = Compare()) -> flat_set<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_set<Key, Compare, KeyContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator>> { }; }

23.6.11.3 Constructors [flat.set.cons]

explicit flat_set(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes c with std​::​move(cont) and compare with comp, sorts the range [begin(), end()) with respect to compare, and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: Linear in N if cont is already sorted with respect to compare and otherwise , where N is the value of cont.size() before this call.

23.6.11.4 Constructors with allocators [flat.set.cons.alloc]

The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<container_type, Alloc> is true.
template<class Alloc> flat_set(const container_type& cont, const Alloc& a); template<class Alloc> flat_set(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_set(cont) and flat_set(cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_set(cont) and flat_set(cont, comp), respectively.
template<class Alloc> flat_set(sorted_unique_t s, const container_type& cont, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t s, const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_set(s, cont) and flat_set(s, cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> explicit flat_set(const Alloc& a); template<class Alloc> flat_set(const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(const flat_set&, const Alloc& a); template<class Alloc> flat_set(flat_set&&, const Alloc& a); template<class InputIterator, class Alloc> flat_set(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_set(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_set(sorted_unique_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_set(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_set(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_set(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_set(sorted_unique_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).

23.6.11.5 Modifiers [flat.set.modifiers]

template<class K> pair<iterator, bool> insert(K&& x); template<class K> iterator insert(const_iterator hint, K&& x);
Constraints: The qualified-id Compare​::​is_transparent is valid and denotes a type.
is_constructible_v<value_type, K> is true.
Preconditions: The conversion from x into value_type constructs an object u, for which find(x) == find(u) is true.
Effects: If the set already contains an element equivalent to x, *this and x are unchanged.
Otherwise, inserts a new element as if by emplace(std​::​forward<K>(x)).
Returns: In the first overload, the bool component of the returned pair is true if and only if the insertion took place.
The returned iterator points to the element whose key is equivalent to x.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_unique_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
template<container-compatible-range<value_type> R> void insert_range(R&& rg);
Effects: Adds elements to c as if by: for (const auto& e : rg) { c.insert(c.end(), e); }
Then, sorts the range of newly inserted elements with respect to compare; merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range; and finally erases all but the first element from each group of consecutive equivalent elements.
Complexity: N + , where N is size() before the operation and M is ranges​::​distance(rg).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
void swap(flat_set& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c, y.c);
container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare, and cont contains no equal elements.
Effects: Equivalent to: c = std​::​move(cont);

23.6.11.6 Erasure [flat.set.erasure]

template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_set<Key, Compare, KeyContainer>::size_type erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: Key meets the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(as_const(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1: 
c still meets its invariants, but can be empty.
— end note]

23.6.12 Class template flat_multiset [flat.multiset]

23.6.12.1 Overview [flat.multiset.overview]

A flat_multiset is a container adaptor that provides an associative container interface that supports equivalent keys (i.e., possibly containing multiple copies of the same key value) and provides for fast retrieval of the keys themselves.
flat_multiset supports iterators that model the random_access_iterator concept ([iterator.concept.random.access]).
A flat_multiset meets all of the requirements for a container ([container.reqmts]) and for a reversible container ([container.rev.reqmts]), plus the optional container requirements ([container.opt.reqmts]).
flat_multiset meets the requirements of an associative container ([associative.reqmts]), except that:
  • it does not meet the requirements related to node handles ([container.node.overview]),
  • it does not meet the requirements related to iterator invalidation, and
  • the time complexity of the operations that insert or erase a single element from the set is linear, including the ones that take an insertion position iterator.
[Note 1: 
A flat_multiset does not meet the additional requirements of an allocator-aware container, as described in [container.alloc.reqmts].
— end note]
A flat_multiset also provides most operations described in [associative.reqmts] for equal keys.
This means that a flat_multiset supports the a_eq operations in [associative.reqmts] but not the a_uniq operations.
For a flat_multiset<Key>, both the key_type and value_type are Key.
Descriptions are provided here only for operations on flat_multiset that are not described in one of the general sections or for operations where there is additional semantic information.
A flat_multiset maintains the invariant that the keys are sorted with respect to the comparison object.
If any member function in [flat.multiset.defn] exits via an exception, the invariant is restored.
[Note 2: 
This can result in the flat_multiset's being emptied.
— end note]
Any sequence container ([sequence.reqmts]) supporting Cpp17RandomAccessIterator can be used to instantiate flat_multiset.
In particular, vector ([vector]) and deque ([deque]) can be used.
[Note 3: 
vector<bool> is not a sequence container.
— end note]
The program is ill-formed if Key is not the same type as KeyContainer​::​value_type.
The effect of calling a constructor or member function that takes a sorted_equivalent_t argument with a range that is not sorted with respect to key_comp() is undefined.

23.6.12.2 Definition [flat.multiset.defn]

namespace std { template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>> class flat_multiset { public: // types using key_type = Key; using value_type = Key; using key_compare = Compare; using value_compare = Compare; using reference = value_type&; using const_reference = const value_type&; using size_type = typename KeyContainer::size_type; using difference_type = typename KeyContainer::difference_type; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; using container_type = KeyContainer; // [flat.multiset.cons], constructors flat_multiset() : flat_multiset(key_compare()) { } explicit flat_multiset(const key_compare& comp) : c(), compare(comp) { } explicit flat_multiset(container_type cont, const key_compare& comp = key_compare()); flat_multiset(sorted_equivalent_t, container_type cont, const key_compare& comp = key_compare()) : c(std::move(cont)), compare(comp) { } template<class InputIterator> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(), compare(comp) { insert(first, last); } template<class InputIterator> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp = key_compare()) : c(first, last), compare(comp) { } template<container-compatible-range<value_type> R> flat_multiset(from_range_t, R&& rg) : flat_multiset(from_range, std::forward<R>(rg), key_compare()) { } template<container-compatible-range<value_type> R> flat_multiset(from_range_t, R&& rg, const key_compare& comp) : flat_multiset(comp) { insert_range(std::forward<R>(rg)); } flat_multiset(initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multiset(il.begin(), il.end(), comp) { } flat_multiset(sorted_equivalent_t s, initializer_list<value_type> il, const key_compare& comp = key_compare()) : flat_multiset(s, il.begin(), il.end(), comp) { } // [flat.multiset.cons.alloc], constructors with allocators template<class Alloc> explicit flat_multiset(const Alloc& a); template<class Alloc> flat_multiset(const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(const container_type& cont, const Alloc& a); template<class Alloc> flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, const container_type& cont, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, const container_type& cont, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(const flat_multiset&, const Alloc& a); template<class Alloc> flat_multiset(flat_multiset&&, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multiset(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a); flat_multiset& operator=(initializer_list<value_type>); // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // [flat.multiset.modifiers], modifiers template<class... Args> iterator emplace(Args&&... args); template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args); iterator insert(const value_type& x) { return emplace(x); } iterator insert(value_type&& x) { return emplace(std::move(x)); } iterator insert(const_iterator position, const value_type& x) { return emplace_hint(position, x); } iterator insert(const_iterator position, value_type&& x) { return emplace_hint(position, std::move(x)); } template<class InputIterator> void insert(InputIterator first, InputIterator last); template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last); template<container-compatible-range<value_type> R> void insert_range(R&& rg); void insert(initializer_list<value_type> il) { insert(il.begin(), il.end()); } void insert(sorted_equivalent_t s, initializer_list<value_type> il) { insert(s, il.begin(), il.end()); } container_type extract() &&; void replace(container_type&&); iterator erase(iterator position); iterator erase(const_iterator position); size_type erase(const key_type& x); template<class K> size_type erase(K&& x); iterator erase(const_iterator first, const_iterator last); void swap(flat_multiset& y) noexcept; void clear() noexcept; // observers key_compare key_comp() const; value_compare value_comp() const; // set operations iterator find(const key_type& x); const_iterator find(const key_type& x) const; template<class K> iterator find(const K& x); template<class K> const_iterator find(const K& x) const; size_type count(const key_type& x) const; template<class K> size_type count(const K& x) const; bool contains(const key_type& x) const; template<class K> bool contains(const K& x) const; iterator lower_bound(const key_type& x); const_iterator lower_bound(const key_type& x) const; template<class K> iterator lower_bound(const K& x); template<class K> const_iterator lower_bound(const K& x) const; iterator upper_bound(const key_type& x); const_iterator upper_bound(const key_type& x) const; template<class K> iterator upper_bound(const K& x); template<class K> const_iterator upper_bound(const K& x) const; pair<iterator, iterator> equal_range(const key_type& x); pair<const_iterator, const_iterator> equal_range(const key_type& x) const; template<class K> pair<iterator, iterator> equal_range(const K& x); template<class K> pair<const_iterator, const_iterator> equal_range(const K& x) const; friend bool operator==(const flat_multiset& x, const flat_multiset& y); friend synth-three-way-result<value_type> operator<=>(const flat_multiset& x, const flat_multiset& y); friend void swap(flat_multiset& x, flat_multiset& y) noexcept { x.swap(y); } private: container_type c; // exposition only key_compare compare; // exposition only }; template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>> flat_multiset(KeyContainer, Compare = Compare()) -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_multiset(KeyContainer, Allocator) -> flat_multiset<typename KeyContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_multiset(KeyContainer, Compare, Allocator) -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Compare = less<typename KeyContainer::value_type>> flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare()) -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class KeyContainer, class Allocator> flat_multiset(sorted_equivalent_t, KeyContainer, Allocator) -> flat_multiset<typename KeyContainer::value_type, less<typename KeyContainer::value_type>, KeyContainer>; template<class KeyContainer, class Compare, class Allocator> flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator) -> flat_multiset<typename KeyContainer::value_type, Compare, KeyContainer>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_multiset(InputIterator, InputIterator, Compare = Compare()) -> flat_multiset<iter-value-type<InputIterator>, Compare>; template<class InputIterator, class Compare = less<iter-value-type<InputIterator>>> flat_multiset(sorted_equivalent_t, InputIterator, InputIterator, Compare = Compare()) -> flat_multiset<iter-value-type<InputIterator>, Compare>; template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, class Allocator = allocator<ranges::range_value_t<R>>> flat_multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) -> flat_multiset<ranges::range_value_t<R>, Compare, vector<ranges::range_value_t<R>, alloc-rebind<Allocator, ranges::range_value_t<R>>>>; template<ranges::input_range R, class Allocator> flat_multiset(from_range_t, R&&, Allocator) -> flat_multiset<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, vector<ranges::range_value_t<R>, alloc-rebind<Allocator, ranges::range_value_t<R>>>>; template<class Key, class Compare = less<Key>> flat_multiset(initializer_list<Key>, Compare = Compare()) -> flat_multiset<Key, Compare>; template<class Key, class Compare = less<Key>> flat_multiset(sorted_equivalent_t, initializer_list<Key>, Compare = Compare()) -> flat_multiset<Key, Compare>; template<class Key, class Compare, class KeyContainer, class Allocator> struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator> : bool_constant<uses_allocator_v<KeyContainer, Allocator>> { }; }

23.6.12.3 Constructors [flat.multiset.cons]

explicit flat_multiset(container_type cont, const key_compare& comp = key_compare());
Effects: Initializes c with std​::​move(cont) and compare with comp, and sorts the range [begin(), end()) with respect to compare.
Complexity: Linear in N if cont is already sorted with respect to compare and otherwise , where N is the value of cont.size() before this call.

23.6.12.4 Constructors with allocators [flat.multiset.cons.alloc]

The constructors in this subclause shall not participate in overload resolution unless uses_allocator_v<container_type, Alloc> is true.
template<class Alloc> flat_multiset(const container_type& cont, const Alloc& a); template<class Alloc> flat_multiset(const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multiset(cont) and flat_multiset(cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Same as flat_multiset(cont) and flat_multiset(cont, comp), respectively.
template<class Alloc> flat_multiset(sorted_equivalent_t s, const container_type& cont, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t s, const container_type& cont, const key_compare& comp, const Alloc& a);
Effects: Equivalent to flat_multiset(s, cont) and flat_multiset(s, cont, comp), respectively, except that c is constructed with uses-allocator construction ([allocator.uses.construction]).
Complexity: Linear.
template<class Alloc> explicit flat_multiset(const Alloc& a); template<class Alloc> flat_multiset(const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(const flat_multiset&, const Alloc& a); template<class Alloc> flat_multiset(flat_multiset&&, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const Alloc& a); template<class InputIterator, class Alloc> flat_multiset(sorted_equivalent_t, InputIterator first, InputIterator last, const key_compare& comp, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multiset(from_range_t, R&& rg, const Alloc& a); template<container-compatible-range<value_type> R, class Alloc> flat_multiset(from_range_t, R&& rg, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multiset(initializer_list<value_type> il, const key_compare& comp, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const Alloc& a); template<class Alloc> flat_multiset(sorted_equivalent_t, initializer_list<value_type> il, const key_compare& comp, const Alloc& a);
Effects: Equivalent to the corresponding non-allocator constructors except that c is constructed with uses-allocator construction ([allocator.uses.construction]).

23.6.12.5 Modifiers [flat.multiset.modifiers]

template<class... Args> iterator emplace(Args&&... args);
Constraints: is_constructible_v<value_type, Args...> is true.
Effects: First, initializes an object t of type value_type with std​::​forward<Args>(args)..., then inserts t as if by: auto it = ranges::upper_bound(c, t, compare); c.insert(it, std::move(t));
Returns: An iterator that points to the inserted element.
template<class InputIterator> void insert(InputIterator first, InputIterator last);
Effects: Adds elements to c as if by: c.insert(c.end(), first, last);
Then, sorts the range of newly inserted elements with respect to compare, and merges the resulting sorted range and the sorted range of pre-existing elements into a single sorted range.
Complexity: N + , where N is size() before the operation and M is distance(first, last).
Remarks: Since this operation performs an in-place merge, it may allocate memory.
template<class InputIterator> void insert(sorted_equivalent_t, InputIterator first, InputIterator last);
Effects: Equivalent to insert(first, last).
Complexity: Linear.
void swap(flat_multiset& y) noexcept;
Effects: Equivalent to: ranges::swap(compare, y.compare); ranges::swap(c, y.c);
container_type extract() &&;
Postconditions: *this is emptied, even if the function exits via an exception.
Returns: std​::​move(c).
void replace(container_type&& cont);
Preconditions: The elements of cont are sorted with respect to compare.
Effects: Equivalent to: c = std​::​move(cont);

23.6.12.6 Erasure [flat.multiset.erasure]

template<class Key, class Compare, class KeyContainer, class Predicate> typename flat_multiset<Key, Compare, KeyContainer>::size_type erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
Preconditions: Key meets the Cpp17MoveAssignable requirements.
Effects: Let E be bool(pred(as_const(e))).
Erases all elements e in c for which E holds.
Returns: The number of elements erased.
Complexity: Exactly c.size() applications of the predicate.
Remarks: Stable ([algorithm.stable]).
If an invocation of erase_if exits via an exception, c is in a valid but unspecified state ([defns.valid]).
[Note 1: 
c still meets its invariants, but can be empty.
— end note]

23.6.13 Container adaptors formatting [container.adaptors.format]

For each of queue, priority_queue, and stack, the library provides the following formatter specialization where adaptor-type is the name of the template: namespace std { template<class charT, class T, formattable<charT> Container, class... U> struct formatter<adaptor-type<T, Container, U...>, charT> { private: using maybe-const-container = // exposition only fmt-maybe-const<Container, charT>; using maybe-const-adaptor = // exposition only maybe-const<is_const_v<maybe-const-container>, // see [ranges.syn] adaptor-type<T, Container, U...>>; formatter<ranges::ref_view<maybe-const-container>, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const; }; }
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-adaptor& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r.c, ctx);

23.7 Views [views]

23.7.1 General [views.general]

The header <span> defines the view span.
The header <mdspan> defines the class template mdspan and other facilities for interacting with these multidimensional views.

23.7.2 Contiguous access [views.contiguous]

23.7.2.1 Header <span> synopsis [span.syn]

#include <initializer_list> // see [initializer.list.syn] // mostly freestanding namespace std { // constants inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); template<class T> concept integral-constant-like = // exposition only is_integral_v<decltype(T::value)> && !is_same_v<bool, remove_const_t<decltype(T::value)>> && convertible_to<T, decltype(T::value)> && equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value; template<class T> constexpr size_t maybe-static-ext = dynamic_extent; // exposition only template<integral-constant-like T> constexpr size_t maybe-static-ext<T> = {T::value}; // [views.span], class template span template<class ElementType, size_t Extent = dynamic_extent> class span; // partially freestanding template<class ElementType, size_t Extent> constexpr bool ranges::enable_view<span<ElementType, Extent>> = true; template<class ElementType, size_t Extent> constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true; // [span.objectrep], views of object representation template<class ElementType, size_t Extent> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept; template<class ElementType, size_t Extent> span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept; }

23.7.2.2 Class template span [views.span]

23.7.2.2.1 Overview [span.overview]

A span is a view over a contiguous sequence of objects, the storage of which is owned by some other object.
All member functions of span have constant time complexity.
namespace std { template<class ElementType, size_t Extent = dynamic_extent> class span { public: // constants and types using element_type = ElementType; using value_type = remove_cv_t<ElementType>; using size_type = size_t; using difference_type = ptrdiff_t; using pointer = element_type*; using const_pointer = const element_type*; using reference = element_type&; using const_reference = const element_type&; using iterator = implementation-defined; // see [span.iterators] using const_iterator = std::const_iterator<iterator>; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::const_iterator<reverse_iterator>; static constexpr size_type extent = Extent; // [span.cons], constructors, copy, and assignment constexpr span() noexcept; template<class It> constexpr explicit(extent != dynamic_extent) span(It first, size_type count); template<class It, class End> constexpr explicit(extent != dynamic_extent) span(It first, End last); template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept; template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept; template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept; template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r); constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); constexpr span(const span& other) noexcept = default; template<class OtherElementType, size_t OtherExtent> constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept; constexpr span& operator=(const span& other) noexcept = default; // [span.sub], subviews template<size_t Count> constexpr span<element_type, Count> first() const; template<size_t Count> constexpr span<element_type, Count> last() const; template<size_t Offset, size_t Count = dynamic_extent> constexpr span<element_type, see below> subspan() const; constexpr span<element_type, dynamic_extent> first(size_type count) const; constexpr span<element_type, dynamic_extent> last(size_type count) const; constexpr span<element_type, dynamic_extent> subspan( size_type offset, size_type count = dynamic_extent) const; // [span.obs], observers constexpr size_type size() const noexcept; constexpr size_type size_bytes() const noexcept; constexpr bool empty() const noexcept; // [span.elem], element access constexpr reference operator[](size_type idx) const; constexpr reference at(size_type idx) const; // freestanding-deleted constexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; // [span.iterators], iterator support constexpr iterator begin() const noexcept; constexpr iterator end() const noexcept; constexpr const_iterator cbegin() const noexcept { return begin(); } constexpr const_iterator cend() const noexcept { return end(); } constexpr reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } constexpr const_reverse_iterator crend() const noexcept { return rend(); } private: pointer data_; // exposition only size_type size_; // exposition only }; template<class It, class EndOrSize> span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>; template<class T, size_t N> span(T (&)[N]) -> span<T, N>; template<class T, size_t N> span(array<T, N>&) -> span<T, N>; template<class T, size_t N> span(const array<T, N>&) -> span<const T, N>; template<class R> span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>; }
span<ElementType, Extent> is a trivially copyable type ([basic.types.general]).
ElementType is required to be a complete object type that is not an abstract class type.
For a span s, any operation that invalidates a pointer in the range [s.data(), s.data() + s.size()) invalidates pointers, iterators, and references to elements of s.

23.7.2.2.2 Constructors, copy, and assignment [span.cons]

constexpr span() noexcept;
Constraints: Extent == dynamic_extent || Extent == 0 is true.
Postconditions: size() == 0 && data() == nullptr.
template<class It> constexpr explicit(extent != dynamic_extent) span(It first, size_type count);
Constraints: Let U be remove_reference_t<iter_reference_t<It>>.
  • is_convertible_v<U(*)[], element_type(*)[]> is true.
    [Note 1: 
    The intent is to allow only qualification conversions of the iterator reference type to element_type.
    — end note]
Preconditions:
Effects: Initializes data_ with to_address(first) and size_ with count.
Throws: Nothing.
template<class It, class End> constexpr explicit(extent != dynamic_extent) span(It first, End last);
Constraints: Let U be remove_reference_t<iter_reference_t<It>>.
Preconditions:
Effects: Initializes data_ with to_address(first) and size_ with last - first.
Throws: When and what last - first throws.
template<size_t N> constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept; template<class T, size_t N> constexpr span(array<T, N>& arr) noexcept; template<class T, size_t N> constexpr span(const array<T, N>& arr) noexcept;
Constraints: Let U be remove_pointer_t<decltype(std​::​data(arr))>.
  • extent == dynamic_extent || N == extent is true, and
  • is_convertible_v<U(*)[], element_type(*)[]> is true.
    [Note 3: 
    The intent is to allow only qualification conversions of the array element type to element_type.
    — end note]
Effects: Constructs a span that is a view over the supplied array.
[Note 4: 
type_identity_t affects class template argument deduction.
— end note]
Postconditions: size() == N && data() == std​::​data(arr) is true.
template<class R> constexpr explicit(extent != dynamic_extent) span(R&& r);
Constraints: Let U be remove_reference_t<ranges​::​range_reference_t<R>>.
  • R satisfies ranges​::​contiguous_range and ranges​::​sized_range.
  • Either R satisfies ranges​::​borrowed_range or is_const_v<element_type> is true.
  • remove_cvref_t<R> is not a specialization of span.
  • remove_cvref_t<R> is not a specialization of array.
  • is_array_v<remove_cvref_t<R>> is false.
  • is_convertible_v<U(*)[], element_type(*)[]> is true.
    [Note 5: 
    The intent is to allow only qualification conversions of the range reference type to element_type.
    — end note]
Preconditions:
Effects: Initializes data_ with ranges​::​data(r) and size_ with ranges​::​size(r).
Throws: What and when ranges​::​data(r) and ranges​::​size(r) throw.
constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il);
Constraints: is_const_v<element_type> is true.
Preconditions: If extent is not equal to dynamic_extent, then il.size() is equal to extent.
Effects: Initializes data_ with il.begin() and size_ with il.size().
constexpr span(const span& other) noexcept = default;
Postconditions: other.size() == size() && other.data() == data().
template<class OtherElementType, size_t OtherExtent> constexpr explicit(see below) span(const span<OtherElementType, OtherExtent>& s) noexcept;
Constraints:
  • extent == dynamic_extent || OtherExtent == dynamic_extent || extent == OtherExtent is true, and
  • is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
    [Note 6: 
    The intent is to allow only qualification conversions of the OtherElementType to element_type.
    — end note]
Preconditions: If extent is not equal to dynamic_extent, then s.size() is equal to extent.
Effects: Constructs a span that is a view over the range [s.data(), s.data() + s.size()).
Postconditions: size() == s.size() && data() == s.data().
Remarks: The expression inside explicit is equivalent to: extent != dynamic_extent && OtherExtent == dynamic_extent
constexpr span& operator=(const span& other) noexcept = default;
Postconditions: size() == other.size() && data() == other.data().

23.7.2.2.3 Deduction guides [span.deduct]

template<class It, class EndOrSize> span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>;
Constraints: It satisfies contiguous_iterator.
template<class R> span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
Constraints: R satisfies ranges​::​contiguous_range.

23.7.2.2.4 Subviews [span.sub]

template<size_t Count> constexpr span<element_type, Count> first() const;
Mandates: Count <= Extent is true.
Preconditions: Count <= size() is true.
Effects: Equivalent to: return R{data(), Count}; where R is the return type.
template<size_t Count> constexpr span<element_type, Count> last() const;
Mandates: Count <= Extent is true.
Preconditions: Count <= size() is true.
Effects: Equivalent to: return R{data() + (size() - Count), Count}; where R is the return type.
template<size_t Offset, size_t Count = dynamic_extent> constexpr span<element_type, see below> subspan() const;
Mandates: Offset <= Extent && (Count == dynamic_extent || Count <= Extent - Offset) is true.
Preconditions: Offset <= size() && (Count == dynamic_extent || Count <= size() - Offset) is true.
Effects: Equivalent to: return span<ElementType, see below>( data() + Offset, Count != dynamic_extent ? Count : size() - Offset);
Remarks: The second template argument of the returned span type is: Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)
constexpr span<element_type, dynamic_extent> first(size_type count) const;
Preconditions: count <= size() is true.
Effects: Equivalent to: return {data(), count};
constexpr span<element_type, dynamic_extent> last(size_type count) const;
Preconditions: count <= size() is true.
Effects: Equivalent to: return {data() + (size() - count), count};
constexpr span<element_type, dynamic_extent> subspan( size_type offset, size_type count = dynamic_extent) const;
Preconditions: offset <= size() && (count == dynamic_extent || count <= size() - offset) is true.
Effects: Equivalent to: return {data() + offset, count == dynamic_extent ? size() - offset : count};

23.7.2.2.5 Observers [span.obs]

constexpr size_type size() const noexcept;
Effects: Equivalent to: return size_;
constexpr size_type size_bytes() const noexcept;
Effects: Equivalent to: return size() * sizeof(element_type);
constexpr bool empty() const noexcept;
Effects: Equivalent to: return size() == 0;

23.7.2.2.6 Element access [span.elem]

constexpr reference operator[](size_type idx) const;
Preconditions: idx < size() is true.
Returns: *(data() + idx).
Throws: Nothing.
constexpr reference at(size_type idx) const;
Returns: *(data() + idx).
Throws: out_of_range if idx >= size() is true.
constexpr reference front() const;
Preconditions: empty() is false.
Returns: *data().
Throws: Nothing.
constexpr reference back() const;
Preconditions: empty() is false.
Returns: *(data() + (size() - 1)).
Throws: Nothing.
constexpr pointer data() const noexcept;
Returns: data_.

23.7.2.2.7 Iterator support [span.iterators]

using iterator = implementation-defined;
The type models contiguous_iterator ([iterator.concept.contiguous]), meets the Cpp17RandomAccessIterator requirements ([random.access.iterators]), and meets the requirements for constexpr iterators ([iterator.requirements.general]), whose value type is value_type and whose reference type is reference.
All requirements on container iterators ([container.reqmts]) apply to span​::​iterator as well.
constexpr iterator begin() const noexcept;
Returns: An iterator referring to the first element in the span.
If empty() is true, then it returns the same value as end().
constexpr iterator end() const noexcept;
Returns: An iterator which is the past-the-end value.
constexpr reverse_iterator rbegin() const noexcept;
Effects: Equivalent to: return reverse_iterator(end());
constexpr reverse_iterator rend() const noexcept;
Effects: Equivalent to: return reverse_iterator(begin());

23.7.2.3 Views of object representation [span.objectrep]

template<class ElementType, size_t Extent> span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_bytes(span<ElementType, Extent> s) noexcept;
Effects: Equivalent to: return R{reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; where R is the return type.
template<class ElementType, size_t Extent> span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent> as_writable_bytes(span<ElementType, Extent> s) noexcept;
Constraints: is_const_v<ElementType> is false.
Effects: Equivalent to: return R{reinterpret_cast<byte*>(s.data()), s.size_bytes()}; where R is the return type.

23.7.3 Multidimensional access [views.multidim]

23.7.3.1 Overview [mdspan.overview]

A multidimensional index space is a Cartesian product of integer intervals.
Each interval can be represented by a half-open range , where and are the lower and upper bounds of the dimension.
The rank of a multidimensional index space is the number of intervals it represents.
The size of a multidimensional index space is the product of for each dimension i if its rank is greater than 0, and 1 otherwise.
An integer r is a rank index of an index space S if r is in the range .
A pack of integers idx is a multidimensional index in a multidimensional index space S (or representation thereof) if both of the following are true:
  • sizeof...(idx) is equal to the rank of S, and
  • for every rank index i of S, the value of idx is an integer in the interval of S.

23.7.3.2 Header <mdspan> synopsis [mdspan.syn]

// all freestanding namespace std { // [mdspan.extents], class template extents template<class IndexType, size_t... Extents> class extents; // [mdspan.extents.dextents], alias template dextents template<class IndexType, size_t Rank> using dextents = see below; // [mdspan.extents.dims], alias template dims template<size_t Rank, class IndexType = size_t> using dims = see below; // [mdspan.layout], layout mapping struct layout_left; struct layout_right; struct layout_stride; template<size_t PaddingValue = dynamic_extent> struct layout_left_padded; template<size_t PaddingValue = dynamic_extent> struct layout_right_padded; // [mdspan.accessor.default], class template default_accessor template<class ElementType> class default_accessor; // [mdspan.accessor.aligned], class template aligned_accessor template<class ElementType, size_t ByteAlignment> class aligned_accessor; // [mdspan.mdspan], class template mdspan template<class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor<ElementType>> class mdspan; // [mdspan.sub], submdspan creation template<class OffsetType, class LengthType, class StrideType> struct strided_slice; template<class LayoutMapping> struct submdspan_mapping_result; struct full_extent_t { explicit full_extent_t() = default; }; inline constexpr full_extent_t full_extent{}; template<class IndexType, class... Extents, class... SliceSpecifiers> constexpr auto submdspan_extents(const extents<IndexType, Extents...>&, SliceSpecifiers...); // [mdspan.sub.sub], submdspan function template template<class ElementType, class Extents, class LayoutPolicy, class AccessorPolicy, class... SliceSpecifiers> constexpr auto submdspan( const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src, SliceSpecifiers... slices) -> see below; template<class T, class IndexType> concept index-pair-like = // exposition only pair-like<T> && convertible_to<tuple_element_t<0, T>, IndexType> && convertible_to<tuple_element_t<1, T>, IndexType>; }

23.7.3.3 Class template extents [mdspan.extents]

23.7.3.3.1 Overview [mdspan.extents.overview]

The class template extents represents a multidimensional index space of rank equal to sizeof...(Extents).
In ([views]), extents is used synonymously with multidimensional index space.
namespace std { template<class IndexType, size_t... Extents> class extents { public: using index_type = IndexType; using size_type = make_unsigned_t<index_type>; using rank_type = size_t; // [mdspan.extents.obs], observers of the multidimensional index space static constexpr rank_type rank() noexcept { return sizeof...(Extents); } static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); } static constexpr size_t static_extent(rank_type) noexcept; constexpr index_type extent(rank_type) const noexcept; // [mdspan.extents.cons], constructors constexpr extents() noexcept = default; template<class OtherIndexType, size_t... OtherExtents> constexpr explicit(see below) extents(const extents<OtherIndexType, OtherExtents...>&) noexcept; template<class... OtherIndexTypes> constexpr explicit extents(OtherIndexTypes...) noexcept; template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(span<OtherIndexType, N>) noexcept; template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(const array<OtherIndexType, N>&) noexcept; // [mdspan.extents.cmp], comparison operators template<class OtherIndexType, size_t... OtherExtents> friend constexpr bool operator==(const extents&, const extents<OtherIndexType, OtherExtents...>&) noexcept; // [mdspan.extents.expo], exposition-only helpers constexpr size_t fwd-prod-of-extents(rank_type) const noexcept; // exposition only constexpr size_t rev-prod-of-extents(rank_type) const noexcept; // exposition only template<class OtherIndexType> static constexpr auto index-cast(OtherIndexType&&) noexcept; // exposition only private: static constexpr rank_type dynamic-index(rank_type) noexcept; // exposition only static constexpr rank_type dynamic-index-inv(rank_type) noexcept; // exposition only array<index_type, rank_dynamic()> dynamic-extents{}; // exposition only }; template<class... Integrals> explicit extents(Integrals...) -> see below; }
Mandates:
  • IndexType is a signed or unsigned integer type, and
  • each element of Extents is either equal to dynamic_extent, or is representable as a value of type IndexType.
Each specialization of extents models regular and is trivially copyable.
Let be the element of Extents.
is a dynamic extent if it is equal to dynamic_extent, otherwise is a static extent.
Let be the value of dynamic-extents[dynamic-index(r)] if is a dynamic extent, otherwise .
The interval of the multidimensional index space represented by an extents object is .

23.7.3.3.2 Exposition-only helpers [mdspan.extents.expo]

static constexpr rank_type dynamic-index(rank_type i) noexcept;
Preconditions: i <= rank() is true.
Returns: The number of with for which is a dynamic extent.
static constexpr rank_type dynamic-index-inv(rank_type i) noexcept;
Preconditions: i < rank_dynamic() is true.
Returns: The minimum value of r such that dynamic-index(r + 1) == i + 1 is true.
constexpr size_t fwd-prod-of-extents(rank_type i) const noexcept;
Preconditions: i <= rank() is true.
Returns: If i > 0 is true, the product of extent(k) for all k in the range [0, i), otherwise 1.
constexpr size_t rev-prod-of-extents(rank_type i) const noexcept;
Preconditions: i < rank() is true.
Returns: If i + 1 < rank() is true, the product of extent(k) for all k in the range [i + 1, rank()), otherwise 1.
template<class OtherIndexType> static constexpr auto index-cast(OtherIndexType&& i) noexcept;
Effects:
  • If OtherIndexType is an integral type other than bool, then equivalent to return i;,
  • otherwise, equivalent to return static_cast<index_type>(i);.
[Note 1: 
This function will always return an integral type other than bool.
Since this function's call sites are constrained on convertibility of OtherIndexType to index_type, integer-class types can use the static_cast branch without loss of precision.
— end note]

23.7.3.3.3 Constructors [mdspan.extents.cons]

template<class OtherIndexType, size_t... OtherExtents> constexpr explicit(see below) extents(const extents<OtherIndexType, OtherExtents...>& other) noexcept;
Constraints:
  • sizeof...(OtherExtents) == rank() is true.
  • ((OtherExtents == dynamic_extent || Extents == dynamic_extent || OtherExtents ==
    Extents) && ...)
    is true.
Preconditions:
  • other.extent(r) equals for each r for which is a static extent, and
  • either
    • sizeof...(OtherExtents) is zero, or
    • other.extent(r) is representable as a value of type index_type for every rank index r of other.
Postconditions: *this == other is true.
Remarks: The expression inside explicit is equivalent to: (((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || (numeric_limits<index_type>::max() < numeric_limits<OtherIndexType>::max())
template<class... OtherIndexTypes> constexpr explicit extents(OtherIndexTypes... exts) noexcept;
Let N be sizeof...(OtherIndexTypes), and let exts_arr be array<index_type, N>{static_cast<
index_type>(std​::​move(exts))...}
.
Constraints:
  • (is_convertible_v<OtherIndexTypes, index_type> && ...) is true,
  • (is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) is true, and
  • N == rank_dynamic() || N == rank() is true.
    [Note 1: 
    One can construct extents from just dynamic extents, which are all the values getting stored, or from all the extents with a precondition.
    — end note]
Preconditions:
  • If N != rank_dynamic() is true, exts_arr[r] equals for each r for which is a static extent, and
  • either
    • sizeof...(exts) == 0 is true, or
    • each element of exts is representable as a nonnegative value of type index_type.
Postconditions: *this == extents(exts_arr) is true.
template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(span<OtherIndexType, N> exts) noexcept; template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) extents(const array<OtherIndexType, N>& exts) noexcept;
Constraints:
  • is_convertible_v<const OtherIndexType&, index_type> is true,
  • is_nothrow_constructible_v<index_type, const OtherIndexType&> is true, and
  • N == rank_dynamic() || N == rank() is true.
Preconditions:
  • If N != rank_dynamic() is true, exts[r] equals for each r for which is a static extent, and
  • either
    • N is zero, or
    • exts[r] is representable as a nonnegative value of type index_type for every rank index r.
Effects:
  • If N equals rank_dynamic(), for all d in the range [0, rank_dynamic()), direct-non-list-initializes dynamic-extents[d] with as_const(exts[d]).
  • Otherwise, for all d in the range [0, rank_dynamic()), direct-non-list-initializes dynamic-extents[d] with as_const(exts[dynamic-index-inv(d)]).
template<class... Integrals> explicit extents(Integrals...) -> see below;
Constraints: (is_convertible_v<Integrals, size_t> && ...) is true.
Remarks: The deduced type is extents<size_t, maybe-static-ext<Integrals>...>.

23.7.3.3.4 Observers of the multidimensional index space [mdspan.extents.obs]

static constexpr size_t static_extent(rank_type i) noexcept;
Preconditions: i < rank() is true.
Returns: .
constexpr index_type extent(rank_type i) const noexcept;
Preconditions: i < rank() is true.
Returns: .

23.7.3.3.5 Comparison operators [mdspan.extents.cmp]

template<class OtherIndexType, size_t... OtherExtents> friend constexpr bool operator==(const extents& lhs, const extents<OtherIndexType, OtherExtents...>& rhs) noexcept;
Returns: true if lhs.rank() equals rhs.rank() and if lhs.extent(r) equals rhs.extent(r) for every rank index r of rhs, otherwise false.

23.7.3.3.6 Alias template dextents [mdspan.extents.dextents]

template<class IndexType, size_t Rank> using dextents = see below;
Result: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, and E​::​index_type denotes IndexType.

23.7.3.3.7 Alias template dims [mdspan.extents.dims]

template<size_t Rank, class IndexType = size_t> using dims = see below;
Result: A type E that is a specialization of extents such that E​::​rank() == Rank && E​::​rank() == E​::​rank_dynamic() is true, and E​::​index_type denotes IndexType.

23.7.3.4 Layout mapping [mdspan.layout]

23.7.3.4.1 General [mdspan.layout.general]

  • M denotes a layout mapping class.
  • m denotes a (possibly const) value of type M.
  • i and j are packs of (possibly const) integers that are multidimensional indices in m.extents() ([mdspan.overview]).
    [Note 1: 
    The type of each element of the packs can be a different integer type.
    — end note]
  • r is a (possibly const) rank index of typename M​::​extents_type.
  • is a pack of (possibly const) integers for which sizeof...() == M​::​extents_type​::​rank() is true, the element is equal to 1, and all other elements are equal to 0.
In [mdspan.layout.reqmts] through [mdspan.layout.stride]:
  • Let is-mapping-of be the exposition-only variable template defined as follows: template<class Layout, class Mapping> constexpr bool is-mapping-of = // exposition only is_same_v<typename Layout::template mapping<typename Mapping::extents_type>, Mapping>;
  • Let is-layout-left-padded-mapping-of be the exposition-only variable template defined as follows: template<class Mapping> constexpr bool is-layout-left-padded-mapping-of = see below; // exposition only where is-layout-left-padded-mapping-of<Mapping> is true if and only if Mapping denotes a specialization of layout_left_padded<S>​::​mapping for some value S of type size_t.
  • Let is-layout-right-padded-mapping-of be the exposition-only variable template defined as follows: template<class Mapping> constexpr bool is-layout-right-padded-mapping-of = see below; // exposition only where is-layout-right-padded-mapping-of<Mapping> is true if and only if Mapping denotes a specialization of layout_right_padded<S>​::​mapping for some value S of type size_t.
  • For nonnegative integers x and y, let denote
    • y if x is zero,
    • otherwise, the least multiple of x that is greater than or equal to y.

23.7.3.4.2 Requirements [mdspan.layout.reqmts]

A type M meets the layout mapping requirements if
  • M models copyable and equality_comparable,
  • is_nothrow_move_constructible_v<M> is true,
  • is_nothrow_move_assignable_v<M> is true,
  • is_nothrow_swappable_v<M> is true, and
  • the following types and expressions are well-formed and have the specified semantics.
typename M::extents_type
Result: A type that is a specialization of extents.
typename M::index_type
Result: typename M​::​extents_type​::​index_type.
typename M::rank_type
Result: typename M​::​extents_type​::​rank_type.
typename M::layout_type
Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of<MP, M> is true.
m.extents()
Result: const typename M​::​extents_type&
m(i...)
Result: typename M​::​index_type
Returns: A nonnegative integer less than numeric_limits<typename M​::​index_type>​::​max() and less than or equal to numeric_limits<size_t>​::​max().
m(i...) == m(static_cast<typename M::index_type>(i)...)
Result: bool
Returns: true
m.required_span_size()
Result: typename M​::​index_type
Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i.
m.is_unique()
Result: bool
Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true.
[Note 1: 
A mapping can return false even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently whether the layout is unique.
— end note]
m.is_exhaustive()
Result: bool
Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k.
[Note 2: 
A mapping can return false even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently whether the layout is exhaustive.
— end note]
m.is_strided()
Result: bool
Returns: true only if for every rank index r of m.extents() there exists an integer such that, for all i where is a multidimensional index in m.extents() ([mdspan.overview]), m((i + )...) - m(i...) equals .
[Note 3: 
This implies that for a strided layout .
— end note]
[Note 4: 
A mapping can return false even if the condition is met.
For certain layouts, it is possibly not feasible to determine efficiently whether the layout is strided.
— end note]
m.stride(r)
Preconditions: m.is_strided() is true.
Result: typename M​::​index_type
Returns: as defined in m.is_strided() above.
M::is_always_unique()
Result: A constant expression ([expr.const]) of type bool.
Returns: true only if m.is_unique() is true for all possible objects m of type M.
[Note 5: 
A mapping can return false even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine whether every instance is unique.
— end note]
M::is_always_exhaustive()
Result: A constant expression ([expr.const]) of type bool.
Returns: true only if m.is_exhaustive() is true for all possible objects m of type M.
[Note 6: 
A mapping can return false even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine whether every instance is exhaustive.
— end note]
M::is_always_strided()
Result: A constant expression ([expr.const]) of type bool.
Returns: true only if m.is_strided() is true for all possible objects m of type M.
[Note 7: 
A mapping can return false even if the above condition is met.
For certain layout mappings, it is possibly not feasible to determine whether every instance is strided.
— end note]

23.7.3.4.3 Layout mapping policy requirements [mdspan.layout.policy.reqmts]

A type MP meets the layout mapping policy requirements if for a type E that is a specialization of extents, MP​::​mapping<E> is valid and denotes a type X that meets the layout mapping requirements ([mdspan.layout.reqmts]), and for which the qualified-id X​::​layout_type is valid and denotes the type MP and the qualified-id X​::​extents_type denotes E.

23.7.3.4.4 Layout mapping policies [mdspan.layout.policy.overview]

namespace std { struct layout_left { template<class Extents> class mapping; }; struct layout_right { template<class Extents> class mapping; }; struct layout_stride { template<class Extents> class mapping; }; template<size_t PaddingValue> struct layout_left_padded { template<class Extents> class mapping; }; template<size_t PaddingValue> struct layout_right_padded { template<class Extents> class mapping; }; }
Each of layout_left, layout_right, and layout_stride, as well as each specialization of layout_left_padded and layout_right_padded, meets the layout mapping policy requirements and is a trivially copyable type.
Furthermore, is_trivially_default_constructible_v<T> is true for any such type T.

23.7.3.4.5 Class template layout_left​::​mapping [mdspan.layout.left]

23.7.3.4.5.1 Overview [mdspan.layout.left.overview]

layout_left provides a layout mapping where the leftmost extent has stride 1, and strides increase left-to-right as the product of extents.
namespace std { template<class Extents> class layout_left::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left; // [mdspan.layout.left.cons], constructors constexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept; template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&) noexcept; template<class LayoutLeftPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept; template<class OtherExtents> constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&); constexpr mapping& operator=(const mapping&) noexcept = default; // [mdspan.layout.left.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const noexcept; template<class... Indices> constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept { return true; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } static constexpr bool is_exhaustive() noexcept { return true; } static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; template<class OtherExtents> friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type extents_{}; // exposition only // [mdspan.sub.map], submdspan mapping specialization template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only -> see below; template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...); } }; }
If Extents is not a specialization of extents, then the program is ill-formed.
layout_left​::​mapping<E> is a trivially copyable type that models regular for each E.
Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type.

23.7.3.4.5.2 Constructors [mdspan.layout.left.cons]

constexpr mapping(const extents_type& e) noexcept;
Preconditions: The size of the multidimensional index space e is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with e.
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept;
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>& other) noexcept;
Constraints:
  • extents_type​::​rank() <= 1 is true, and
  • is_constructible_v<extents_type, OtherExtents> is true.
Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class LayoutLeftPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>) mapping(const LayoutLeftPaddedMapping&) noexcept;
Constraints:
  • is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping> is true.
  • is_constructible_v<extents_type, typename LayoutLeftPaddedMapping​::​extents_type>
    is true.
Mandates: If
  • Extents​::​rank() is greater than one,
  • Extents​::​static_extent(0) does not equal dynamic_extent, and
  • LayoutLeftPaddedMapping​::​static-padding-stride does not equal dynamic_extent,
then Extents​::​static_extent(0) equals LayoutLeftPaddedMapping​::​static-padding-stride.
Preconditions:
  • If extents_type​::​rank() > 1 is true, then other.stride(1) equals other.extents(0).
  • other.required_span_size() is representable as a value of type index_type.
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions:
  • If extents_type​::​rank() > 0 is true, then for all r in the range [0, extents_type​::​rank()), other.stride(r) equals other.extents().fwd-prod-of-extents(r), and
  • other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().

23.7.3.4.5.3 Observers [mdspan.layout.left.obs]

constexpr index_type required_span_size() const noexcept;
Returns: extents().fwd-prod-of-extents(extents_type​::​rank()).
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;
Constraints:
  • sizeof...(Indices) == extents_type​::​rank() is true,
  • (is_convertible_v<Indices, index_type> && ...) is true, and
  • (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).
Effects: Let P be a parameter pack such that is_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.
Equivalent to: return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
constexpr index_type stride(rank_type i) const;
Constraints: extents_type​::​rank() > 0 is true.
Preconditions: i < extents_type​::​rank() is true.
Returns: extents().fwd-prod-of-extents(i).
template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
Constraints: extents_type​::​rank() == OtherExtents​::​rank() is true.
Effects: Equivalent to: return x.extents() == y.extents();

23.7.3.4.6 Class template layout_right​::​mapping [mdspan.layout.right]

23.7.3.4.6.1 Overview [mdspan.layout.right.overview]

layout_right provides a layout mapping where the rightmost extent is stride 1, and strides increase right-to-left as the product of extents.
namespace std { template<class Extents> class layout_right::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right; // [mdspan.layout.right.cons], constructors constexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>&) noexcept; template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&) noexcept; template<class LayoutRightPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept; template<class OtherExtents> constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [mdspan.layout.right.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const noexcept; template<class... Indices> constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept { return true; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } static constexpr bool is_exhaustive() noexcept { return true; } static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; template<class OtherExtents> friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type extents_{}; // exposition only // [mdspan.sub.map], submdspan mapping specialization template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only -> see below; template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...); } }; }
If Extents is not a specialization of extents, then the program is ill-formed.
layout_right​::​mapping<E> is a trivially copyable type that models regular for each E.
Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type.

23.7.3.4.6.2 Constructors [mdspan.layout.right.cons]

constexpr mapping(const extents_type& e) noexcept;
Preconditions: The size of the multidimensional index space e is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with e.
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept;
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>& other) noexcept;
Constraints:
  • extents_type​::​rank() <= 1 is true, and
  • is_constructible_v<extents_type, OtherExtents> is true.
Preconditions: other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class LayoutRightPaddedMapping> constexpr explicit(!is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>) mapping(const LayoutRightPaddedMapping&) noexcept;
Constraints:
  • is-layout-right-padded-mapping-of<LayoutRightPaddedMapping> is true.
  • is_constructible_v<extents_type, typename LayoutRightPaddedMapping​::​extents_-
    type>
    is true.
Mandates: If
  • Extents​::​rank() is greater than one,
  • Extents​::​static_extent(Extents​::​rank() - 1) does not equal dynamic_extent, and
  • LayoutRightPaddedMapping​::​static-padding-stride does not equal dynamic_extent,
then Extents​::​static_extent(Extents​::​rank() - 1) equals LayoutRightPaddedMapping​::​static-padding-stride.
Preconditions:
  • If extents_type​::​rank() > 1 is true, then other.stride(extents_type​::​rank() - 2)
    equals other.extents().extent(extents_type​::​rank() - 1).
  • other.required_span_size() is representable as a value of type index_type.
Effects: Direct-non-list-initializes extents_ with other.extents().
template<class OtherExtents> constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>& other) noexcept;
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions:
  • If extents_type​::​rank() > 0 is true, then for all r in the range [0, extents_type​::​rank()), other.stride(r) equals other.extents().rev-prod-of-extents(r).
  • other.required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().

23.7.3.4.6.3 Observers [mdspan.layout.right.obs]

index_type required_span_size() const noexcept;
Returns: extents().fwd-prod-of-extents(extents_type​::​rank()).
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;
Constraints:
  • sizeof...(Indices) == extents_type​::​rank() is true,
  • (is_convertible_v<Indices, index_type> && ...) is true, and
  • (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).
Effects: Let P be a parameter pack such that is_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.
Equivalent to: return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
constexpr index_type stride(rank_type i) const noexcept;
Constraints: extents_type​::​rank() > 0 is true.
Preconditions: i < extents_type​::​rank() is true.
Returns: extents().rev-prod-of-extents(i).
template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
Constraints: extents_type​::​rank() == OtherExtents​::​rank() is true.
Effects: Equivalent to: return x.extents() == y.extents();

23.7.3.4.7 Class template layout_stride​::​mapping [mdspan.layout.stride]

23.7.3.4.7.1 Overview [mdspan.layout.stride.overview]

layout_stride provides a layout mapping where the strides are user-defined.
namespace std { template<class Extents> class layout_stride::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_stride; private: static constexpr rank_type rank_ = extents_type::rank(); // exposition only public: // [mdspan.layout.stride.cons], constructors constexpr mapping() noexcept; constexpr mapping(const mapping&) noexcept = default; template<class OtherIndexType> constexpr mapping(const extents_type&, span<OtherIndexType, rank_>) noexcept; template<class OtherIndexType> constexpr mapping(const extents_type&, const array<OtherIndexType, rank_>&) noexcept; template<class StridedLayoutMapping> constexpr explicit(see below) mapping(const StridedLayoutMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [mdspan.layout.stride.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, rank_> strides() const noexcept { return strides_; } constexpr index_type required_span_size() const noexcept; template<class... Indices> constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept { return false; } static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type i) const noexcept { return strides_[i]; } template<class OtherMapping> friend constexpr bool operator==(const mapping&, const OtherMapping&) noexcept; private: extents_type extents_{}; // exposition only array<index_type, rank_> strides_{}; // exposition only // [mdspan.sub.map], submdspan mapping specialization template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only -> see below; template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...); } }; }
If Extents is not a specialization of extents, then the program is ill-formed.
layout_stride​::​mapping<E> is a trivially copyable type that models regular for each E.
Mandates: If Extents​::​rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type typename Extents​::​index_type.

23.7.3.4.7.2 Exposition-only helpers [mdspan.layout.stride.expo]

Let REQUIRED-SPAN-SIZE(e, strides) be:
  • 1, if e.rank() == 0 is true,
  • otherwise 0, if the size of the multidimensional index space e is 0,
  • otherwise 1 plus the sum of products of (e.extent(r) - 1) and extents_type::index-cast(strides[r]) for all r in the range [0, e.rank()).
Let OFFSET(m) be:
  • m(), if e.rank() == 0 is true,
  • otherwise 0, if the size of the multidimensional index space e is 0,
  • otherwise m(z...) for a pack of integers z that is a multidimensional index in m.extents() and each element of z equals 0.
Let is-extents be the exposition-only variable template defined as follows: template<class T> constexpr bool is-extents = false; // exposition only template<class IndexType, size_t... Args> constexpr bool is-extents<extents<IndexType, Args...>> = true; // exposition only
Let layout-mapping-alike be the exposition-only concept defined as follows: template<class M> concept layout-mapping-alike = requires { // exposition only requires is-extents<typename M::extents_type>; { M::is_always_strided() } -> same_as<bool>; { M::is_always_exhaustive() } -> same_as<bool>; { M::is_always_unique() } -> same_as<bool>; bool_constant<M::is_always_strided()>::value; bool_constant<M::is_always_exhaustive()>::value; bool_constant<M::is_always_unique()>::value; };
[Note 1: 
This concept checks that the functions M​::​is_always_strided(), M​::​is_always_exhaustive(), and M​::​is_always_unique() exist, are constant expressions, and have a return type of bool.
— end note]

23.7.3.4.7.3 Constructors [mdspan.layout.stride.cons]

constexpr mapping() noexcept;
Preconditions: layout_right​::​mapping<extents_type>().required_span_size() is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with extents_type(), and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with layout_right​::​mapping<extents_type>().stride(d).
template<class OtherIndexType> constexpr mapping(const extents_type& e, span<OtherIndexType, rank_> s) noexcept; template<class OtherIndexType> constexpr mapping(const extents_type& e, const array<OtherIndexType, rank_>& s) noexcept;
Constraints:
  • is_convertible_v<const OtherIndexType&, index_type> is true, and
  • is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
Preconditions:
  • The result of converting s[i] to index_type is greater than 0 for all i in the range [0, rank_).
  • REQUIRED-SPAN-SIZE(e, s) is representable as a value of type index_type ([basic.fundamental]).
  • If rank_ is greater than 0, then there exists a permutation P of the integers in the range [0, rank_), such that s[] >= s[] * e.extent(p) is true for all i in the range [1, rank_), where is the element of P.
    [Note 1: 
    For layout_stride, this condition is necessary and sufficient for is_unique() to be true.
    — end note]
Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with as_const(s[d]).
template<class StridedLayoutMapping> constexpr explicit(see below) mapping(const StridedLayoutMapping& other) noexcept;
Constraints:
  • layout-mapping-alike<StridedLayoutMapping> is satisfied.
  • is_constructible_v<extents_type, typename StridedLayoutMapping​::​extents_type> is
    true.
  • StridedLayoutMapping​::​is_always_unique() is true.
  • StridedLayoutMapping​::​is_always_strided() is true.
Preconditions:
Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_), direct-non-list-initializes strides_[d] with other.stride(d).
Remarks: The expression inside explicit is equivalent to: !(is_convertible_v<typename StridedLayoutMapping::extents_type, extents_type> && (is-mapping-of<layout_left, StridedLayoutMapping> || is-mapping-of<layout_right, StridedLayoutMapping> || is-layout-left-padded-mapping-of<StridedLayoutMapping> || is-layout-right-padded-mapping-of<StridedLayoutMapping> || is-mapping-of<layout_stride, StridedLayoutMapping>))

23.7.3.4.7.4 Observers [mdspan.layout.stride.obs]

constexpr index_type required_span_size() const noexcept;
Returns: REQUIRED-SPAN-SIZE(extents(), strides_).
template<class... Indices> constexpr index_type operator()(Indices... i) const noexcept;
Constraints:
  • sizeof...(Indices) == rank_ is true,
  • (is_convertible_v<Indices, index_type> && ...) is true, and
  • (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions: extents_type​::​index-cast(i) is a multidimensional index in extents_ ([mdspan.overview]).
Effects: Let P be a parameter pack such that is_same_v<index_sequence_for<Indices...>, index_sequence<P...>> is true.
Equivalent to: return ((static_cast<index_type>(i) * stride(P)) + ... + 0);
constexpr bool is_exhaustive() const noexcept;
Returns:
  • true if rank_ is 0.
  • Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that stride() equals 1, and stride() equals stride() * extents().extent() for i in the range [1, rank_), where is the element of P.
  • Otherwise, false.
template<class OtherMapping> friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept;
Constraints:
Preconditions: OtherMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]).
Returns: true if x.extents() == y.extents() is true, OFFSET(y) == 0 is true, and each of x.stride(r) == y.stride(r) is true for r in the range [0, x.extents().rank()).
Otherwise, false.

23.7.3.4.8 Class template layout_left_padded​::​mapping [mdspan.layout.leftpad]

23.7.3.4.8.1 Overview [mdspan.layout.leftpad.overview]

layout_left_padded provides a layout mapping that behaves like layout_left​::​mapping, except that the padding stride stride(1) can be greater than or equal to extent(0).
namespace std { template<size_t PaddingValue> template<class Extents> class layout_left_padded<PaddingValue>::mapping { public: static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left_padded<PaddingValue>; private: static constexpr size_t rank_ = extents_type::rank(); // exposition only static constexpr size_t first-static-extent = // exposition only extents_type::static_extent(0); // [mdspan.layout.leftpad.expo], exposition-only members static constexpr size_t static-padding-stride = see below; // exposition only public: // [mdspan.layout.leftpad.cons], constructors constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); template<class OtherIndexType> constexpr mapping(const extents_type&, OtherIndexType); template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>&); template<class OtherExtents> constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<OtherExtents>&); template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping&); template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [mdspan.layout.leftpad.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, rank_> strides() const noexcept; constexpr index_type required_span_size() const noexcept; template<class... Indices> constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; template<class LayoutLeftPaddedMapping> friend constexpr bool operator==(const mapping&, const LayoutLeftPaddedMapping&) noexcept; private: // [mdspan.layout.leftpad.expo], exposition-only members index_type stride-1 = static-padding-stride; // exposition only extents_type extents_{}; // exposition only // [mdspan.sub.map], submdspan mapping specialization template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only -> see below; template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...); } }; }
If Extents is not a specialization of extents, then the program is ill-formed.
layout_left_padded​::​mapping<E> is a trivially copyable type that models regular for each E.
Throughout [mdspan.layout.leftpad], let P_rank be the following size rank_ parameter pack of size_t values:
  • the empty parameter pack, if rank_ equals zero;
  • otherwise, 0zu, if rank_ equals one;
  • otherwise, the parameter pack 0zu, 1zu, …, rank_- 1.
Mandates:
  • If rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type index_type.
  • padding_value is representable as a value of type index_type.
  • If
    • rank_ is greater than one,
    • padding_value does not equal dynamic_extent, and
    • first-static-extent does not equal dynamic_extent,
    then LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent) is representable as a value of type size_t, and is representable as a value of type index_type.
  • If
    • rank_ is greater than one,
    • padding_value does not equal dynamic_extent, and
    • extents_type​::​static_extent(k) does not equal dynamic_extent for all k in the range [0, extents_type​::​rank()),
    then the product of LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(0)) and all values ext.static_extent(k) with k in the range of [1, rank_) is representable as a value of type size_t, and is representable as a value of type index_type.

23.7.3.4.8.2 Exposition-only members [mdspan.layout.leftpad.expo]

static constexpr size_t static-padding-stride = see below;
The value is
  • 0, if rank_ equals zero or one;
  • otherwise, dynamic_extent, if padding_value or first-static-extent equals dynamic_extent;
  • otherwise, the size_t value which is LEAST-MULTIPLE-AT-LEAST(padding_value, first-static-extent).
index_type stride-1 = static-padding-stride;
Recommended practice: Implementations should not store this value if static-padding-stride is not dynamic_extent.
[Note 1: 
Using extents<index_type, static-padding-stride> instead of index_type as the type of stride-1 would achieve this.
— end note]

23.7.3.4.8.3 Constructors [mdspan.layout.leftpad.cons]

constexpr mapping(const extents_type& ext);
Preconditions:
  • The size of the multidimensional index space ext is representable as a value of type index_type.
  • If rank_ is greater than one and padding_value does not equal dynamic_extent, then LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0)) is representable as a value of type index_type.
  • If rank_ is greater than one and padding_value does not equal dynamic_extent, then the product of LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0)) and all values ext.extent(k) with k in the range of [1, rank_) is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with ext; and
  • if rank_ is greater than one, direct-non-list-initializes stride-1
    • with ext.extent(0) if padding_value is dynamic_extent,
    • otherwise with LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(0)).
template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType pad);
Constraints:
  • is_convertible_v<OtherIndexType, index_type> is true.
  • is_nothrow_constructible_v<index_type, OtherIndexType> is true.
Preconditions:
  • pad is representable as a value of type index_type.
  • extents_type​::​index-cast(pad) is greater than zero.
  • If rank_ is greater than one, then LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)) is representable as a value of type index_type.
  • If rank_ is greater than one, then the product of LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)) and all values ext.extent(k) with k in the range of [1, rank_) is representable as a value of type index_type.
  • If padding_value is not equal to dynamic_extent, padding_value equals extents_type​::​index-cast(pad).
Effects: Direct-non-list-initializes extents_ with ext, and if rank_ is greater than one, direct-non-list-initializes stride-1 with LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(0)).
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_left::mapping<OtherExtents>& other);
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Mandates: If OtherExtents​::​rank() is greater than 1, then (static-padding-stride == dynamic_extent) || (OtherExtents::static_extent(0) == dynamic_extent) || (static-padding-stride == OtherExtents::static_extent(0)) is true.
Preconditions:
  • If extents_type​::​rank() > 1 is true and padding_value == dynamic_extent is false, then other.stride(1) equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extents().extent(0))) and
  • other.required_span_size() is representable as a value of type index_type.
Effects: Equivalent to mapping(other.extents()).
template<class OtherExtents> constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions:
  • If rank_ is greater than 1 and padding_value does not equal dynamic_extent, then other.stride(1) equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extents().extent(0)))
  • If rank_ is greater than 0, then other.stride(0) equals 1.
  • If rank_ is greater than 2, then for all r in the range [2, rank_), other.stride(r) equals (other.extents().fwd-prod-of-extents(r) / other.extents().extent(0)) * other.stride(1)
  • other.required_span_size() is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with other.extents() and
  • if rank_ is greater than one, direct-non-list-initializes stride-1 with other.stride(1).
template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other);
Constraints:
  • is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping> is true.
  • is_constructible_v<extents_type, typename LayoutLeftPaddedMapping​::​extents_type>
    is true.
Mandates: If rank_ is greater than 1, then padding_value == dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent || padding_value == LayoutLeftPaddedMapping::padding_value is true.
  • If rank_ is greater than 1 and padding_value does not equal dynamic_extent, then other.stride(1) equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extent(0)))
  • other.required_span_size() is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with other.extents() and
  • if rank_ is greater than one, direct-non-list-initializes stride-1 with other.stride(1).
Remarks: The expression inside explicit is equivalent to: rank_> 1 && (padding_value != dynamic_extent || LayoutLeftPaddedMapping::padding_value == dynamic_extent)
template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other) noexcept;
Constraints:
  • is-layout-right-padded-mapping-of<LayoutRightPaddedMapping> is true or
    is-mapping-of<layout_right, LayoutRightPaddedMapping> is true.
  • rank_ equals zero or one.
  • is_constructible_v<extents_type, typename LayoutRightPaddedMapping​::​extents_-
    type>
    is true.
Preconditions: other.required_span_size() is representable as a value of type index_type.
Effects: Direct-non-list-initializes extents_ with other.extents().
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<typename LayoutRightPaddedMapping::extents_type, extents_type>
[Note 1: 
Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride does not affect either the constraints or the preconditions.
— end note]

23.7.3.4.8.4 Observers [mdspan.layout.leftpad.obs]

constexpr array<index_type, rank_> strides() const noexcept;
Returns: array<index_type, rank_>({stride(P_rank)...}).
constexpr index_type required_span_size() const noexcept;
Returns:
  • 0 if the multidimensional index space extents_ is empty,
  • otherwise, *this(((extents_(P_rank) - index_type(1))...)) + 1.
template<class... Indices> constexpr size_t operator()(Indices... idxs) const noexcept;
Constraints:
  • sizeof...(Indices) == rank_ is true.
  • (is_convertible_v<Indices, index_type> && ...) is true.
  • (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions: extents_type​::​index-cast(idxs) is a multidimensional index in extents() ([mdspan.overview]).
Returns: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0).
static constexpr bool is_always_exhaustive() noexcept;
Returns:
  • If rank_ equals zero or one, then true;
  • otherwise, if neither static-padding-stride nor first-static-extent equal dynamic_extent, then static-padding-stride == first-static-extent;
  • otherwise, false.
constexpr bool is_exhaustive() const noexcept;
Returns: true if rank_ equals zero or one; otherwise, extents_.extent(0) == stride(1).
constexpr index_type stride(rank_type r) const noexcept;
Preconditions: r is smaller than rank_.
Returns:
  • If r equals zero: 1;
  • otherwise, if r equals one: stride-1;
  • otherwise, the product of stride-1 and all values extents_.extent(k) with k in the range [1, r).
template<class LayoutLeftPaddedMapping> friend constexpr bool operator==(const mapping& x, const LayoutLeftPaddedMapping& y) noexcept;
Constraints:
  • is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping> is true.
  • LayoutLeftPaddedMapping​::​extents_type​::​rank() == rank_ is true.
Returns: true if x.extents() == y.extents() is true and rank_ < 2 || x.stride(1) == y.
stride(1)
is true.
Otherwise, false.

23.7.3.4.9 Class template layout_right_padded​::​mapping [mdspan.layout.rightpad]

23.7.3.4.9.1 Overview [mdspan.layout.rightpad.overview]

layout_right_padded provides a layout mapping that behaves like layout_right​::​mapping, except that the padding stride stride(extents_type​::​rank() - 2) can be greater than or equal to extents_type​::​extent(extents_type​::​rank() - 1).
namespace std { template<size_t PaddingValue> template<class Extents> class layout_right_padded<PaddingValue>::mapping { public: static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right_padded<PaddingValue>; private: static constexpr size_t rank_ = extents_type::rank(); // exposition only static constexpr size_t last-static-extent = // exposition only extents_type::static_extent(rank_ - 1); // [mdspan.layout.rightpad.expo], exposition-only members static constexpr size_t static-padding-stride = see below; // exposition only public: // [mdspan.layout.rightpad.cons], constructors constexpr mapping() noexcept : mapping(extents_type{}) {} constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&); template<class OtherIndexType> constexpr mapping(const extents_type&, OtherIndexType); template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>&); template<class OtherExtents> constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping<OtherExtents>&); template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping&); template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping&) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [mdspan.layout.rightpad.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr array<index_type, rank_> strides() const noexcept; constexpr index_type required_span_size() const noexcept; template<class... Indices> constexpr index_type operator()(Indices...) const noexcept; static constexpr bool is_always_unique() noexcept { return true; } static constexpr bool is_always_exhaustive() noexcept; static constexpr bool is_always_strided() noexcept { return true; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept; static constexpr bool is_strided() noexcept { return true; } constexpr index_type stride(rank_type) const noexcept; template<class LayoutRightPaddedMapping> friend constexpr bool operator==(const mapping&, const LayoutRightPaddedMapping&) noexcept; private: // [mdspan.layout.rightpad.expo], exposition-only members index_type stride-rm2 = static-padding-stride; // exposition only extents_type extents_{}; // exposition only // [mdspan.sub.map], submdspan mapping specialization template<class... SliceSpecifiers> constexpr auto submdspan-mapping-impl(SliceSpecifiers...) const // exposition only -> see below; template<class... SliceSpecifiers> friend constexpr auto submdspan_mapping(const mapping& src, SliceSpecifiers... slices) { return src.submdspan-mapping-impl(slices...); } }; }
If Extents is not a specialization of extents, then the program is ill-formed.
layout_right_padded​::​mapping<E> is a trivially copyable type that models regular for each E.
Throughout [mdspan.layout.rightpad], let P_rank be the following size rank_ parameter pack of size_t values:
  • the empty parameter pack, if rank_ equals zero;
  • otherwise, 0zu, if rank_ equals one;
  • otherwise, the parameter pack 0zu, 1zu, …, rank_- 1.
Mandates:
  • If rank_dynamic() == 0 is true, then the size of the multidimensional index space Extents() is representable as a value of type index_type.
  • padding_value is representable as a value of type index_type.
  • If
    • rank_ is greater than one,
    • padding_value does not equal dynamic_extent, and
    • last-static-extent does not equal dynamic_extent,
    then LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent) is representable as a value of type size_t, and is representable as a value of type index_type.
  • If
    • rank_ is greater than one,
    • padding_value does not equal dynamic_extent, and
    • extents_type​::​static_extent(k) does not equal dynamic_extent for all k in the range [0, rank_),
    then the product of LEAST-MULTIPLE-AT-LEAST(padding_value, ext.static_extent(rank_ - 1)) and all values ext.static_extent(k) with k in the range of [0, rank_ - 1) is representable as a value of type size_t, and is representable as a value of type index_type.

23.7.3.4.9.2 Exposition-only members [mdspan.layout.rightpad.expo]

static constexpr size_t static-padding-stride = see below;
The value is
  • 0, if rank_ equals zero or one;
  • otherwise, dynamic_extent, if padding_value or last-static-extent equals dynamic_extent;
  • otherwise, the size_t value which is LEAST-MULTIPLE-AT-LEAST(padding_value, last-static-extent).
index_type stride-rm2 = static-padding-stride;
Recommended practice: Implementations should not store this value if static-padding-stride is not dynamic_extent.
[Note 1: 
Using extents<index_type, static-padding-stride> instead of index_type as the type of stride-rm2 would achieve this.
— end note]

23.7.3.4.9.3 Constructors [mdspan.layout.rightpad.cons]

constexpr mapping(const extents_type& ext);
Preconditions:
  • The size of the multidimensional index space ext is representable as a value of type index_type.
  • If rank_ is greater than one and padding_value does not equal dynamic_extent, then LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1)) is representable as a value of type index_type.
  • If rank_ is greater than one and padding_value does not equal dynamic_extent, then the product of LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1)) and all values ext.extent(k) with k in the range of [0, rank_ - 1) is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with ext; and
  • if rank_ is greater than one, direct-non-list-initializes stride-rm2
    • with ext.extent(rank_ - 1) if padding_value is dynamic_extent,
    • otherwise with LEAST-MULTIPLE-AT-LEAST(padding_value, ext.extent(rank_ - 1)).
template<class OtherIndexType> constexpr mapping(const extents_type& ext, OtherIndexType pad);
Constraints:
  • is_convertible_v<OtherIndexType, index_type> is true.
  • is_nothrow_constructible_v<index_type, OtherIndexType> is true.
Preconditions:
  • pad is representable as a value of type index_type.
  • extents_type​::​index-cast(pad) is greater than zero.
  • If rank_ is greater than one, then LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)) is representable as a value of type index_type.
  • If rank_ is greater than one, then the product of LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)) and all values ext.extent(k) with k in the range of [0, rank_ - 1) is representable as a value of type index_type.
  • If padding_value is not equal to dynamic_extent, padding_value equals extents_type​::​index-cast(pad).
Effects: Direct-non-list-initializes extents_ with ext, and if rank_ is greater than one, direct-non-list-initializes stride-rm2 with LEAST-MULTIPLE-AT-LEAST(pad, ext.extent(rank_ - 1)).
template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const layout_right::mapping<OtherExtents>& other);
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Mandates: If OtherExtents​::​rank() is greater than 1, then (static-padding-stride == dynamic_extent) || (OtherExtents::static_extent(rank_ - 1) == dynamic_extent) || (static-padding-stride == OtherExtents::static_extent(rank_ - 1)) is true.
Preconditions:
  • If rank_ > 1 is true and padding_value == dynamic_extent is false, then other.stride(
    rank_ - 2)
    equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extents().extent(rank_ - 1))) and
  • other.required_span_size() is representable as a value of type index_type.
Effects: Equivalent to mapping(other.extents()).
template<class OtherExtents> constexpr explicit(rank_ > 0) mapping(const layout_stride::mapping<OtherExtents>& other);
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions:
  • If rank_ is greater than 1 and padding_value does not equal dynamic_extent, then other.stride(rank_ - 2) equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extents().extent(rank_ - 1)))
  • If rank_ is greater than 0, then other.stride(rank_ - 1) equals 1.
  • If rank_ is greater than 2, then for all r in the range [0, rank_ - 2), other.stride(r) equals (other.extents().rev-prod-of-extents(r) / other.extents().extent(rank_ - 1)) * other.stride(rank_ - 2)
  • other.required_span_size() is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with other.extents(); and
  • if rank_ is greater than one, direct-non-list-initializes stride-rm2 with other.stride(rank_ - 2).
template<class LayoutRightPaddedMapping> constexpr explicit(see below) mapping(const LayoutRightPaddedMapping& other);
Constraints:
  • is-layout-right-padded-mapping-of<LayoutRightPaddedMapping> is true.
  • is_constructible_v<extents_type, typename LayoutRightPaddedMapping​::​extents_-
    type>
    is true.
Mandates: If rank_ is greater than 1, then padding_value == dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent || padding_value == LayoutRightPaddedMapping::padding_value is true.
Preconditions:
  • If rank_ is greater than 1 and padding_value does not equal dynamic_extent, then other.stride(rank_ - 2) equals LEAST-MULTIPLE-AT-LEAST(padding_value, extents_type::index-cast(other.extent(rank_ - 1)))
  • other.required_span_size() is representable as a value of type index_type.
Effects:
  • Direct-non-list-initializes extents_ with other.extents(); and
  • if rank_ is greater than one, direct-non-list-initializes stride-rm2 with other.stride(rank_ - 2).
Remarks: The expression inside explicit is equivalent to: rank_ > 1 && (padding_value != dynamic_extent || LayoutRightPaddedMapping::padding_value == dynamic_extent)
template<class LayoutLeftPaddedMapping> constexpr explicit(see below) mapping(const LayoutLeftPaddedMapping& other) noexcept;
Constraints:
  • is-layout-left-padded-mapping-of<LayoutLeftPaddedMapping> is true or
    is-mapping-of<layout_left, LayoutLeftPaddedMapping> is true.
  • rank_ equals zero or one.
  • is_constructible_v<extents_type, typename LayoutLeftPaddedMapping​::​extents_type>
    is true.
Preconditions: other.required_span_size() is representable as a value of type index_type.
Effects: Direct-non-list-initializes extents_ with other.extents().
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<typename LayoutLeftPaddedMapping::extents_type, extents_type>
[Note 1: 
Neither the input mapping nor the mapping to be constructed uses the padding stride in the rank-0 or rank-1 case, so the padding stride affects neither the constraints nor the preconditions.
— end note]

23.7.3.4.9.4 Observers [mdspan.layout.rightpad.obs]

constexpr array<index_type, rank_> strides() const noexcept;
Returns: array<index_type, rank_>(stride(P_rank)...).
constexpr index_type required_span_size() const noexcept;
Returns: 0 if the multidimensional index space extents_ is empty, otherwise *this(((extents_(P_rank) - index_type(1))...)) + 1.
template<class... Indices> constexpr size_t operator()(Indices... idxs) const noexcept;
Constraints:
  • sizeof...(Indices) == rank_ is true.
  • (is_convertible_v<Indices, index_type> && ...) is true.
  • (is_nothrow_constructible_v<index_type, Indices> && ...) is true.
Preconditions: extents_type​::​index-cast(idxs) is a multidimensional index in extents() ([mdspan.overview]).
Returns: ((static_cast<index_type>(idxs) * stride(P_rank)) + ... + 0).
static constexpr bool is_always_exhaustive() noexcept;
Returns:
  • If rank_ equals zero or one, then true;
  • otherwise, if neither static-padding-stride nor last-static-extent equal dynamic_extent, then static-padding-stride == last-static-extent;
  • otherwise, false.
constexpr bool is_exhaustive() const noexcept;
Returns: true if rank_ equals zero or one; otherwise, extents_.extent(rank_ - 1) == stride(rank_ - 2)
constexpr index_type stride(rank_type r) const noexcept;
Preconditions: r is smaller than rank_.
Returns:
  • If r equals rank_ - 1: 1;
  • otherwise, if r equals rank_ - 2: stride-rm2;
  • otherwise, the product of stride-rm2 and all values extents_.extent(k) with k in the range of [r + 1, rank_ - 1).
template<class LayoutRightPaddedMapping> friend constexpr bool operator==(const mapping& x, const LayoutRightPaddedMapping& y) noexcept;
Constraints:
  • is-layout-right-padded-mapping-of<LayoutRightPaddedMapping> is true.
  • LayoutRightPaddedMapping​::​extents_type​::​rank() == rank_ is true.
Returns: true if x.extents() == y.extents() is true and rank_ < 2 || x.stride(rank_ - 2) == y.stride(rank_ - 2) is true.
Otherwise, false.

23.7.3.5 Accessor policy [mdspan.accessor]

23.7.3.5.1 General [mdspan.accessor.general]

An accessor policy defines types and operations by which a reference to a single object is created from an abstract data handle to a number of such objects and an index.
A range of indices is an accessible range of a given data handle and an accessor if, for each i in the range, the accessor policy's access function produces a valid reference to an object.
  • A denotes an accessor policy.
  • a denotes a value of type A or const A.
  • p denotes a value of type A​::​data_handle_type or const A​::​data_handle_type.
    [Note 1: 
    The type A​::​data_handle_type need not be dereferenceable.
    — end note]
  • n, i, and j each denote values of type size_t.

23.7.3.5.2 Requirements [mdspan.accessor.reqmts]

A type A meets the accessor policy requirements if
  • A models copyable,
  • is_nothrow_move_constructible_v<A> is true,
  • is_nothrow_move_assignable_v<A> is true,
  • is_nothrow_swappable_v<A> is true, and
  • the following types and expressions are well-formed and have the specified semantics.
typename A::element_type
Result: A complete object type that is not an abstract class type.
typename A::data_handle_type
Result: A type that models copyable, and for which is_nothrow_move_constructible_v<A​::​data_handle_type> is true, is_nothrow_move_assignable_v<A​::​data_handle_type> is true, and is_nothrow_swappable_v<A​::​data_handle_type> is true.
[Note 1: 
The type of data_handle_type need not be element_type*.
— end note]
typename A::reference
Result: A type that models common_reference_with<A​::​reference&&, A​::​element_type&>.
[Note 2: 
The type of reference need not be element_type&.
— end note]
typename A::offset_policy
Result: A type OP such that:
  • OP meets the accessor policy requirements,
  • constructible_from<OP, const A&> is modeled, and
  • is_same_v<typename OP​::​element_type, typename A​::​element_type> is true.
a.access(p, i)
Result: A​::​reference
Remarks: The expression is equality preserving.
[Note 3: 
Concrete accessor policies can impose preconditions for their access function.
However, they might not.
For example, an accessor where p is span<A​::​element_type, dynamic_extent> and access(p, i) returns p[i % p.size()] does not need to impose a precondition on i.
— end note]
a.offset(p, i)
Result: A​::​offset_policy​::​data_handle_type
Returns: q such that for b being A​::​offset_policy(a), and any integer n for which [0, n) is an accessible range of p and a:
  • is an accessible range of q and b; and
  • b.access(q, j) provides access to the same element as a.access(p, i + j), for every j in the range .
Remarks: The expression is equality-preserving.

23.7.3.5.3 Class template default_accessor [mdspan.accessor.default]

23.7.3.5.3.1 Overview [mdspan.accessor.default.overview]

namespace std { template<class ElementType> struct default_accessor { using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; constexpr default_accessor() noexcept = default; template<class OtherElementType> constexpr default_accessor(default_accessor<OtherElementType>) noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; }; }
default_accessor meets the accessor policy requirements.
ElementType is required to be a complete object type that is neither an abstract class type nor an array type.
Each specialization of default_accessor is a trivially copyable type that models semiregular.
is an accessible range for an object p of type data_handle_type and an object of type default_accessor if and only if [p, p + n) is a valid range.

23.7.3.5.3.2 Members [mdspan.accessor.default.members]

template<class OtherElementType> constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}
Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
constexpr reference access(data_handle_type p, size_t i) const noexcept;
Effects: Equivalent to: return p[i];
constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
Effects: Equivalent to: return p + i;

23.7.3.5.4 Class template aligned_accessor [mdspan.accessor.aligned]

23.7.3.5.4.1 Overview [mdspan.accessor.aligned.overview]

namespace std { template<class ElementType, size_t ByteAlignment> struct aligned_accessor { using offset_policy = default_accessor<ElementType>; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; static constexpr size_t byte_alignment = ByteAlignment; constexpr aligned_accessor() noexcept = default; template<class OtherElementType, size_t OtherByteAlignment> constexpr aligned_accessor( aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept; template<class OtherElementType> constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept; template<class OtherElementType> constexpr operator default_accessor<OtherElementType>() const noexcept; constexpr reference access(data_handle_type p, size_t i) const noexcept; constexpr typename offset_policy::data_handle_type offset( data_handle_type p, size_t i) const noexcept; }; }
Mandates:
  • byte_alignment is a power of two, and
  • byte_alignment >= alignof(ElementType) is true.
aligned_accessor meets the accessor policy requirements.
ElementType is required to be a complete object type that is neither an abstract class type nor an array type.
Each specialization of aligned_accessor is a trivially copyable type that models semiregular.
[0, n) is an accessible range for an object p of type data_handle_type and an object of type aligned_accessor if and only if
  • [p, p + n) is a valid range, and,
  • if n is greater than zero, then is_sufficiently_aligned<byte_alignment>(p) is true.
[Example 1: 
The following function compute uses is_sufficiently_aligned to check whether a given mdspan with default_accessor has a data handle with sufficient alignment to be used with aligned_accessor<float, 4 * sizeof(float)>.
If so, the function dispatches to a function compute_using_fourfold_overalignment that requires fourfold over-alignment of arrays, but can therefore use hardware-specific instructions, such as four-wide SIMD (Single Instruction Multiple Data) instructions.
Otherwise, compute dispatches to a possibly less optimized function compute_without_requiring_overalignment that has no over-alignment requirement.
void compute_using_fourfold_overalignment( std::mdspan<float, std::dims<1>, std::layout_right, std::aligned_accessor<float, 4 * alignof(float)>> x); void compute_without_requiring_overalignment( std::mdspan<float, std::dims<1>, std::layout_right> x); void compute(std::mdspan<float, std::dims<1>> x) { constexpr auto byte_alignment = 4 * sizeof(float); auto accessor = std::aligned_accessor<float, byte_alignment>{}; auto x_handle = x.data_handle(); if (std::is_sufficiently_aligned<byte_alignment>(x_handle)) { compute_using_fourfold_overalignment(std::mdspan{x_handle, x.mapping(), accessor}); } else { compute_without_requiring_overalignment(x); } } — end example]

23.7.3.5.4.2 Members [mdspan.accessor.aligned.members]

template<class OtherElementType, size_t OtherByteAlignment> constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
Constraints:
  • is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
  • OtherByteAlignment >= byte_alignment is true.
Effects: None.
template<class OtherElementType> constexpr explicit aligned_accessor(default_accessor<OtherElementType>) noexcept;
Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
Effects: None.
constexpr reference access(data_handle_type p, size_t i) const noexcept;
Preconditions: [0, i + 1) is an accessible range for p and *this.
Effects: Equivalent to: return assume_aligned<byte_alignment>(p)[i];
template<class OtherElementType> constexpr operator default_accessor<OtherElementType>() const noexcept;
Constraints: is_convertible_v<element_type(*)[], OtherElementType(*)[]> is true.
Effects: Equivalent to: return {};
constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept;
Preconditions: [0, i + 1) is an accessible range for p and *this.
Effects: Equivalent to: return assume_aligned<byte_alignment>(p) + i;

23.7.3.6 Class template mdspan [mdspan.mdspan]

23.7.3.6.1 Overview [mdspan.mdspan.overview]

mdspan is a view of a multidimensional array of elements.
namespace std { template<class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor<ElementType>> class mdspan { public: using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping<extents_type>; using element_type = ElementType; using value_type = remove_cv_t<element_type>; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using data_handle_type = typename accessor_type::data_handle_type; using reference = typename accessor_type::reference; static constexpr rank_type rank() noexcept { return extents_type::rank(); } static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } static constexpr size_t static_extent(rank_type r) noexcept { return extents_type::static_extent(r); } constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } // [mdspan.mdspan.cons], constructors constexpr mdspan(); constexpr mdspan(const mdspan& rhs) = default; constexpr mdspan(mdspan&& rhs) = default; template<class... OtherIndexTypes> constexpr explicit mdspan(data_handle_type ptr, OtherIndexTypes... exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts); constexpr mdspan(data_handle_type p, const extents_type& ext); constexpr mdspan(data_handle_type p, const mapping_type& m); constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); template<class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessorPolicy> constexpr explicit(see below) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessorPolicy>& other); constexpr mdspan& operator=(const mdspan& rhs) = default; constexpr mdspan& operator=(mdspan&& rhs) = default; // [mdspan.mdspan.members], members template<class... OtherIndexTypes> constexpr reference operator[](OtherIndexTypes... indices) const; template<class OtherIndexType> constexpr reference operator[](span<OtherIndexType, rank()> indices) const; template<class OtherIndexType> constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const; constexpr size_type size() const noexcept; constexpr bool empty() const noexcept; friend constexpr void swap(mdspan& x, mdspan& y) noexcept; constexpr const extents_type& extents() const noexcept { return map_.extents(); } constexpr const data_handle_type& data_handle() const noexcept { return ptr_; } constexpr const mapping_type& mapping() const noexcept { return map_; } constexpr const accessor_type& accessor() const noexcept { return acc_; } static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); } static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); } static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); } constexpr bool is_unique() const { return map_.is_unique(); } constexpr bool is_exhaustive() const { return map_.is_exhaustive(); } constexpr bool is_strided() const { return map_.is_strided(); } constexpr index_type stride(rank_type r) const { return map_.stride(r); } private: accessor_type acc_; // exposition only mapping_type map_; // exposition only data_handle_type ptr_; // exposition only }; template<class CArray> requires (is_array_v<CArray> && rank_v<CArray> == 1) mdspan(CArray&) -> mdspan<remove_all_extents_t<CArray>, extents<size_t, extent_v<CArray, 0>>>; template<class Pointer> requires (is_pointer_v<remove_reference_t<Pointer>>) mdspan(Pointer&&) -> mdspan<remove_pointer_t<remove_reference_t<Pointer>>, extents<size_t>>; template<class ElementType, class... Integrals> requires ((is_convertible_v<Integrals, size_t> && ...) && sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) -> mdspan<ElementType, extents<size_t, maybe-static-ext<Integrals>...>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, span<OtherIndexType, N>) -> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class OtherIndexType, size_t N> mdspan(ElementType*, const array<OtherIndexType, N>&) -> mdspan<ElementType, dextents<size_t, N>>; template<class ElementType, class IndexType, size_t... ExtentsPack> mdspan(ElementType*, const extents<IndexType, ExtentsPack...>&) -> mdspan<ElementType, extents<IndexType, ExtentsPack...>>; template<class ElementType, class MappingType> mdspan(ElementType*, const MappingType&) -> mdspan<ElementType, typename MappingType::extents_type, typename MappingType::layout_type>; template<class MappingType, class AccessorType> mdspan(const typename AccessorType::data_handle_type&, const MappingType&, const AccessorType&) -> mdspan<typename AccessorType::element_type, typename MappingType::extents_type, typename MappingType::layout_type, AccessorType>; }
Mandates:
  • ElementType is a complete object type that is neither an abstract class type nor an array type,
  • Extents is a specialization of extents, and
  • is_same_v<ElementType, typename AccessorPolicy​::​element_type> is true.
LayoutPolicy shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]), and AccessorPolicy shall meet the accessor policy requirements ([mdspan.accessor.reqmts]).
Each specialization MDS of mdspan models copyable and
  • is_nothrow_move_constructible_v<MDS> is true,
  • is_nothrow_move_assignable_v<MDS> is true, and
  • is_nothrow_swappable_v<MDS> is true.
A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types.

23.7.3.6.2 Constructors [mdspan.mdspan.cons]

constexpr mdspan();
Constraints:
  • rank_dynamic() > 0 is true.
  • is_default_constructible_v<data_handle_type> is true.
  • is_default_constructible_v<mapping_type> is true.
  • is_default_constructible_v<accessor_type> is true.
Preconditions: [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for the values of map_ and acc_ after the invocation of this constructor.
Effects: Value-initializes ptr_, map_, and acc_.
template<class... OtherIndexTypes> constexpr explicit mdspan(data_handle_type p, OtherIndexTypes... exts);
Let N be sizeof...(OtherIndexTypes).
Constraints:
  • (is_convertible_v<OtherIndexTypes, index_type> && ...) is true,
  • (is_nothrow_constructible<index_type, OtherIndexTypes> && ...) is true,
  • N == rank() || N == rank_dynamic() is true,
  • is_constructible_v<mapping_type, extents_type> is true, and
  • is_default_constructible_v<accessor_type> is true.
Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.
Effects:
  • Direct-non-list-initializes ptr_ with std​::​move(p),
  • direct-non-list-initializes map_ with extents_type(static_cast<index_type>(std​::​move(exts​))...), and
  • value-initializes acc_.
template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, span<OtherIndexType, N> exts); template<class OtherIndexType, size_t N> constexpr explicit(N != rank_dynamic()) mdspan(data_handle_type p, const array<OtherIndexType, N>& exts);
Constraints:
  • is_convertible_v<const OtherIndexType&, index_type> is true,
  • is_nothrow_constructible_v<index_type, const OtherIndexType&> is true,
  • N == rank() || N == rank_dynamic() is true,
  • is_constructible_v<mapping_type, extents_type> is true, and
  • is_default_constructible_v<accessor_type> is true.
Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.
Effects:
  • Direct-non-list-initializes ptr_ with std​::​move(p),
  • direct-non-list-initializes map_ with extents_type(exts), and
  • value-initializes acc_.
constexpr mdspan(data_handle_type p, const extents_type& ext);
Constraints:
  • is_constructible_v<mapping_type, const extents_type&> is true, and
  • is_default_constructible_v<accessor_type> is true.
Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ for the values of map_ and acc_ after the invocation of this constructor.
Effects:
  • Direct-non-list-initializes ptr_ with std​::​move(p),
  • direct-non-list-initializes map_ with ext, and
  • value-initializes acc_.
constexpr mdspan(data_handle_type p, const mapping_type& m);
Constraints: is_default_constructible_v<accessor_type> is true.
Preconditions: [0, m.required_span_size()) is an accessible range of p and acc_ for the value of acc_ after the invocation of this constructor.
Effects:
  • Direct-non-list-initializes ptr_ with std​::​move(p),
  • direct-non-list-initializes map_ with m, and
  • value-initializes acc_.
constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a);
Preconditions: [0, m.required_span_size()) is an accessible range of p and a.
Effects:
  • Direct-non-list-initializes ptr_ with std​::​move(p),
  • direct-non-list-initializes map_ with m, and
  • direct-non-list-initializes acc_ with a.
template<class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor> constexpr explicit(see below) mdspan(const mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessor>& other);
Constraints:
  • is_constructible_v<mapping_type, const OtherLayoutPolicy​::​template mapping<Oth-
    erExtents>&>
    is true, and
  • is_constructible_v<accessor_type, const OtherAccessor&> is true.
Mandates:
  • is_constructible_v<data_handle_type, const OtherAccessor​::​data_handle_type&> is
    true, and
  • is_constructible_v<extents_type, OtherExtents> is true.
Preconditions:
  • For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true.
  • [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for values of ptr_, map_, and acc_ after the invocation of this constructor.
Effects:
  • Direct-non-list-initializes ptr_ with other.ptr_,
  • direct-non-list-initializes map_ with other.map_, and
  • direct-non-list-initializes acc_ with other.acc_.
Remarks: The expression inside explicit is equivalent to: !is_convertible_v<const OtherLayoutPolicy::template mapping<OtherExtents>&, mapping_type> || !is_convertible_v<const OtherAccessor&, accessor_type>

23.7.3.6.3 Members [mdspan.mdspan.members]

template<class... OtherIndexTypes> constexpr reference operator[](OtherIndexTypes... indices) const;
Constraints:
  • (is_convertible_v<OtherIndexTypes, index_type> && ...) is true,
  • (is_nothrow_constructible_v<index_type, OtherIndexTypes> && ...) is true, and
  • sizeof...(OtherIndexTypes) == rank() is true.
Let I be extents_type​::​index-cast(std​::​move(indices)).
Preconditions: I is a multidimensional index in extents().
[Note 1: 
This implies that map_(I) < map_.required_span_size() is true.
— end note]
Effects: Equivalent to: return acc_.access(ptr_, map_(static_cast<index_type>(std::move(indices))...));
template<class OtherIndexType> constexpr reference operator[](span<OtherIndexType, rank()> indices) const; template<class OtherIndexType> constexpr reference operator[](const array<OtherIndexType, rank()>& indices) const;
Constraints:
  • is_convertible_v<const OtherIndexType&, index_type> is true, and
  • is_nothrow_constructible_v<index_type, const OtherIndexType&> is true.
Effects: Let P be a parameter pack such that is_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.
Equivalent to: return operator[](extents_type::index-cast(as_const(indices[P]))...);
constexpr size_type size() const noexcept;
Preconditions: The size of the multidimensional index space extents() is representable as a value of type size_type ([basic.fundamental]).
Returns: extents().fwd-prod-of-extents(rank()).
constexpr bool empty() const noexcept;
Returns: true if the size of the multidimensional index space extents() is 0, otherwise false.
friend constexpr void swap(mdspan& x, mdspan& y) noexcept;
Effects: Equivalent to: swap(x.ptr_, y.ptr_); swap(x.map_, y.map_); swap(x.acc_, y.acc_);

23.7.3.7 submdspan [mdspan.sub]

23.7.3.7.1 Overview [mdspan.sub.overview]

The submdspan facilities create a new mdspan viewing a subset of elements of an existing input mdspan.
The subset viewed by the created mdspan is determined by the SliceSpecifier arguments.
For each function defined in [mdspan.sub] that takes a parameter pack named slices as an argument:
  • let index_type be
    • M​::​index_type if the function is a member of a class M,
    • otherwise, remove_reference_t<decltype(src)>​::​index_type if the function has a parameter named src,
    • otherwise, the same type as the function's template argument IndexType;
  • let rank be the number of elements in slices;
  • let be the element of slices;
  • let be the type of ; and
  • let map-rank be an array<size_t, rank> such that for each k in the range [0, rank), map-rank[k] equals:

23.7.3.7.2 strided_slice [mdspan.sub.strided.slice]

strided_slice represents a set of extent regularly spaced integer indices.
The indices start at offset, and increase by increments of stride.
namespace std { template<class OffsetType, class ExtentType, class StrideType> struct strided_slice { using offset_type = OffsetType; using extent_type = ExtentType; using stride_type = StrideType; [[no_unique_address]] offset_type offset{}; [[no_unique_address]] extent_type extent{}; [[no_unique_address]] stride_type stride{}; }; }
strided_slice has the data members and special members specified above.
It has no base classes or members other than those specified.
Mandates: OffsetType, ExtentType, and StrideType are signed or unsigned integer types, or model integral-constant-like.
[Note 1: 
strided_slice{.offset = 1, .extent = 10, .stride = 3} indicates the indices 1, 4, 7, and 10.
Indices are selected from the half-open interval [1, 1 + 10).
— end note]

23.7.3.7.3 submdspan_mapping_result [mdspan.sub.map.result]

Specializations of submdspan_mapping_result are returned by overloads of submdspan_mapping.
namespace std { template<class LayoutMapping> struct submdspan_mapping_result { [[no_unique_address]] LayoutMapping mapping = LayoutMapping(); size_t offset{}; }; }
submdspan_mapping_result has the data members and special members specified above.
It has no base classes or members other than those specified.
LayoutMapping shall meet the layout mapping requirements ([mdspan.layout.policy.reqmts]).

23.7.3.7.4 Exposition-only helpers [mdspan.sub.helpers]

template<class T> constexpr T de-ice(T val) { return val; } template<integral-constant-like T> constexpr auto de-ice(T) { return T::value; } template<class IndexType, size_t k, class... SliceSpecifiers> constexpr IndexType first_(SliceSpecifiers... slices);
Mandates: IndexType is a signed or unsigned integer type.
Let denote the following value:
Preconditions: is representable as a value of type IndexType.
Returns: extents<IndexType>​::​index-cast().
template<size_t k, class Extents, class... SliceSpecifiers> constexpr auto last_(const Extents& src, SliceSpecifiers... slices);
Mandates: Extents is a specialization of extents.
Let index_type be typename Extents​::​index_type.
Let denote the following value:
  • de-ice() + 1 if models convertible_to<index_type>; otherwise
  • get<1>() if models index-pair-like<index_type>; otherwise
  • de-ice(.offset) + de-ice(.extent) if is a specialization of strided_slice; otherwise
  • src.extent(k).
Preconditions: is representable as a value of type index_type.
Returns: Extents​::​index-cast().
template<class IndexType, size_t N, class... SliceSpecifiers> constexpr array<IndexType, sizeof...(SliceSpecifiers)> src-indices(const array<IndexType, N>& indices, SliceSpecifiers... slices);
Mandates: IndexType is a signed or unsigned integer type.
Returns: An array<IndexType, sizeof...(SliceSpecifiers)> src_idx such that for each k in the range [0, sizeof...(SliceSpecifiers)), src_idx[k] equals
  • first_<IndexType, k>(slices...) for each k where map-rank[k] equals dynamic_extent,
  • otherwise, first_<IndexType, k>(slices...) + indices[map-rank[k]].

23.7.3.7.5 submdspan_extents function [mdspan.sub.extents]

template<class IndexType, class... Extents, class... SliceSpecifiers> constexpr auto submdspan_extents(const extents<IndexType, Extents...>& src, SliceSpecifiers... slices);
Constraints: sizeof...(slices) equals Extents​::​rank().
Mandates: For each rank index k of src.extents(), exactly one of the following is true:
Preconditions: For each rank index k of src.extents(), all of the following are true:
  • if is a specialization of strided_slice
  • 0  ≤ first_<IndexType, k>(slices...)  ≤ last_<k>(src, slices...)  ≤ src.extent(k)
Let SubExtents be a specialization of extents such that:
  • SubExtents​::​rank() equals the number of k such that does not model convertible_to<IndexType>; and
  • for each rank index k of Extents such that map-rank[k] != dynamic_extent is true, SubExtents​::​static_extent(map-rank[k]) equals:
    • Extents​::​static_extent(k) if is_convertible_v<, full_extent_t> is true; otherwise
    • de-ice(tuple_element_t<1, >()) - de-ice(tuple_element_t<0, >()) if models index-pair-like<IndexType>, and both tuple_element_t<0, > and tuple_element_t<1, > model integral-constant-like; otherwise
    • 0, if is a specialization of strided_slice, whose extent_type models integral-constant-like, for which extent_type() equals zero; otherwise
    • 1 + (de-ice(​::​extent_type()) - 1) / de-ice(​::​stride_type()), if is a specialization of strided_slice whose extent_type and stride_type model integral-constant-like;
    • otherwise, dynamic_extent.
Returns: A value ext of type SubExtents such that for each k for which map-rank[k] != dynamic_extent is true, ext.extent(map-rank[k]) equals:
  • .extent == 0 ? 0 : 1 + (de-ice(.extent) - 1) / de-ice(.stride) if is a specialization of strided_slice,
  • otherwise, last_<k>(src, slices...) - first_<IndexType, k>(slices...).

23.7.3.7.6 Specializations of submdspan_mapping [mdspan.sub.map]

23.7.3.7.6.1 Common [mdspan.sub.map.common]

The following elements apply to all functions in [mdspan.sub.map].
Constraints: sizeof...(slices) equals extents_type​::​rank().
Mandates: For each rank index k of extents(), exactly one of the following is true:
Preconditions: For each rank index k of extents(), all of the following are true:
  • if is a specialization of strided_slice, .extent is equal to zero or .stride is greater than zero; and
  • 0  ≤ first_<index_type, k>(slices...)
    0  ≤ last_<k>(extents(), slices...)
    0  ≤ extents().extent(k)
Let sub_ext be the result of submdspan_extents(extents(), slices...) and let SubExtents be decltype(sub_ext).
Let sub_strides be an array<SubExtents​::​index_type, SubExtents​::​rank()> such that for each rank index k of extents() for which map-rank[k] is not dynamic_extent, sub_strides[map-rank[k]] equals:
  • stride(k) * de-ice(.stride) if is a specialization of strided_slice and .stride < .extent is true;
  • otherwise, stride(k).
Let P be a parameter pack such that is_same_v<make_index_sequence<rank()>, index_sequence<P...>> is true.
If first_<index_type, k>(slices...) equals extents().extent(k) for any rank index k of extents(), then let offset be a value of type size_t equal to (*this).required_span_size().
Otherwise, let offset be a value of type size_t equal to (*this)(first_<index_type, P>(slices...)...).
Given a layout mapping type M, a type S is a unit-stride slice for M if

23.7.3.7.6.2 layout_left specialization of submdspan_mapping [mdspan.sub.map.left]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_left::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;
Returns:
  • submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if SubExtents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if
    • for each k in the range [0, SubExtents​::​rank() - 1)), is_convertible_v<, full_extent_t> is true; and
    • for k equal to SubExtents​::​rank() - 1, is a unit-stride slice for mapping;
    [Note 1: 
    If the above conditions are true, all with k larger than SubExtents​::​rank() - 1 are convertible to index_type.
    — end note]
  • otherwise, submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)), offset} if for a value u for which is the smallest value p larger than zero for which is a unit-stride slice for mapping, the following conditions are met:
    • is a unit-stride slice for mapping; and
    • for each k in the range [u + 1, u + SubExtents​::​rank() - 1), is_convertible_v<, full_extent_t> is true; and
    • for k equal to u + SubExtents​::​rank() - 1, is a unit-stride slice for mapping;
    and where S_static is:
    • dynamic_extent, if static_extent(k) is dynamic_extent for any k in the range [0, u + 1),
    • otherwise, the product of all values static_extent(k) for k in the range [0, u + 1);
  • otherwise, submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

23.7.3.7.6.3 layout_right specialization of submdspan_mapping [mdspan.sub.map.right]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_right::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;
Returns:
  • submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset}, if SubExtents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if
    • for each k in the range [rank_ - SubExtents​::​rank() + 1, rank_), is_convertible_v<, full_extent_t> is true; and
    • for k equal to _rank - SubExtents​::​rank(), is a unit-stride slice for mapping;
    [Note 1: 
    If the above conditions are true, all with are convertible to index_type.
    — end note]
  • otherwise, submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext, stride(rank_ - u - 2)), offset} if for a value u for which is the largest value p smaller than rank_ - 1 for which is a unit-stride slice for mapping, the following conditions are met:
    • for k equal to rank_ - 1, is a unit-stride slice for mapping; and
    • for each k in the range [rank_ - SubExtents​::​rank() - u + 1, rank_ - u - 1), is_convertible_v<, full_extent_t> is true; and
    • for k equal to rank_ - SubExtents​::​rank() - u,
      is a unit-stride slice for mapping;
    and where S_static is:
    • dynamic_extent, if static_extent(k) is dynamic_extent for any k in the range [rank_ - u - 1, rank_),
    • otherwise, the product of all values static_extent(k) for k in the range [rank_ - u - 1, rank_);
  • otherwise, submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

23.7.3.7.6.4 layout_stride specialization of submdspan_mapping [mdspan.sub.map.stride]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_stride::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;
Returns:
  • submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

23.7.3.7.6.5 layout_left_padded specialization of submdspan_mapping [mdspan.sub.map.leftpad]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_left_padded::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;
Returns:
  • submdspan_mapping_result{*this, 0}, if Extents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if rank_ == 1 is true or SubExtents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_left​::​mapping(sub_ext), offset}, if
    • SubExtents​::​rank() == 1 is true and
    • is a unit-stride slice for mapping;
  • otherwise, submdspan_mapping_result{layout_left_padded<S_static>::mapping(sub_ext, stride(u + 1)), offset} if for a value u for which u + 1 is the smallest value p larger than zero for which is a unit-stride slice for mapping, the following conditions are met:
    • is a unit-stride slice for mapping; and
    • for each k in the range [u + 1, u + SubExtents​::​rank() - 1), is_convertible_v<, full_extent_t> is true; and
    • for k equal to u + SubExtents​::​rank() - 1, is a unit-stride slice for mapping;
    where S_static is:
    • dynamic_extent, if static-padding-stride is dynamic_extent or static_extent(k) is dynamic_extent for any k in the range [1, u + 1),
    • otherwise, the product of static-padding-stride and all values static_extent(k) for k in the range [1, u + 1);
  • otherwise, submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

23.7.3.7.6.6 layout_right_padded specialization of submdspan_mapping [mdspan.sub.map.rightpad]

template<class Extents> template<class... SliceSpecifiers> constexpr auto layout_right_padded::mapping<Extents>::submdspan-mapping-impl( SliceSpecifiers... slices) const -> see below;
Returns:
  • submdspan_mapping_result{*this, 0}, if rank_ == 0 is true;
  • otherwise, submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset},
    if rank_ == 1 is true or SubExtents​::​rank() == 0 is true;
  • otherwise, submdspan_mapping_result{layout_right​::​mapping(sub_ext), offset}, if
    • SubExtents​::​rank() == 1 is true and
    • for k equal to rank_ - 1, is a unit-stride slice for mapping;
  • otherwise, submdspan_mapping_result{layout_right_padded<S_static>::mapping(sub_ext, stride(rank_ - u - 2)), offset} if for a value u for which rank_ - u - 2 is the largest value p smaller than rank_ - 1 for which is a unit-stride slice for mapping, the following conditions are met:
    • for k equal to rank_ - 1, is a unit-stride slice for mapping; and
    • for each k in the range [rank_ - SubExtents​::​rank() - u + 1, rank_ - u - 1)), is_convertible_v<, full_extent_t> is true; and
    • for k equal to rank_ - SubExtents​::​rank() - u,
      is a unit-stride slice for mapping;
    and where S_static is:
    • dynamic_extent if static-padding-stride is dynamic_extent or for any k in the range [rank_ - u - 1, rank_ - 1) static_extent(k) is dynamic_extent,
    • otherwise, the product of static-padding-stride and all values static_extent(k) with k in the range [rank_ - u - 1, rank_ - 1);
  • otherwise, submdspan_mapping_result{layout_stride::mapping(sub_ext, sub_strides), offset}

23.7.3.7.7 submdspan function template [mdspan.sub.sub]

template<class ElementType, class Extents, class LayoutPolicy, class AccessorPolicy, class... SliceSpecifiers> constexpr auto submdspan( const mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>& src, SliceSpecifiers... slices) -> see below;
Let index_type be typename Extents​::​index_type.
Let sub_map_offset be the result of submdspan_mapping(src.mapping(), slices...).
[Note 1: 
This invocation of submdspan_mapping selects a function call via overload resolution on a candidate set that includes the lookup set found by argument-dependent lookup ([basic.lookup.argdep]).
— end note]
Constraints:
  • sizeof...(slices) equals Extents​::​rank(), and
  • the expression submdspan_mapping(src.mapping(), slices...) is well-formed when treated as an unevaluated operand.
Mandates:
  • decltype(submdspan_mapping(src.mapping(), slices...)) is a specialization of submdspan_mapping_result.
  • is_same_v<remove_cvref_t<decltype(sub_map_offset.mapping.extents())>, decltype(submdspan_extents(src.mapping(), slices...))> is true.
  • For each rank index k of src.extents(), exactly one of the following is true:
Preconditions:
  • For each rank index k of src.extents(), all of the following are true:
    • if is a specialization of strided_slice
    • 0  ≤ first_<index_type, k>(slices...)  ≤ last_<k>(src.extents(), slices...)  ≤ src.extent(k)
  • sub_map_offset.mapping.extents() == submdspan_extents(src.mapping(), slices...) is true; and
  • for each integer pack I which is a multidimensional index in sub_map_offset.mapping.extents(), sub_map_offset.mapping(I...) + sub_map_offset.offset == src.mapping()(src-indices(array{I...}, slices...)) is true.
[Note 2: 
These conditions ensure that the mapping returned by submdspan_mapping matches the algorithmically expected index-mapping given the slice specifiers.
— end note]
Effects: Equivalent to: auto sub_map_result = submdspan_mapping(src.mapping(), slices...); return mdspan(src.accessor().offset(src.data(), sub_map_result.offset), sub_map_result.mapping, AccessorPolicy::offset_policy(src.accessor()));
[Example 1: 
Given a rank-3 mdspan grid3d representing a three-dimensional grid of regularly spaced points in a rectangular prism, the function zero_surface sets all elements on the surface of the 3-dimensional shape to zero.
It does so by reusing a function zero_2d that takes a rank-2 mdspan.
// zero out all elements in an mdspan template<class T, class E, class L, class A> void zero_2d(mdspan<T, E, L, A> a) { static_assert(a.rank() == 2); for (int i = 0; i < a.extent(0); i++) for (int j = 0; j < a.extent(1); j++) a[i, j] = 0; } // zero out just the surface template<class T, class E, class L, class A> void zero_surface(mdspan<T, E, L, A> grid3d) { static_assert(grid3d.rank() == 3); zero_2d(submdspan(grid3d, 0, full_extent, full_extent)); zero_2d(submdspan(grid3d, full_extent, 0, full_extent)); zero_2d(submdspan(grid3d, full_extent, full_extent, 0)); zero_2d(submdspan(grid3d, grid3d.extent(0) - 1, full_extent, full_extent)); zero_2d(submdspan(grid3d, full_extent, grid3d.extent(1) - 1, full_extent)); zero_2d(submdspan(grid3d, full_extent, full_extent, grid3d.extent(2) - 1)); } — end example]

24 Iterators library [iterators]

24.1 General [iterators.general]

This Clause describes components that C++ programs may use to perform iterations over containers ([containers]), streams ([iostream.format]), stream buffers ([stream.buffers]), and other ranges ([ranges]).
The following subclauses describe iterator requirements, and components for iterator primitives, predefined iterators, and stream iterators, as summarized in Table 71.
Table 71 — Iterators library summary [tab:iterators.summary]
Subclause
Header
Iterator requirements
<iterator>
Iterator primitives
Iterator adaptors
Stream iterators
Range access

24.2 Header <iterator> synopsis [iterator.synopsis]

#include <compare> // see [compare.syn] #include <concepts> // see [concepts.syn] namespace std { template<class T> using with-reference = T&; // exposition only template<class T> concept can-reference // exposition only = requires { typename with-reference<T>; }; template<class T> concept dereferenceable // exposition only = requires(T& t) { { *t } -> can-reference; // not required to be equality-preserving }; // [iterator.assoc.types], associated types // [incrementable.traits], incrementable traits template<class> struct incrementable_traits; // freestanding template<class T> using iter_difference_t = see below; // freestanding // [readable.traits], indirectly readable traits template<class> struct indirectly_readable_traits; // freestanding template<class T> using iter_value_t = see below; // freestanding // [iterator.traits], iterator traits template<class I> struct iterator_traits; // freestanding template<class T> requires is_object_v<T> struct iterator_traits<T*>; // freestanding template<dereferenceable T> using iter_reference_t = decltype(*declval<T&>()); // freestanding namespace ranges { // [iterator.cust], customization point objects inline namespace unspecified { // [iterator.cust.move], ranges​::​iter_move inline constexpr unspecified iter_move = unspecified; // freestanding // [iterator.cust.swap], ranges​::​iter_swap inline constexpr unspecified iter_swap = unspecified; // freestanding } } template<dereferenceable T> requires requires(T& t) { { ranges::iter_move(t) } -> can-reference; } using iter_rvalue_reference_t // freestanding = decltype(ranges::iter_move(declval<T&>())); // [iterator.concepts], iterator concepts // [iterator.concept.readable], concept indirectly_readable template<class In> concept indirectly_readable = see below; // freestanding // [indirectcallable.traits], indirect callable traits template<indirectly_readable T> using indirect-value-t = see below; // exposition only template<indirectly_readable T> using iter_common_reference_t = // freestanding common_reference_t<iter_reference_t<T>, indirect-value-t<T>>; // [iterator.concept.writable], concept indirectly_writable template<class Out, class T> concept indirectly_writable = see below; // freestanding // [iterator.concept.winc], concept weakly_incrementable template<class I> concept weakly_incrementable = see below; // freestanding // [iterator.concept.inc], concept incrementable template<class I> concept incrementable = see below; // freestanding // [iterator.concept.iterator], concept input_or_output_iterator template<class I> concept input_or_output_iterator = see below; // freestanding // [iterator.concept.sentinel], concept sentinel_for template<class S, class I> concept sentinel_for = see below; // freestanding // [iterator.concept.sizedsentinel], concept sized_sentinel_for template<class S, class I> constexpr bool disable_sized_sentinel_for = false; // freestanding template<class S, class I> concept sized_sentinel_for = see below; // freestanding // [iterator.concept.input], concept input_iterator template<class I> concept input_iterator = see below; // freestanding // [iterator.concept.output], concept output_iterator template<class I, class T> concept output_iterator = see below; // freestanding // [iterator.concept.forward], concept forward_iterator template<class I> concept forward_iterator = see below; // freestanding // [iterator.concept.bidir], concept bidirectional_iterator template<class I> concept bidirectional_iterator = see below; // freestanding // [iterator.concept.random.access], concept random_access_iterator template<class I> concept random_access_iterator = see below; // freestanding // [iterator.concept.contiguous], concept contiguous_iterator template<class I> concept contiguous_iterator = see below; // freestanding // [indirectcallable], indirect callable requirements // [indirectcallable.indirectinvocable], indirect callables template<class F, class I> concept indirectly_unary_invocable = see below; // freestanding template<class F, class I> concept indirectly_regular_unary_invocable = see below; // freestanding template<class F, class I> concept indirect_unary_predicate = see below; // freestanding template<class F, class I1, class I2> concept indirect_binary_predicate = see below; // freestanding template<class F, class I1, class I2 = I1> concept indirect_equivalence_relation = see below; // freestanding template<class F, class I1, class I2 = I1> concept indirect_strict_weak_order = see below; // freestanding template<class F, class... Is> requires (indirectly_readable<Is> && ...) && invocable<F, iter_reference_t<Is>...> using indirect_result_t = invoke_result_t<F, iter_reference_t<Is>...>; // freestanding // [projected], projected template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj> struct projected; // freestanding template<weakly_incrementable I, class Proj> struct incrementable_traits<projected<I, Proj>>; // freestanding template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj> using projected_value_t = // freestanding remove_cvref_t<invoke_result_t<Proj&, iter_value_t<I>&>>; // [alg.req], common algorithm requirements // [alg.req.ind.move], concept indirectly_movable template<class In, class Out> concept indirectly_movable = see below; // freestanding template<class In, class Out> concept indirectly_movable_storable = see below; // freestanding // [alg.req.ind.copy], concept indirectly_copyable template<class In, class Out> concept indirectly_copyable = see below; // freestanding template<class In, class Out> concept indirectly_copyable_storable = see below; // freestanding // [alg.req.ind.swap], concept indirectly_swappable template<class I1, class I2 = I1> concept indirectly_swappable = see below; // freestanding // [alg.req.ind.cmp], concept indirectly_comparable template<class I1, class I2, class R, class P1 = identity, class P2 = identity> concept indirectly_comparable = see below; // freestanding // [alg.req.permutable], concept permutable template<class I> concept permutable = see below; // freestanding // [alg.req.mergeable], concept mergeable template<class I1, class I2, class Out, class R = ranges::less, class P1 = identity, class P2 = identity> concept mergeable = see below; // freestanding // [alg.req.sortable], concept sortable template<class I, class R = ranges::less, class P = identity> concept sortable = see below; // freestanding // [iterator.primitives], primitives // [std.iterator.tags], iterator tags struct input_iterator_tag { }; // freestanding struct output_iterator_tag { }; // freestanding struct forward_iterator_tag: public input_iterator_tag { }; // freestanding struct bidirectional_iterator_tag: public forward_iterator_tag { }; // freestanding struct random_access_iterator_tag: public bidirectional_iterator_tag { }; // freestanding struct contiguous_iterator_tag: public random_access_iterator_tag { }; // freestanding // [iterator.operations], iterator operations template<class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n); // freestanding template<class InputIterator> constexpr typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last); // freestanding template<class InputIterator> constexpr InputIterator next(InputIterator x, // freestanding typename iterator_traits<InputIterator>::difference_type n = 1); template<class BidirectionalIterator> constexpr BidirectionalIterator prev(BidirectionalIterator x, // freestanding typename iterator_traits<BidirectionalIterator>::difference_type n = 1); // [range.iter.ops], range iterator operations namespace ranges { // [range.iter.op.advance], ranges​::​advance template<input_or_output_iterator I> constexpr void advance(I& i, iter_difference_t<I> n); // freestanding template<input_or_output_iterator I, sentinel_for<I> S> constexpr void advance(I& i, S bound); // freestanding template<input_or_output_iterator I, sentinel_for<I> S> constexpr iter_difference_t<I> advance(I& i, iter_difference_t<I> n, // freestanding S bound); // [range.iter.op.distance], ranges​::​distance template<class I, sentinel_for<I> S> requires (!sized_sentinel_for<S, I>) constexpr iter_difference_t<I> distance(I first, S last); // freestanding template<class I, sized_sentinel_for<decay_t<I>> S> constexpr iter_difference_t<decay_t<I>> distance(I&& first, S last); // freestanding template<range R> constexpr range_difference_t<R> distance(R&& r); // freestanding // [range.iter.op.next], ranges​::​next template<input_or_output_iterator I> constexpr I next(I x); // freestanding template<input_or_output_iterator I> constexpr I next(I x, iter_difference_t<I> n); // freestanding template<input_or_output_iterator I, sentinel_for<I> S> constexpr I next(I x, S bound); // freestanding template<input_or_output_iterator I, sentinel_for<I> S> constexpr I next(I x, iter_difference_t<I> n, S bound); // freestanding // [range.iter.op.prev], ranges​::​prev template<bidirectional_iterator I> constexpr I prev(I x); // freestanding template<bidirectional_iterator I> constexpr I prev(I x, iter_difference_t<I> n); // freestanding template<bidirectional_iterator I> constexpr I prev(I x, iter_difference_t<I> n, I bound); // freestanding } // [predef.iterators], predefined iterators and sentinels // [reverse.iterators], reverse iterators template<class Iterator> class reverse_iterator; // freestanding template<class Iterator1, class Iterator2> constexpr bool operator==( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator!=( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<=( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>=( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y); template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const reverse_iterator<Iterator1>& x, // freestanding const reverse_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr auto operator-( // freestanding const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base()); template<class Iterator> constexpr reverse_iterator<Iterator> operator+( // freestanding iter_difference_t<Iterator> n, const reverse_iterator<Iterator>& x); template<class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i); // freestanding template<class Iterator1, class Iterator2> requires (!sized_sentinel_for<Iterator1, Iterator2>) constexpr bool disable_sized_sentinel_for<reverse_iterator<Iterator1>, // freestanding reverse_iterator<Iterator2>> = true; // [insert.iterators], insert iterators template<class Container> class back_insert_iterator; // freestanding template<class Container> constexpr back_insert_iterator<Container> back_inserter(Container& x); // freestanding template<class Container> class front_insert_iterator; // freestanding template<class Container> constexpr front_insert_iterator<Container> front_inserter(Container& x); // freestanding template<class Container> class insert_iterator; // freestanding template<class Container> constexpr insert_iterator<Container> inserter(Container& x, ranges::iterator_t<Container> i); // freestanding // [const.iterators], constant iterators and sentinels // [const.iterators.alias], alias templates template<indirectly_readable I> using iter_const_reference_t = see below; // freestanding template<class Iterator> concept constant-iterator = see below; // exposition only template<input_iterator I> using const_iterator = see below; // freestanding template<semiregular S> using const_sentinel = see below; // freestanding // [const.iterators.iterator], class template basic_const_iterator template<input_iterator Iterator> class basic_const_iterator; // freestanding template<class T, common_with<T> U> requires input_iterator<common_type_t<T, U>> struct common_type<basic_const_iterator<T>, U> { // freestanding using type = basic_const_iterator<common_type_t<T, U>>; }; template<class T, common_with<T> U> requires input_iterator<common_type_t<T, U>> struct common_type<U, basic_const_iterator<T>> { // freestanding using type = basic_const_iterator<common_type_t<T, U>>; }; template<class T, common_with<T> U> requires input_iterator<common_type_t<T, U>> struct common_type<basic_const_iterator<T>, basic_const_iterator<U>> { // freestanding using type = basic_const_iterator<common_type_t<T, U>>; }; template<input_iterator I> constexpr const_iterator<I> make_const_iterator(I it) { return it; } // freestanding template<semiregular S> constexpr const_sentinel<S> make_const_sentinel(S s) { return s; } // freestanding // [move.iterators], move iterators and sentinels template<class Iterator> class move_iterator; // freestanding template<class Iterator1, class Iterator2> constexpr bool operator==( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator<=( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr bool operator>=( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const move_iterator<Iterator1>& x, // freestanding const move_iterator<Iterator2>& y); template<class Iterator1, class Iterator2> constexpr auto operator-( // freestanding const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); template<class Iterator> constexpr move_iterator<Iterator> operator+(iter_difference_t<Iterator> n, const move_iterator<Iterator>& x); // freestanding template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i); // freestanding template<class Iterator1, class Iterator2> requires (!sized_sentinel_for<Iterator1, Iterator2>) constexpr bool disable_sized_sentinel_for<move_iterator<Iterator1>, // freestanding move_iterator<Iterator2>> = true; template<semiregular S> class move_sentinel; // freestanding // [iterators.common], common iterators template<input_or_output_iterator I, sentinel_for<I> S> requires (!same_as<I, S> && copyable<I>) class common_iterator; // freestanding template<class I, class S> struct incrementable_traits<common_iterator<I, S>>; // freestanding template<input_iterator I, class S> struct iterator_traits<common_iterator<I, S>>; // freestanding // [default.sentinel], default sentinel struct default_sentinel_t; // freestanding inline constexpr default_sentinel_t default_sentinel{}; // freestanding // [iterators.counted], counted iterators template<input_or_output_iterator I> class counted_iterator; // freestanding template<input_iterator I> requires see below struct iterator_traits<counted_iterator<I>>; // freestanding // [unreachable.sentinel], unreachable sentinel struct unreachable_sentinel_t; // freestanding inline constexpr unreachable_sentinel_t unreachable_sentinel{}; // freestanding // [stream.iterators], stream iterators template<class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> class istream_iterator; template<class T, class charT, class traits, class Distance> bool operator==(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y); template<class T, class charT = char, class traits = char_traits<charT>> class ostream_iterator; template<class charT, class traits = char_traits<charT>> class istreambuf_iterator; template<class charT, class traits> bool operator==(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b); template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator; // [iterator.range], range access template<class C> constexpr auto begin(C& c) -> decltype(c.begin()); // freestanding template<class C> constexpr auto begin(const C& c) -> decltype(c.begin()); // freestanding template<class C> constexpr auto end(C& c) -> decltype(c.end()); // freestanding template<class C> constexpr auto end(const C& c) -> decltype(c.end()); // freestanding template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept; // freestanding template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept; // freestanding template<class C> constexpr auto cbegin(const C& c) // freestanding noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c)); template<class C> constexpr auto cend(const C& c) // freestanding noexcept(noexcept(std::end(c))) -> decltype(std::end(c)); template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin()); // freestanding template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin()); // freestanding template<class C> constexpr auto rend(C& c) -> decltype(c.rend()); // freestanding template<class C> constexpr auto rend(const C& c) -> decltype(c.rend()); // freestanding template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]) // freestanding template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]); // freestanding template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il); // freestanding template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il); // freestanding template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c)); // freestanding template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c)); // freestanding template<class C> constexpr auto size(const C& c) -> decltype(c.size()); // freestanding template<class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept; // freestanding template<class C> constexpr auto ssize(const C& c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>; // freestanding template<class T, ptrdiff_t N> constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept; // freestanding template<class C> constexpr auto empty(const C& c) -> decltype(c.empty()); // freestanding template<class T, size_t N> constexpr bool empty(const T (&array)[N]) noexcept; // freestanding template<class E> constexpr bool empty(initializer_list<E> il) noexcept; // freestanding template<class C> constexpr auto data(C& c) -> decltype(c.data()); // freestanding template<class C> constexpr auto data(const C& c) -> decltype(c.data()); // freestanding template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept; // freestanding template<class E> constexpr const E* data(initializer_list<E> il) noexcept; // freestanding }

24.3 Iterator requirements [iterator.requirements]

24.3.1 General [iterator.requirements.general]

Iterators are a generalization of pointers that allow a C++ program to work with different data structures (for example, containers and ranges) in a uniform manner.
To be able to construct template algorithms that work correctly and efficiently on different types of data structures, the library formalizes not just the interfaces but also the semantics and complexity assumptions of iterators.
An input iterator i supports the expression *i, resulting in a value of some object type T, called the value type of the iterator.
An output iterator i has a non-empty set of types that are writable to the iterator; for each such type T, the expression *i = o is valid where o is a value of type T.
For every iterator type X, there is a corresponding signed integer-like type ([iterator.concept.winc]) called the difference type of the iterator.
Since iterators are an abstraction of pointers, their semantics are a generalization of most of the semantics of pointers in C++.
This ensures that every function template that takes iterators works as well with regular pointers.
This document defines six categories of iterators, according to the operations defined on them: input iterators, output iterators, forward iterators, bidirectional iterators, random access iterators, and contiguous iterators, as shown in Table 72.
Table 72 — Relations among iterator categories [tab:iterators.relations]
Contiguous
Random Access
Bidirectional
Forward
Input
Output
Forward iterators meet all the requirements of input iterators and can be used whenever an input iterator is specified; Bidirectional iterators also meet all the requirements of forward iterators and can be used whenever a forward iterator is specified; Random access iterators also meet all the requirements of bidirectional iterators and can be used whenever a bidirectional iterator is specified; Contiguous iterators also meet all the requirements of random access iterators and can be used whenever a random access iterator is specified.
Iterators that further meet the requirements of output iterators are called mutable iterators.
Nonmutable iterators are referred to as constant iterators.
In addition to the requirements in this subclause, the nested typedef-names specified in [iterator.traits] shall be provided for the iterator type.
[Note 1: 
Either the iterator type must provide the typedef-names directly (in which case iterator_traits pick them up automatically), or an iterator_traits specialization must provide them.
— end note]
Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence.
Such a value is called a past-the-end value.
Values of an iterator i for which the expression *i is defined are called dereferenceable.
The library never assumes that past-the-end values are dereferenceable.
Iterators can also have singular values that are not associated with any sequence.
Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that meet the Cpp17DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation.
[Note 2: 
This guarantee is not offered for default-initialization, although the distinction only matters for types with trivial default constructors such as pointers or aggregates holding pointers.
— end note]
In these cases the singular value is overwritten the same way as any other value.
Dereferenceable values are always non-singular.
Most of the library's algorithmic templates that operate on data structures have interfaces that use ranges.
A range is an iterator and a sentinel that designate the beginning and end of the computation, or an iterator and a count that designate the beginning and the number of elements to which the computation is to be applied.201
An iterator and a sentinel denoting a range are comparable.
A range [i, s) is empty if i == s; otherwise, [i, s) refers to the elements in the data structure starting with the element pointed to by i and up to but not including the element, if any, pointed to by the first iterator j such that j == s.
A sentinel s is called reachable from an iterator i if and only if there is a finite sequence of applications of the expression ++i that makes i == s.
If s is reachable from i, [i, s) denotes a valid range.
A counted range is empty if n == 0; otherwise, refers to the n elements in the data structure starting with the element pointed to by i and up to but not including the element, if any, pointed to by the result of n applications of ++i.
A counted range is valid if and only if n == 0; or n is positive, i is dereferenceable, and is valid.
The result of the application of library functions to invalid ranges is undefined.
All the categories of iterators require only those functions that are realizable for a given category in constant time (amortized).
Therefore, requirement tables and concept definitions for the iterators do not specify complexity.
Destruction of an iterator may invalidate pointers and references previously obtained from that iterator if its type does not meet the Cpp17ForwardIterator requirements and does not model forward_iterator.
An invalid iterator is an iterator that may be singular.202
Iterators meet the constexpr iterators requirements if all operations provided to meet iterator category requirements are constexpr functions.
[Note 3: 
For example, the types “pointer to int” and reverse_iterator<int*> meet the constexpr iterator requirements.
— end note]
201)201)
The sentinel denoting the end of a range can have the same type as the iterator denoting the beginning of the range, or a different type.
202)202)
This definition applies to pointers, since pointers are iterators.
The effect of dereferencing an iterator that has been invalidated is undefined.

24.3.2 Associated types [iterator.assoc.types]

24.3.2.1 Incrementable traits [incrementable.traits]

To implement algorithms only in terms of incrementable types, it is often necessary to determine the difference type that corresponds to a particular incrementable type.
Accordingly, it is required that if WI is the name of a type that models the weakly_incrementable concept ([iterator.concept.winc]), the type iter_difference_t<WI> be defined as the incrementable type's difference type.
namespace std { template<class> struct incrementable_traits { }; template<class T> requires is_object_v<T> struct incrementable_traits<T*> { using difference_type = ptrdiff_t; }; template<class I> struct incrementable_traits<const I> : incrementable_traits<I> { }; template<class T> requires requires { typename T::difference_type; } struct incrementable_traits<T> { using difference_type = typename T::difference_type; }; template<class T> requires (!requires { typename T::difference_type; } && requires(const T& a, const T& b) { { a - b } -> integral; }) struct incrementable_traits<T> { using difference_type = make_signed_t<decltype(declval<T>() - declval<T>())>; }; template<class T> using iter_difference_t = see below; }
Let be remove_cvref_t<I>.
The type iter_difference_t<I> denotes
  • incrementable_traits<>​::​difference_type if iterator_traits<> names a specialization generated from the primary template, and
  • iterator_traits<>​::​difference_type otherwise.
Users may specialize incrementable_traits on program-defined types.

24.3.2.2 Indirectly readable traits [readable.traits]

To implement algorithms only in terms of indirectly readable types, it is often necessary to determine the value type that corresponds to a particular indirectly readable type.
Accordingly, it is required that if R is the name of a type that models the indirectly_readable concept ([iterator.concept.readable]), the type iter_value_t<R> be defined as the indirectly readable type's value type.
template<class> struct cond-value-type { }; // exposition only template<class T> requires is_object_v<T> struct cond-value-type<T> { using value_type = remove_cv_t<T>; }; template<class T> concept has-member-value-type = requires { typename T::value_type; }; // exposition only template<class T> concept has-member-element-type = requires { typename T::element_type; }; // exposition only template<class> struct indirectly_readable_traits { }; template<class T> struct indirectly_readable_traits<T*> : cond-value-type<T> { }; template<class I> requires is_array_v<I> struct indirectly_readable_traits<I> { using value_type = remove_cv_t<remove_extent_t<I>>; }; template<class I> struct indirectly_readable_traits<const I> : indirectly_readable_traits<I> { }; template<has-member-value-type T> struct indirectly_readable_traits<T> : cond-value-type<typename T::value_type> { }; template<has-member-element-type T> struct indirectly_readable_traits<T> : cond-value-type<typename T::element_type> { }; template<has-member-value-type T> requires has-member-element-type<T> struct indirectly_readable_traits<T> { }; template<has-member-value-type T> requires has-member-element-type<T> && same_as<remove_cv_t<typename T::element_type>, remove_cv_t<typename T::value_type>> struct indirectly_readable_traits<T> : cond-value-type<typename T::value_type> { }; template<class T> using iter_value_t = see below;
Let be remove_cvref_t<I>.
The type iter_value_t<I> denotes
  • indirectly_readable_traits<>​::​value_type if iterator_traits<> names a specialization generated from the primary template, and
  • iterator_traits<>​::​value_type otherwise.
Class template indirectly_readable_traits may be specialized on program-defined types.
[Note 1: 
Some legacy output iterators define a nested type named value_type that is an alias for void.
These types are not indirectly_readable and have no associated value types.
— end note]
[Note 2: 
Smart pointers like shared_ptr<int> are indirectly_readable and have an associated value type, but a smart pointer like shared_ptr<void> is not indirectly_readable and has no associated value type.
— end note]

24.3.2.3 Iterator traits [iterator.traits]

To implement algorithms only in terms of iterators, it is sometimes necessary to determine the iterator category that corresponds to a particular iterator type.
Accordingly, it is required that if I is the type of an iterator, the type iterator_traits<I>::iterator_category be defined as the iterator's iterator category.
In addition, the types iterator_traits<I>::pointer iterator_traits<I>::reference shall be defined as the iterator's pointer and reference types; that is, for an iterator object a of class type, the same type as decltype(a.operator->()) and decltype(*a), respectively.
The type iterator_traits<I>​::​pointer shall be void for an iterator of class type I that does not support operator->.
Additionally, in the case of an output iterator, the types iterator_traits<I>::value_type iterator_traits<I>::difference_type iterator_traits<I>::reference may be defined as void.
The definitions in this subclause make use of the following exposition-only concepts: template<class I> concept cpp17-iterator = requires(I i) { { *i } -> can-reference; { ++i } -> same_as<I&>; { *i++ } -> can-reference; } && copyable<I>; template<class I> concept cpp17-input-iterator = cpp17-iterator<I> && equality_comparable<I> && requires(I i) { typename incrementable_traits<I>::difference_type; typename indirectly_readable_traits<I>::value_type; typename common_reference_t<iter_reference_t<I>&&, typename indirectly_readable_traits<I>::value_type&>; typename common_reference_t<decltype(*i++)&&, typename indirectly_readable_traits<I>::value_type&>; requires signed_integral<typename incrementable_traits<I>::difference_type>; }; template<class I> concept cpp17-forward-iterator = cpp17-input-iterator<I> && constructible_from<I> && is_reference_v<iter_reference_t<I>> && same_as<remove_cvref_t<iter_reference_t<I>>, typename indirectly_readable_traits<I>::value_type> && requires(I i) { { i++ } -> convertible_to<const I&>; { *i++ } -> same_as<iter_reference_t<I>>; }; template<class I> concept cpp17-bidirectional-iterator = cpp17-forward-iterator<I> && requires(I i) { { --i } -> same_as<I&>; { i-- } -> convertible_to<const I&>; { *i-- } -> same_as<iter_reference_t<I>>; }; template<class I> concept cpp17-random-access-iterator = cpp17-bidirectional-iterator<I> && totally_ordered<I> && requires(I i, typename incrementable_traits<I>::difference_type n) { { i += n } -> same_as<I&>; { i -= n } -> same_as<I&>; { i + n } -> same_as<I>; { n + i } -> same_as<I>; { i - n } -> same_as<I>; { i - i } -> same_as<decltype(n)>; { i[n] } -> convertible_to<iter_reference_t<I>>; };
The members of a specialization iterator_traits<I> generated from the iterator_traits primary template are computed as follows:
  • If I has valid ([temp.deduct]) member types difference_type, value_type, reference, and iterator_category, then iterator_traits<I> has the following publicly accessible members: using iterator_category = typename I::iterator_category; using value_type = typename I::value_type; using difference_type = typename I::difference_type; using pointer = see below; using reference = typename I::reference;
    If the qualified-id I​::​pointer is valid and denotes a type, then iterator_traits<I>​::​pointer names that type; otherwise, it names void.
  • Otherwise, if I satisfies the exposition-only concept cpp17-input-iterator, iterator_traits<I> has the following publicly accessible members: using iterator_category = see below; using value_type = typename indirectly_readable_traits<I>::value_type; using difference_type = typename incrementable_traits<I>::difference_type; using pointer = see below; using reference = see below;
  • Otherwise, if I satisfies the exposition-only concept cpp17-iterator, then iterator_traits<I> has the following publicly accessible members: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = see below; using pointer = void; using reference = void;
    If the qualified-id incrementable_traits<I>​::​difference_type is valid and denotes a type, then difference_type names that type; otherwise, it names void.
  • Otherwise, iterator_traits<I> has no members by any of the above names.
Explicit or partial specializations of iterator_traits may have a member type iterator_concept that is used to indicate conformance to the iterator concepts ([iterator.concepts]).
[Example 1: 
To indicate conformance to the input_iterator concept but a lack of conformance to the Cpp17InputIterator requirements ([input.iterators]), an iterator_traits specialization might have iterator_concept denote input_iterator_tag but not define iterator_category.
— end example]
iterator_traits is specialized for pointers as namespace std { template<class T> requires is_object_v<T> struct iterator_traits<T*> { using iterator_concept = contiguous_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = remove_cv_t<T>; using difference_type = ptrdiff_t; using pointer = T*; using reference = T&; }; }
[Example 2: 
To implement a generic reverse function, a C++ program can do the following: template<class BI> void reverse(BI first, BI last) { typename iterator_traits<BI>::difference_type n = distance(first, last); --n; while(n > 0) { typename iterator_traits<BI>::value_type tmp = *first; *first++ = *--last; *last = tmp; n -= 2; } }
— end example]

24.3.3 Customization point objects [iterator.cust]

24.3.3.1 ranges​::​iter_move [iterator.cust.move]

The name ranges​::​iter_move denotes a customization point object ([customization.point.object]).
The expression ranges​::​iter_move(E) for a subexpression E is expression-equivalent to:
  • iter_move(E), if E has class or enumeration type and iter_move(E) is a well-formed expression when treated as an unevaluated operand, where the meaning of iter_move is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]).
  • Otherwise, if the expression *E is well-formed:
  • Otherwise, ranges​::​iter_move(E) is ill-formed.
    [Note 1: 
    This case can result in substitution failure when ranges​::​iter_move(E) appears in the immediate context of a template instantiation.
    — end note]
If ranges​::​iter_move(E) is not equal to *E, the program is ill-formed, no diagnostic required.

24.3.3.2 ranges​::​iter_swap [iterator.cust.swap]

The name ranges​::​iter_swap denotes a customization point object ([customization.point.object]) that exchanges the values ([concept.swappable]) denoted by its arguments.
Let iter-exchange-move be the exposition-only function template:
template<class X, class Y> constexpr iter_value_t<X> iter-exchange-move(X&& x, Y&& y) noexcept(noexcept(iter_value_t<X>(iter_move(x))) && noexcept(*x = iter_move(y)));
Effects: Equivalent to: iter_value_t<X> old_value(iter_move(x)); *x = iter_move(y); return old_value;
The expression ranges​::​iter_swap(E1, E2) for subexpressions E1 and E2 is expression-equivalent to:
  • (void)iter_swap(E1, E2), if either E1 or E2 has class or enumeration type and iter_swap(E1, E2) is a well-formed expression with overload resolution performed in a context that includes the declaration template<class I1, class I2> void iter_swap(I1, I2) = delete; and does not include a declaration of ranges​::​iter_swap.
    If the function selected by overload resolution does not exchange the values denoted by E1 and E2, the program is ill-formed, no diagnostic required.
    [Note 1: 
    This precludes calling unconstrained std​::​iter_swap.
    When the deleted overload is viable, program-defined overloads need to be more specialized ([temp.func.order]) to be selected.
    — end note]
  • Otherwise, if the types of E1 and E2 each model indirectly_readable, and if the reference types of E1 and E2 model swappable_with ([concept.swappable]), then ranges​::​swap(*E1, *E2).
  • Otherwise, if the types T1 and T2 of E1 and E2 model indirectly_movable_storable<T1, T2> and indirectly_movable_storable<T2, T1>, then (void)(*E1 = iter-exchange-move(E2, E1)), except that E1 is evaluated only once.
  • Otherwise, ranges​::​iter_swap(E1, E2) is ill-formed.
    [Note 2: 
    This case can result in substitution failure when ranges​::​iter_swap(E1, E2) appears in the immediate context of a template instantiation.
    — end note]

24.3.4 Iterator concepts [iterator.concepts]

24.3.4.1 General [iterator.concepts.general]

For a type I, let ITER_TRAITS(I) denote the type I if iterator_traits<I> names a specialization generated from the primary template.
Otherwise, ITER_TRAITS(I) denotes iterator_traits<I>.
  • If the qualified-id ITER_TRAITS(I)​::​iterator_concept is valid and names a type, then ITER_CONCEPT(I) denotes that type.
  • Otherwise, if the qualified-id ITER_TRAITS(I)​::​iterator_category is valid and names a type, then ITER_CONCEPT(I) denotes that type.
  • Otherwise, if iterator_traits<I> names a specialization generated from the primary template, then ITER_CONCEPT(I) denotes random_access_iterator_tag.
  • Otherwise, ITER_CONCEPT(I) does not denote a type.
[Note 1: 
ITER_TRAITS enables independent syntactic determination of an iterator's category and concept.
— end note]
[Example 1: 
struct I { using value_type = int; using difference_type = int; int operator*() const; I& operator++(); I operator++(int); I& operator--(); I operator--(int); bool operator==(I) const; }; iterator_traits<I>​::​iterator_category denotes input_iterator_tag, and ITER_CONCEPT(I) denotes random_access_iterator_tag.
— end example]

24.3.4.2 Concept indirectly_readable [iterator.concept.readable]

Types that are indirectly readable by applying operator* model the indirectly_readable concept, including pointers, smart pointers, and iterators.
template<class In> concept indirectly-readable-impl = // exposition only requires(const In in) { typename iter_value_t<In>; typename iter_reference_t<In>; typename iter_rvalue_reference_t<In>; { *in } -> same_as<iter_reference_t<In>>; { ranges::iter_move(in) } -> same_as<iter_rvalue_reference_t<In>>; } && common_reference_with<iter_reference_t<In>&&, iter_value_t<In>&> && common_reference_with<iter_reference_t<In>&&, iter_rvalue_reference_t<In>&&> && common_reference_with<iter_rvalue_reference_t<In>&&, const iter_value_t<In>&>;
template<class In> concept indirectly_readable = indirectly-readable-impl<remove_cvref_t<In>>;
Given a value i of type I, I models indirectly_readable only if the expression *i is equality-preserving.

24.3.4.3 Concept indirectly_writable [iterator.concept.writable]

The indirectly_writable concept specifies the requirements for writing a value into an iterator's referenced object.
template<class Out, class T> concept indirectly_writable = requires(Out&& o, T&& t) { *o = std::forward<T>(t); // not required to be equality-preserving *std::forward<Out>(o) = std::forward<T>(t); // not required to be equality-preserving const_cast<const iter_reference_t<Out>&&>(*o) = std::forward<T>(t); // not required to be equality-preserving const_cast<const iter_reference_t<Out>&&>(*std::forward<Out>(o)) = std::forward<T>(t); // not required to be equality-preserving };
Let E be an expression such that decltype((E)) is T, and let o be a dereferenceable object of type Out.
Out and T model indirectly_writable<Out, T> only if:
  • If Out and T model indirectly_readable<Out> && same_as<iter_value_t<Out>, decay_t<T>>, then *o after any above assignment is equal to the value of E before the assignment.
After evaluating any above assignment expression, o is not required to be dereferenceable.
If E is an xvalue ([basic.lval]), the resulting state of the object it denotes is valid but unspecified ([lib.types.movedfrom]).
[Note 1: 
The only valid use of an operator* is on the left side of the assignment statement.
Assignment through the same value of the indirectly writable type happens only once.
— end note]
[Note 2: 
indirectly_writable has the awkward const_cast expressions to reject iterators with prvalue non-proxy reference types that permit rvalue assignment but do not also permit const rvalue assignment.
Consequently, an iterator type I that returns std​::​string by value does not model indirectly_writable<I, std​::​string>.
— end note]

24.3.4.4 Concept weakly_incrementable [iterator.concept.winc]

The weakly_incrementable concept specifies the requirements on types that can be incremented with the pre- and post-increment operators.
The increment operations are not required to be equality-preserving, nor is the type required to be equality_comparable.
template<class T> constexpr bool is-integer-like = see below; // exposition only template<class T> constexpr bool is-signed-integer-like = see below; // exposition only template<class I> concept weakly_incrementable = movable<I> && requires(I i) { typename iter_difference_t<I>; requires is-signed-integer-like<iter_difference_t<I>>; { ++i } -> same_as<I&>; // not required to be equality-preserving i++; // not required to be equality-preserving };
A type I is an integer-class type if it is in a set of implementation-defined types that behave as integer types do, as defined below.
[Note 1: 
An integer-class type is not necessarily a class type.
— end note]
The range of representable values of an integer-class type is the continuous set of values over which it is defined.
For any integer-class type, its range of representable values is either to (inclusive) for some integer N, in which case it is a signed-integer-class type, or 0 to (inclusive) for some integer N, in which case it is an unsigned-integer-class type.
In both cases, N is called the width of the integer-class type.
The width of an integer-class type is greater than that of every integral type of the same signedness.
A type I other than cv bool is integer-like if it models integral<I> or if it is an integer-class type.
An integer-like type I is signed-integer-like if it models signed_integral<I> or if it is a signed-integer-class type.
An integer-like type I is unsigned-integer-like if it models unsigned_integral<I> or if it is an unsigned-integer-class type.
For every integer-class type I, let B(I) be a unique hypothetical extended integer type of the same signedness with the same width ([basic.fundamental]) as I.
[Note 2: 
The corresponding hypothetical specialization numeric_limits<B(I)> meets the requirements on numeric_limits specializations for integral types ([numeric.limits]).
— end note]
For every integral type J, let B(J) be the same type as J.
Expressions of integer-class type are explicitly convertible to any integer-like type, and implicitly convertible to any integer-class type of equal or greater width and the same signedness.
Expressions of integral type are both implicitly and explicitly convertible to any integer-class type.
Conversions between integral and integer-class types and between two integer-class types do not exit via an exception.
The result of such a conversion is the unique value of the destination type that is congruent to the source modulo , where N is the width of the destination type.
Let a be an object of integer-class type I, let b be an object of integer-like type I2 such that the expression b is implicitly convertible to I, let x and y be, respectively, objects of type B(I) and B(I2) as described above that represent the same values as a and b, and let c be an lvalue of any integral type.
  • The expressions a++ and a-- shall be prvalues of type I whose values are equal to that of a prior to the evaluation of the expressions.
    The expression a++ shall modify the value of a by adding 1 to it.
    The expression a-- shall modify the value of a by subtracting 1 from it.
  • The expressions ++a, --a, and &a shall be expression-equivalent to a += 1, a -= 1, and addressof(a), respectively.
  • For every unary-operator @ other than & for which the expression @x is well-formed, @a shall also be well-formed and have the same value, effects, and value category as @x.
    If @x has type bool, so too does @a; if @x has type B(I), then @a has type I.
  • For every assignment operator @= for which c @= x is well-formed, c @= a shall also be well-formed and shall have the same value and effects as c @= x.
    The expression c @= a shall be an lvalue referring to c.
  • For every assignment operator @= for which x @= y is well-formed, a @= b shall also be well-formed and shall have the same effects as x @= y, except that the value that would be stored into x is stored into a.
    The expression a @= b shall be an lvalue referring to a.
  • For every non-assignment binary operator @ for which x @ y and y @ x are well-formed, a @ b and b @ a shall also be well-formed and shall have the same value, effects, and value category as x @ y and y @ x, respectively.
    If x @ y or y @ x has type B(I), then a @ b or b @ a, respectively, has type I; if x @ y or y @ x has type B(I2), then a @ b or b @ a, respectively, has type I2; if x @ y or y @ x has any other type, then a @ b or b @ a, respectively, has that type.
An expression E of integer-class type I is contextually convertible to bool as if by bool(E != I(0)).
All integer-class types model regular ([concepts.object]) and three_way_comparable<strong_ordering> ([cmp.concept]).
A value-initialized object of integer-class type has value 0.
For every (possibly cv-qualified) integer-class type I, numeric_limits<I> is specialized such that each static data member m has the same value as numeric_limits<B(I)>​::​m, and each static member function f returns I(numeric_limits<B(I)>​::​f()).
For any two integer-like types I1 and I2, at least one of which is an integer-class type, common_type_t<I1, I2> denotes an integer-class type whose width is not less than that of I1 or I2.
If both I1 and I2 are signed-integer-like types, then common_type_t<I1, I2> is also a signed-integer-like type.
is-integer-like<I> is true if and only if I is an integer-like type.
is-signed-integer-like<I> is true if and only if I is a signed-integer-like type.
Let i be an object of type I.
When i is in the domain of both pre- and post-increment, i is said to be incrementable.
I models weakly_incrementable<I> only if:
  • The expressions ++i and i++ have the same domain.
  • If i is incrementable, then both ++i and i++ advance i to the next element.
  • If i is incrementable, then addressof(++i) is equal to addressof(i).
Recommended practice: The implementation of an algorithm on a weakly incrementable type should never attempt to pass through the same incrementable value twice; such an algorithm should be a single-pass algorithm.
[Note 3: 
For weakly_incrementable types, a equals b does not imply that ++a equals ++b.
(Equality does not guarantee the substitution property or referential transparency.)
Such algorithms can be used with istreams as the source of the input data through the istream_iterator class template.
— end note]

24.3.4.5 Concept incrementable [iterator.concept.inc]

The incrementable concept specifies requirements on types that can be incremented with the pre- and post-increment operators.
The increment operations are required to be equality-preserving, and the type is required to be equality_comparable.
[Note 1: 
This supersedes the annotations on the increment expressions in the definition of weakly_incrementable.
— end note]
template<class I> concept incrementable = regular<I> && weakly_incrementable<I> && requires(I i) { { i++ } -> same_as<I>; };
Let a and b be incrementable objects of type I.
I models incrementable only if:
  • If bool(a == b) then bool(a++ == b).
  • If bool(a == b) then bool(((void)a++, a) == ++b).
[Note 2: 
The requirement that a equals b implies ++a equals ++b (which is not true for weakly incrementable types) allows the use of multi-pass one-directional algorithms with types that model incrementable.
— end note]

24.3.4.6 Concept input_or_output_iterator [iterator.concept.iterator]

The input_or_output_iterator concept forms the basis of the iterator concept taxonomy; every iterator models input_or_output_iterator.
This concept specifies operations for dereferencing and incrementing an iterator.
Most algorithms will require additional operations to compare iterators with sentinels ([iterator.concept.sentinel]), to read ([iterator.concept.input]) or write ([iterator.concept.output]) values, or to provide a richer set of iterator movements ([iterator.concept.forward], [iterator.concept.bidir], [iterator.concept.random.access]).
template<class I> concept input_or_output_iterator = requires(I i) { { *i } -> can-reference; } && weakly_incrementable<I>;
[Note 1: 
Unlike the Cpp17Iterator requirements, the input_or_output_iterator concept does not require copyability.
— end note]

24.3.4.7 Concept sentinel_for [iterator.concept.sentinel]

The sentinel_for concept specifies the relationship between an input_or_output_iterator type and a semiregular type whose values denote a range.
Let s and i be values of type S and I such that [i, s) denotes a range.
Types S and I model sentinel_for<S, I> only if:
  • i == s is well-defined.
  • If bool(i != s) then i is dereferenceable and [++i, s) denotes a range.
  • assignable_from<I&, S> is either modeled or not satisfied.
The domain of == is not static.
Given an iterator i and sentinel s such that [i, s) denotes a range and i != s, i and s are not required to continue to denote a range after incrementing any other iterator equal to i.
Consequently, i == s is no longer required to be well-defined.

24.3.4.8 Concept sized_sentinel_for [iterator.concept.sizedsentinel]

The sized_sentinel_for concept specifies requirements on an input_or_output_iterator type I and a corresponding sentinel_for<I> that allow the use of the - operator to compute the distance between them in constant time.
template<class S, class I> concept sized_sentinel_for = sentinel_for<S, I> && !disable_sized_sentinel_for<remove_cv_t<S>, remove_cv_t<I>> && requires(const I& i, const S& s) { { s - i } -> same_as<iter_difference_t<I>>; { i - s } -> same_as<iter_difference_t<I>>; };
Let i be an iterator of type I, and s a sentinel of type S such that [i, s) denotes a range.
Let N be the smallest number of applications of ++i necessary to make bool(i == s) be true.
S and I model sized_sentinel_for<S, I> only if:
  • If N is representable by iter_difference_t<I>, then s - i is well-defined and equals N.
  • If is representable by iter_difference_t<I>, then i - s is well-defined and equals .
template<class S, class I> constexpr bool disable_sized_sentinel_for = false;
Remarks: Pursuant to [namespace.std], users may specialize disable_sized_sentinel_for for cv-unqualified non-array object types S and I if S and/or I is a program-defined type.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.
[Note 1: 
disable_sized_sentinel_for allows use of sentinels and iterators with the library that satisfy but do not in fact model sized_sentinel_for.
— end note]
[Example 1: 
The sized_sentinel_for concept is modeled by pairs of random_access_iterators ([iterator.concept.random.access]) and by counted iterators and their sentinels ([counted.iterator]).
— end example]

24.3.4.9 Concept input_iterator [iterator.concept.input]

The input_iterator concept defines requirements for a type whose referenced values can be read (from the requirement for indirectly_readable ([iterator.concept.readable])) and which can be both pre- and post-incremented.
[Note 1: 
Unlike the Cpp17InputIterator requirements ([input.iterators]), the input_iterator concept does not need equality comparison since iterators are typically compared to sentinels.
— end note]
template<class I> concept input_iterator = input_or_output_iterator<I> && indirectly_readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;

24.3.4.10 Concept output_iterator [iterator.concept.output]

The output_iterator concept defines requirements for a type that can be used to write values (from the requirement for indirectly_writable ([iterator.concept.writable])) and which can be both pre- and post-incremented.
[Note 1: 
Output iterators are not required to model equality_comparable.
— end note]
template<class I, class T> concept output_iterator = input_or_output_iterator<I> && indirectly_writable<I, T> && requires(I i, T&& t) { *i++ = std::forward<T>(t); // not required to be equality-preserving };
Let E be an expression such that decltype((E)) is T, and let i be a dereferenceable object of type I.
I and T model output_iterator<I, T> only if *i++ = E; has effects equivalent to: *i = E; ++i;
Recommended practice: The implementation of an algorithm on output iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single-pass algorithm.

24.3.4.11 Concept forward_iterator [iterator.concept.forward]

The forward_iterator concept adds copyability, equality comparison, and the multi-pass guarantee, specified below.
template<class I> concept forward_iterator = input_iterator<I> && derived_from<ITER_CONCEPT(I), forward_iterator_tag> && incrementable<I> && sentinel_for<I, I>;
The domain of == for forward iterators is that of iterators over the same underlying sequence.
However, value-initialized iterators of the same type may be compared and shall compare equal to other value-initialized iterators of the same type.
[Note 1: 
Value-initialized iterators behave as if they refer past the end of the same empty sequence.
— end note]
Pointers and references obtained from a forward iterator into a range [i, s) shall remain valid while [i, s) continues to denote a range.
Two dereferenceable iterators a and b of type X offer the multi-pass guarantee if
  • a == b implies ++a == ++b and
  • the expression ((void)[](X x){++x;}(a), *a) is equivalent to the expression *a.
[Note 2: 
The requirement that a == b implies ++a == ++b and the removal of the restrictions on the number of assignments through a mutable iterator (which applies to output iterators) allow the use of multi-pass one-directional algorithms with forward iterators.
— end note]

24.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]

The bidirectional_iterator concept adds the ability to move an iterator backward as well as forward.
template<class I> concept bidirectional_iterator = forward_iterator<I> && derived_from<ITER_CONCEPT(I), bidirectional_iterator_tag> && requires(I i) { { --i } -> same_as<I&>; { i-- } -> same_as<I>; };
A bidirectional iterator r is decrementable if and only if there exists some q such that ++q == r.
Decrementable iterators r shall be in the domain of the expressions --r and r--.
Let a and b be equal objects of type I.
I models bidirectional_iterator only if:
  • If a and b are decrementable, then all of the following are true:
    • addressof(--a) == addressof(a)
    • bool(a-- == b)
    • after evaluating both a-- and --b, bool(a == b) is still true
    • bool(++(--a) == b)
  • If a and b are incrementable, then bool(--(++a) == b).

24.3.4.13 Concept random_access_iterator [iterator.concept.random.access]

The random_access_iterator concept adds support for constant-time advancement with +=, +, -=, and -, as well as the computation of distance in constant time with -.
Random access iterators also support array notation via subscripting.
template<class I> concept random_access_iterator = bidirectional_iterator<I> && derived_from<ITER_CONCEPT(I), random_access_iterator_tag> && totally_ordered<I> && sized_sentinel_for<I, I> && requires(I i, const I j, const iter_difference_t<I> n) { { i += n } -> same_as<I&>; { j + n } -> same_as<I>; { n + j } -> same_as<I>; { i -= n } -> same_as<I&>; { j - n } -> same_as<I>; { j[n] } -> same_as<iter_reference_t<I>>; };
Let a and b be valid iterators of type I such that b is reachable from a after n applications of ++a, let D be iter_difference_t<I>, and let n denote a value of type D.
I models random_access_iterator only if:
  • (a += n) is equal to b.
  • addressof(a += n) is equal to addressof(a).
  • (a + n) is equal to (a += n).
  • For any two positive values x and y of type D, if (a + D(x + y)) is valid, then (a + D(x + y)) is equal to ((a + x) + y).
  • (a + D(0)) is equal to a.
  • If (a + D(n - 1)) is valid, then (a + n) is equal to [](I c){ return ++c; }(a + D(n - 1)).
  • (b += D(-n)) is equal to a.
  • (b -= n) is equal to a.
  • addressof(b -= n) is equal to addressof(b).
  • (b - n) is equal to (b -= n).
  • If b is dereferenceable, then a[n] is valid and is equal to *b.
  • bool(a <= b) is true.

24.3.4.14 Concept contiguous_iterator [iterator.concept.contiguous]

The contiguous_iterator concept provides a guarantee that the denoted elements are stored contiguously in memory.
template<class I> concept contiguous_iterator = random_access_iterator<I> && derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> && is_lvalue_reference_v<iter_reference_t<I>> && same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> && requires(const I& i) { { to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>; };
Let a and b be dereferenceable iterators and c be a non-dereferenceable iterator of type I such that b is reachable from a and c is reachable from b, and let D be iter_difference_t<I>.
The type I models contiguous_iterator only if
  • to_address(a) == addressof(*a),
  • to_address(b) == to_address(a) + D(b - a),
  • to_address(c) == to_address(a) + D(c - a),
  • to_address(I{}) is well-defined,
  • ranges​::​iter_move(a) has the same type, value category, and effects as std​::​move(*a), and
  • if ranges​::​iter_swap(a, b) is well-formed, it has effects equivalent to ranges​::​swap(*a, *b).

24.3.5 C++17 iterator requirements [iterator.cpp17]

24.3.5.1 General [iterator.cpp17.general]

In the following sections, a and b denote values of type X or const X, difference_type and reference refer to the types iterator_traits<X>​::​difference_type and iterator_traits<X>​::​reference, respectively, n denotes a value of difference_type, u, tmp, and m denote identifiers, r denotes a value of X&, t denotes a value of value type T, o denotes a value of some type that is writable to the output iterator.
[Note 1: 
For an iterator type X there must be an instantiation of iterator_traits<X> ([iterator.traits]).
— end note]

24.3.5.2 Cpp17Iterator [iterator.iterators]

The Cpp17Iterator requirements form the basis of the iterator taxonomy; every iterator meets the Cpp17Iterator requirements.
This set of requirements specifies operations for dereferencing and incrementing an iterator.
Most algorithms will require additional operations to read ([input.iterators]) or write ([output.iterators]) values, or to provide a richer set of iterator movements ([forward.iterators], [bidirectional.iterators], [random.access.iterators]).
A type X meets the Cpp17Iterator requirements if
Table 73Cpp17Iterator requirements [tab:iterator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
*r
unspecified
Preconditions: r is dereferenceable.
++r
X&

24.3.5.3 Input iterators [input.iterators]

A class or pointer type X meets the requirements of an input iterator for the value type T if X meets the Cpp17Iterator ([iterator.iterators]) and Cpp17EqualityComparable (Table 28) requirements and the expressions in Table 74 are valid and have the indicated semantics.
In Table 74, the term the domain of == is used in the ordinary mathematical sense to denote the set of values over which == is (required to be) defined.
This set can change over time.
Each algorithm places additional requirements on the domain of == for the iterator values it uses.
These requirements can be inferred from the uses that algorithm makes of == and !=.
[Example 1: 
The call find(a,b,x) is defined only if the value of a has the property p defined as follows: b has property p and a value i has property p if (*i==x) or if (*i!=x and ++i has property p).
— end example]
Table 74Cpp17InputIterator requirements (in addition to Cpp17Iterator) [tab:inputiterator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
a != b
decltype(a != b) models boolean-testable
!(a == b)
Preconditions: (a, b) is in the domain of ==.
*a
reference, convertible to T
Preconditions: a is dereferenceable.

The expression
(void)*a, *a is equivalent to *a.

If a == b and (a, b) is in the domain of == then *a is equivalent to *b.
a->m
(*a).m
Preconditions: a is dereferenceable.
++r
X&
Preconditions: r is dereferenceable.

Postconditions: r is dereferenceable or r is past-the-end;
any copies of the previous value of r are no longer required to be dereferenceable nor to be in the domain of ==.
(void)r++
equivalent to (void)++r
*r++
convertible to T
{ T tmp = *r;
++r;
return tmp; }
Recommended practice: 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.
[Note 1: 
For input iterators, a == b does not imply ++a == ++b.
(Equality does not guarantee the substitution property or referential transparency.)
Value type T is not required to be a Cpp17CopyAssignable type (Table 34).
Such an algorithm can be used with istreams as the source of the input data through the istream_iterator class template.
— end note]

24.3.5.4 Output iterators [output.iterators]

A class or pointer type X meets the requirements of an output iterator if X meets the Cpp17Iterator requirements ([iterator.iterators]) and the expressions in Table 75 are valid and have the indicated semantics.
Table 75Cpp17OutputIterator requirements (in addition to Cpp17Iterator) [tab:outputiterator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
*r = o
result is not used
Remarks: After this operation r is not required to be dereferenceable.

Postconditions: r is incrementable.
++r
X&
addressof(r) == addressof(++r).

Remarks: After this operation r is not required to be dereferenceable.

Postconditions: r is incrementable.
r++
convertible to const X&
{ X tmp = r;
++r;
return tmp; }
Remarks: After this operation r is not required to be dereferenceable.

Postconditions: r is incrementable.
*r++ = o
result is not used
Remarks: After this operation r is not required to be dereferenceable.

Postconditions: r is incrementable.
Recommended practice: The implementation of an algorithm on output iterators should never attempt to pass through the same iterator twice; such an algorithm should be a single-pass algorithm.
[Note 1: 
The only valid use of an operator* is on the left side of the assignment statement.
Assignment through the same value of the iterator happens only once.
Equality and inequality are not necessarily defined.
— end note]

24.3.5.5 Forward iterators [forward.iterators]

A class or pointer type X meets the Cpp17ForwardIterator requirements if
  • X meets the Cpp17InputIterator requirements ([input.iterators]),
  • X meets the Cpp17DefaultConstructible requirements ([utility.arg.requirements]),
  • if X is a mutable iterator, reference is a reference to T; if X is a constant iterator, reference is a reference to const T,
  • the expressions in Table 76 are valid and have the indicated semantics, and
  • objects of type X offer the multi-pass guarantee, described below.
The domain of == for forward iterators is that of iterators over the same underlying sequence.
However, value-initialized iterators may be compared and shall compare equal to other value-initialized iterators of the same type.
[Note 1: 
Value-initialized iterators behave as if they refer past the end of the same empty sequence.
— end note]
Two dereferenceable iterators a and b of type X offer the multi-pass guarantee if
  • a == b implies ++a == ++b and
  • X is a pointer type or the expression (void)++X(a), *a is equivalent to the expression *a.
[Note 2: 
The requirement that a == b implies ++a == ++b (which is not true for input and output iterators) and the removal of the restrictions on the number of the assignments through a mutable iterator (which applies to output iterators) allows the use of multi-pass one-directional algorithms with forward iterators.
— end note]
Table 76Cpp17ForwardIterator requirements (in addition to Cpp17InputIterator) [tab:forwarditerator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
r++
convertible to const X&
{ X tmp = r;
++r;
return tmp; }
*r++
reference
If a and b are equal, then either a and b are both dereferenceable or else neither is dereferenceable.
If a and b are both dereferenceable, then a == b if and only if *a and *b are bound to the same object.

24.3.5.6 Bidirectional iterators [bidirectional.iterators]

A class or pointer type X meets the requirements of a bidirectional iterator if, in addition to meeting the Cpp17ForwardIterator requirements, the following expressions are valid as shown in Table 77.
Table 77Cpp17BidirectionalIterator requirements (in addition to Cpp17ForwardIterator) [tab:bidirectionaliterator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
--r
X&
Preconditions: there exists s such that r == ++s.

Postconditions: r is dereferenceable.

--(++r) == r.

--r == --s implies r == s.

addressof(r) == addressof(--r).
r--
convertible to const X&
{ X tmp = r;
--r;
return tmp; }
*r--
reference
[Note 1: 
Bidirectional iterators allow algorithms to move iterators backward as well as forward.
— end note]

24.3.5.7 Random access iterators [random.access.iterators]

A class or pointer type X meets the requirements of a random access iterator if, in addition to meeting the Cpp17BidirectionalIterator requirements, the following expressions are valid as shown in Table 78.
Table 78Cpp17RandomAccessIterator requirements (in addition to Cpp17BidirectionalIterator) [tab:randomaccessiterator]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
r += n
X&
{ difference_type m = n;
if (m >= 0)
while (m--)
++r;
else
while (m++)
--r;
return r; }
a + n
n + a
X
{ X tmp = a;
return tmp += n; }
a + n == n + a.
r -= n
X&
return r += -n;
Preconditions: the absolute value of n is in the range of representable values of difference_type.
a - n
X
{ X tmp = a;
return tmp -= n; }
b - a
difference_type
return n;
Preconditions: there exists a value n of type difference_type such that a + n == b.

b == a + (b - a).
a[n]
convertible to reference
*(a + n)
a < b
decltype(a < b) models boolean-testable
Effects: Equivalent to: return b - a > 0;
< is a total ordering relation
a > b
decltype(a > b) models boolean-testable
b < a
> is a total ordering relation opposite to <.
a >= b
decltype(a >= b) models boolean-testable
!(a < b)
a <= b
decltype(a <= b) models boolean-testable
!(a > b)

24.3.6 Indirect callable requirements [indirectcallable]

24.3.6.1 General [indirectcallable.general]

There are several concepts that group requirements of algorithms that take callable objects ([func.def]) as arguments.

24.3.6.2 Indirect callable traits [indirectcallable.traits]

To implement algorithms taking projections, it is necessary to determine the projected type of an iterator's value type.
For the exposition-only alias template indirect-value-t, indirect-value-t<T> denotes
  • invoke_result_t<Proj&, indirect-value-t<I>> if T names projected<I, Proj>, and
  • iter_value_t<T>& otherwise.

24.3.6.3 Indirect callables [indirectcallable.indirectinvocable]

The indirect callable concepts are used to constrain those algorithms that accept callable objects ([func.def]) as arguments.
namespace std { template<class F, class I> concept indirectly_unary_invocable = indirectly_readable<I> && copy_constructible<F> && invocable<F&, indirect-value-t<I>> && invocable<F&, iter_reference_t<I>> && common_reference_with< invoke_result_t<F&, indirect-value-t<I>>, invoke_result_t<F&, iter_reference_t<I>>>; template<class F, class I> concept indirectly_regular_unary_invocable = indirectly_readable<I> && copy_constructible<F> && regular_invocable<F&, indirect-value-t<I>> && regular_invocable<F&, iter_reference_t<I>> && common_reference_with< invoke_result_t<F&, indirect-value-t<I>>, invoke_result_t<F&, iter_reference_t<I>>>; template<class F, class I> concept indirect_unary_predicate = indirectly_readable<I> && copy_constructible<F> && predicate<F&, indirect-value-t<I>> && predicate<F&, iter_reference_t<I>>; template<class F, class I1, class I2> concept indirect_binary_predicate = indirectly_readable<I1> && indirectly_readable<I2> && copy_constructible<F> && predicate<F&, indirect-value-t<I1>, indirect-value-t<I2>> && predicate<F&, indirect-value-t<I1>, iter_reference_t<I2>> && predicate<F&, iter_reference_t<I1>, indirect-value-t<I2>> && predicate<F&, iter_reference_t<I1>, iter_reference_t<I2>>; template<class F, class I1, class I2 = I1> concept indirect_equivalence_relation = indirectly_readable<I1> && indirectly_readable<I2> && copy_constructible<F> && equivalence_relation<F&, indirect-value-t<I1>, indirect-value-t<I2>> && equivalence_relation<F&, indirect-value-t<I1>, iter_reference_t<I2>> && equivalence_relation<F&, iter_reference_t<I1>, indirect-value-t<I2>> && equivalence_relation<F&, iter_reference_t<I1>, iter_reference_t<I2>>; template<class F, class I1, class I2 = I1> concept indirect_strict_weak_order = indirectly_readable<I1> && indirectly_readable<I2> && copy_constructible<F> && strict_weak_order<F&, indirect-value-t<I1>, indirect-value-t<I2>> && strict_weak_order<F&, indirect-value-t<I1>, iter_reference_t<I2>> && strict_weak_order<F&, iter_reference_t<I1>, indirect-value-t<I2>> && strict_weak_order<F&, iter_reference_t<I1>, iter_reference_t<I2>>; }

24.3.6.4 Class template projected [projected]

Class template projected is used to constrain algorithms that accept callable objects and projections ([defns.projection]).
It combines an indirectly_readable type I and a callable object type Proj into a new indirectly_readable type whose reference type is the result of applying Proj to the iter_reference_t of I.
namespace std { template<class I, class Proj> struct projected-impl { // exposition only struct type { // exposition only using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>; using difference_type = iter_difference_t<I>; // present only if I // models weakly_incrementable indirect_result_t<Proj&, I> operator*() const; // not defined }; }; template<indirectly_readable I, indirectly_regular_unary_invocable<I> Proj> using projected = projected-impl<I, Proj>::type; }

24.3.7 Common algorithm requirements [alg.req]

24.3.7.1 General [alg.req.general]

There are several additional iterator concepts that are commonly applied to families of algorithms.
These group together iterator requirements of algorithm families.
There are three relational concepts that specify how element values are transferred between indirectly_readable and indirectly_writable types: indirectly_movable, indirectly_copyable, and indirectly_swappable.
There are three relational concepts for rearrangements: permutable, mergeable, and sortable.
There is one relational concept for comparing values from different sequences: indirectly_comparable.
[Note 1: 
The ranges​::​less function object type used in the concepts below imposes constraints on the concepts' arguments in addition to those that appear in the concepts' bodies ([range.cmp]).
— end note]

24.3.7.2 Concept indirectly_movable [alg.req.ind.move]

The indirectly_movable concept specifies the relationship between an indirectly_readable type and an indirectly_writable type between which values may be moved.
template<class In, class Out> concept indirectly_movable = indirectly_readable<In> && indirectly_writable<Out, iter_rvalue_reference_t<In>>;
The indirectly_movable_storable concept augments indirectly_movable with additional requirements enabling the transfer to be performed through an intermediate object of the indirectly_readable type's value type.
template<class In, class Out> concept indirectly_movable_storable = indirectly_movable<In, Out> && indirectly_writable<Out, iter_value_t<In>> && movable<iter_value_t<In>> && constructible_from<iter_value_t<In>, iter_rvalue_reference_t<In>> && assignable_from<iter_value_t<In>&, iter_rvalue_reference_t<In>>;
Let i be a dereferenceable value of type In.
In and Out model indirectly_movable_storable<In, Out> only if after the initialization of the object obj in iter_value_t<In> obj(ranges::iter_move(i)); obj is equal to the value previously denoted by *i.
If iter_rvalue_reference_t<In> is an rvalue reference type, the resulting state of the value denoted by *i is valid but unspecified ([lib.types.movedfrom]).

24.3.7.3 Concept indirectly_copyable [alg.req.ind.copy]

The indirectly_copyable concept specifies the relationship between an indirectly_readable type and an indirectly_writable type between which values may be copied.
template<class In, class Out> concept indirectly_copyable = indirectly_readable<In> && indirectly_writable<Out, iter_reference_t<In>>;
The indirectly_copyable_storable concept augments indirectly_copyable with additional requirements enabling the transfer to be performed through an intermediate object of the indirectly_readable type's value type.
It also requires the capability to make copies of values.
template<class In, class Out> concept indirectly_copyable_storable = indirectly_copyable<In, Out> && indirectly_writable<Out, iter_value_t<In>&> && indirectly_writable<Out, const iter_value_t<In>&> && indirectly_writable<Out, iter_value_t<In>&&> && indirectly_writable<Out, const iter_value_t<In>&&> && copyable<iter_value_t<In>> && constructible_from<iter_value_t<In>, iter_reference_t<In>> && assignable_from<iter_value_t<In>&, iter_reference_t<In>>;
Let i be a dereferenceable value of type In.
In and Out model indirectly_copyable_storable<In, Out> only if after the initialization of the object obj in iter_value_t<In> obj(*i); obj is equal to the value previously denoted by *i.
If iter_reference_t<In> is an rvalue reference type, the resulting state of the value denoted by *i is valid but unspecified ([lib.types.movedfrom]).

24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]

The indirectly_swappable concept specifies a swappable relationship between the values referenced by two indirectly_readable types.
template<class I1, class I2 = I1> concept indirectly_swappable = indirectly_readable<I1> && indirectly_readable<I2> && requires(const I1 i1, const I2 i2) { ranges::iter_swap(i1, i1); ranges::iter_swap(i2, i2); ranges::iter_swap(i1, i2); ranges::iter_swap(i2, i1); };

24.3.7.5 Concept indirectly_comparable [alg.req.ind.cmp]

The indirectly_comparable concept specifies the common requirements of algorithms that compare values from two different sequences.
template<class I1, class I2, class R, class P1 = identity, class P2 = identity> concept indirectly_comparable = indirect_binary_predicate<R, projected<I1, P1>, projected<I2, P2>>;

24.3.7.6 Concept permutable [alg.req.permutable]

The permutable concept specifies the common requirements of algorithms that reorder elements in place by moving or swapping them.
template<class I> concept permutable = forward_iterator<I> && indirectly_movable_storable<I, I> && indirectly_swappable<I, I>;

24.3.7.7 Concept mergeable [alg.req.mergeable]

The mergeable concept specifies the requirements of algorithms that merge sorted sequences into an output sequence by copying elements.
template<class I1, class I2, class Out, class R = ranges::less, class P1 = identity, class P2 = identity> concept mergeable = input_iterator<I1> && input_iterator<I2> && weakly_incrementable<Out> && indirectly_copyable<I1, Out> && indirectly_copyable<I2, Out> && indirect_strict_weak_order<R, projected<I1, P1>, projected<I2, P2>>;

24.3.7.8 Concept sortable [alg.req.sortable]

The sortable concept specifies the common requirements of algorithms that permute sequences into ordered sequences (e.g., sort).
template<class I, class R = ranges::less, class P = identity> concept sortable = permutable<I> && indirect_strict_weak_order<R, projected<I, P>>;

24.4 Iterator primitives [iterator.primitives]

24.4.1 General [iterator.primitives.general]

To simplify the use of iterators, the library provides several classes and functions.

24.4.2 Standard iterator tags [std.iterator.tags]

It is often desirable for a function template specialization to find out what is the most specific category of its iterator argument, so that the function can select the most efficient algorithm at compile time.
To facilitate this, the library introduces category tag classes which are used as compile time tags for algorithm selection.
They are: output_iterator_tag, input_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag, and contiguous_iterator_tag.
For every iterator of type I, iterator_traits<I>​::​iterator_category shall be defined to be a category tag that describes the iterator's behavior.
Additionally, iterator_traits<I>​::​iterator_concept may be used to indicate conformance to the iterator concepts ([iterator.concepts]).
namespace std { struct output_iterator_tag { }; struct input_iterator_tag { }; struct forward_iterator_tag: public input_iterator_tag { }; struct bidirectional_iterator_tag: public forward_iterator_tag { }; struct random_access_iterator_tag: public bidirectional_iterator_tag { }; struct contiguous_iterator_tag: public random_access_iterator_tag { }; }
[Example 1: 
A program-defined iterator BinaryTreeIterator can be included into the bidirectional iterator category by specializing the iterator_traits template: template<class T> struct iterator_traits<BinaryTreeIterator<T>> { using iterator_category = bidirectional_iterator_tag; using difference_type = ptrdiff_t; using value_type = T; using pointer = T*; using reference = T&; };
— end example]
[Example 2: 
If evolve() is well-defined for bidirectional iterators, but can be implemented more efficiently for random access iterators, then the implementation is as follows: template<class BidirectionalIterator> inline void evolve(BidirectionalIterator first, BidirectionalIterator last) { evolve(first, last, typename iterator_traits<BidirectionalIterator>::iterator_category()); } template<class BidirectionalIterator> void evolve(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag) { // more generic, but less efficient algorithm } template<class RandomAccessIterator> void evolve(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) { // more efficient, but less generic algorithm }
— end example]

24.4.3 Iterator operations [iterator.operations]

Since only random access iterators provide + and - operators, the library provides two function templates advance and distance.
These function templates use + and - for random access iterators (and are, therefore, constant time for them); for input, forward and bidirectional iterators they use ++ to provide linear time implementations.
template<class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n);
Preconditions: n is negative only for bidirectional iterators.
Effects: Increments i by n if n is non-negative, and decrements i by -n otherwise.
template<class InputIterator> constexpr typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);
Preconditions: last is reachable from first, or InputIterator meets the Cpp17RandomAccessIterator requirements and first is reachable from last.
Effects: If InputIterator meets the Cpp17RandomAccessIterator requirements, returns (last - first); otherwise, increments first until last is reached and returns the number of increments.
template<class InputIterator> constexpr InputIterator next(InputIterator x, typename iterator_traits<InputIterator>::difference_type n = 1);
Effects: Equivalent to: advance(x, n); return x;
template<class BidirectionalIterator> constexpr BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
Effects: Equivalent to: advance(x, -n); return x;

24.4.4 Range iterator operations [range.iter.ops]

24.4.4.1 General [range.iter.ops.general]

The library includes the function templates ranges​::​advance, ranges​::​distance, ranges​::​next, and ranges​::​prev to manipulate iterators.
These operations adapt to the set of operators provided by each iterator category to provide the most efficient implementation possible for a concrete iterator type.
[Example 1: 
ranges​::​advance uses the + operator to move a random_access_iterator forward n steps in constant time.
For an iterator type that does not model random_access_iterator, ranges​::​advance instead performs n individual increments with the ++ operator.
— end example]
The entities defined in [range.iter.ops] are algorithm function objects ([alg.func.obj]).

24.4.4.2 ranges​::​advance [range.iter.op.advance]

template<input_or_output_iterator I> constexpr void ranges::advance(I& i, iter_difference_t<I> n);
Preconditions: If I does not model bidirectional_iterator, n is not negative.
Effects:
template<input_or_output_iterator I, sentinel_for<I> S> constexpr void ranges::advance(I& i, S bound);
Preconditions: Either assignable_from<I&, S> || sized_sentinel_for<S, I> is modeled, or [i, bound) denotes a range.
Effects:
  • If I and S model assignable_from<I&, S>, equivalent to i = std​::​move(bound).
  • Otherwise, if S and I model sized_sentinel_for<S, I>, equivalent to ranges​::​advance(i, bound - i).
  • Otherwise, while bool(i != bound) is true, increments i.
template<input_or_output_iterator I, sentinel_for<I> S> constexpr iter_difference_t<I> ranges::advance(I& i, iter_difference_t<I> n, S bound);
Preconditions: If n > 0, [i, bound) denotes a range.
If n == 0, [i, bound) or [bound, i) denotes a range.
If n < 0, [bound, i) denotes a range, I models bidirectional_iterator, and I and S model same_as<I, S>.
Effects:
  • If S and I model sized_sentinel_for<S, I>:
    • If ​|n|  ≥ |bound - i|, equivalent to ranges​::​advance(i, bound).
    • Otherwise, equivalent to ranges​::​advance(i, n).
  • Otherwise,
    • if n is non-negative, while bool(i != bound) is true, increments i but at most n times.
    • Otherwise, while bool(i != bound) is true, decrements i but at most -n times.
Returns: n - M, where M is the difference between the ending and starting positions of i.

24.4.4.3 ranges​::​distance [range.iter.op.distance]

template<class I, sentinel_for<I> S> requires (!sized_sentinel_for<S, I>) constexpr iter_difference_t<I> ranges::distance(I first, S last);
Preconditions: [first, last) denotes a range.
Effects: Increments first until last is reached and returns the number of increments.
template<class I, sized_sentinel_for<decay_t<I>> S> constexpr iter_difference_t<decay_t<I>> ranges::distance(I&& first, S last);
Effects: Equivalent to: return last - static_cast<const decay_t<I>&>(first);
template<range R> constexpr range_difference_t<R> ranges::distance(R&& r);
Effects: If R models sized_range, equivalent to: return static_cast<range_difference_t<R>>(ranges::size(r)); // [range.prim.size]
Otherwise, equivalent to: return ranges::distance(ranges::begin(r), ranges::end(r)); // [range.access]

24.4.4.4 ranges​::​next [range.iter.op.next]

template<input_or_output_iterator I> constexpr I ranges::next(I x);
Effects: Equivalent to: ++x; return x;
template<input_or_output_iterator I> constexpr I ranges::next(I x, iter_difference_t<I> n);
Effects: Equivalent to: ranges​::​advance(x, n); return x;
template<input_or_output_iterator I, sentinel_for<I> S> constexpr I ranges::next(I x, S bound);
Effects: Equivalent to: ranges​::​advance(x, bound); return x;
template<input_or_output_iterator I, sentinel_for<I> S> constexpr I ranges::next(I x, iter_difference_t<I> n, S bound);
Effects: Equivalent to: ranges​::​advance(x, n, bound); return x;

24.4.4.5 ranges​::​prev [range.iter.op.prev]

template<bidirectional_iterator I> constexpr I ranges::prev(I x);
Effects: Equivalent to: --x; return x;
template<bidirectional_iterator I> constexpr I ranges::prev(I x, iter_difference_t<I> n);
Effects: Equivalent to: ranges​::​advance(x, -n); return x;
template<bidirectional_iterator I> constexpr I ranges::prev(I x, iter_difference_t<I> n, I bound);
Effects: Equivalent to: ranges​::​advance(x, -n, bound); return x;

24.5 Iterator adaptors [predef.iterators]

24.5.1 Reverse iterators [reverse.iterators]

24.5.1.1 General [reverse.iterators.general]

Class template reverse_iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence.

24.5.1.2 Class template reverse_iterator [reverse.iterator]

namespace std { template<class Iterator> class reverse_iterator { public: using iterator_type = Iterator; using iterator_concept = see below; using iterator_category = see below; using value_type = iter_value_t<Iterator>; using difference_type = iter_difference_t<Iterator>; using pointer = typename iterator_traits<Iterator>::pointer; using reference = iter_reference_t<Iterator>; constexpr reverse_iterator(); constexpr explicit reverse_iterator(Iterator x); template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u); template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u); constexpr Iterator base() const; constexpr reference operator*() const; constexpr pointer operator->() const requires see below; constexpr reverse_iterator& operator++(); constexpr reverse_iterator operator++(int); constexpr reverse_iterator& operator--(); constexpr reverse_iterator operator--(int); constexpr reverse_iterator operator+ (difference_type n) const; constexpr reverse_iterator& operator+=(difference_type n); constexpr reverse_iterator operator- (difference_type n) const; constexpr reverse_iterator& operator-=(difference_type n); constexpr unspecified operator[](difference_type n) const; friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(see below); template<indirectly_swappable<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<Iterator2>& y) noexcept(see below); protected: Iterator current; }; }
The member typedef-name iterator_concept denotes
The member typedef-name iterator_category denotes
  • random_access_iterator_tag if the type iterator_traits<​Iterator>​::​iterator_category models derived_from<random_access_iterator_tag>, and
  • iterator_traits<​Iterator>​::​iterator_category otherwise.

24.5.1.3 Requirements [reverse.iter.requirements]

The template parameter Iterator shall either meet the requirements of a Cpp17BidirectionalIterator ([bidirectional.iterators]) or model bidirectional_iterator ([iterator.concept.bidir]).
Additionally, Iterator shall either meet the requirements of a Cpp17RandomAccessIterator ([random.access.iterators]) or model random_access_iterator ([iterator.concept.random.access]) if the definitions of any of the members or the non-member operators ([reverse.iter.cmp]) are instantiated ([temp.inst]).

24.5.1.4 Construction and assignment [reverse.iter.cons]

constexpr reverse_iterator();
Effects: Value-initializes current.
constexpr explicit reverse_iterator(Iterator x);
Effects: Initializes current with x.
template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);
Constraints: is_same_v<U, Iterator> is false and const U& models convertible_to<Iterator>.
Effects: Initializes current with u.current.
template<class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);
Constraints: is_same_v<U, Iterator> is false, const U& models convertible_to<Iterator>, and assignable_from<Iterator&, const U&> is modeled.
Effects: Assigns u.current to current.
Returns: *this.

24.5.1.5 Conversion [reverse.iter.conv]

constexpr Iterator base() const;
Returns: current.

24.5.1.6 Element access [reverse.iter.elem]

constexpr reference operator*() const;
Effects: As if by: Iterator tmp = current; return *--tmp;
constexpr pointer operator->() const requires (is_pointer_v<Iterator> || requires(const Iterator i) { i.operator->(); });
Effects:
  • If Iterator is a pointer type, equivalent to: return prev(current);
  • Otherwise, equivalent to: return prev(current).operator->();
constexpr unspecified operator[](difference_type n) const;
Returns: current[-n-1].

24.5.1.7 Navigation [reverse.iter.nav]

constexpr reverse_iterator operator+(difference_type n) const;
Returns: reverse_iterator(current-n).
constexpr reverse_iterator operator-(difference_type n) const;
Returns: reverse_iterator(current+n).
constexpr reverse_iterator& operator++();
Effects: As if by: --current;
Returns: *this.
constexpr reverse_iterator operator++(int);
Effects: As if by: reverse_iterator tmp = *this; --current; return tmp;
constexpr reverse_iterator& operator--();
Effects: As if by ++current.
Returns: *this.
constexpr reverse_iterator operator--(int);
Effects: As if by: reverse_iterator tmp = *this; ++current; return tmp;
constexpr reverse_iterator& operator+=(difference_type n);
Effects: As if by: current -= n;
Returns: *this.
constexpr reverse_iterator& operator-=(difference_type n);
Effects: As if by: current += n;
Returns: *this.

24.5.1.8 Comparisons [reverse.iter.cmp]

template<class Iterator1, class Iterator2> constexpr bool operator==( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() == y.base() is well-formed and convertible to bool.
Returns: x.base() == y.base().
template<class Iterator1, class Iterator2> constexpr bool operator!=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() != y.base() is well-formed and convertible to bool.
Returns: x.base() != y.base().
template<class Iterator1, class Iterator2> constexpr bool operator<( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() > y.base() is well-formed and convertible to bool.
Returns: x.base() > y.base().
template<class Iterator1, class Iterator2> constexpr bool operator>( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() < y.base() is well-formed and convertible to bool.
Returns: x.base() < y.base().
template<class Iterator1, class Iterator2> constexpr bool operator<=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() >= y.base() is well-formed and convertible to bool.
Returns: x.base() >= y.base().
template<class Iterator1, class Iterator2> constexpr bool operator>=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Constraints: x.base() <= y.base() is well-formed and convertible to bool.
Returns: x.base() <= y.base().
template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);
Returns: y.base() <=> x.base().
[Note 1: 
The argument order in the Returns: element is reversed because this is a reverse iterator.
— end note]

24.5.1.9 Non-member functions [reverse.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());
Returns: y.base() - x.base().
template<class Iterator> constexpr reverse_iterator<Iterator> operator+( iter_difference_t<Iterator> n, const reverse_iterator<Iterator>& x);
Returns: reverse_iterator<Iterator>(x.base() - n).
friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const reverse_iterator& i) noexcept(see below);
Effects: Equivalent to: auto tmp = i.base(); return ranges::iter_move(--tmp);
Remarks: The exception specification is equivalent to: is_nothrow_copy_constructible_v<Iterator> && noexcept(ranges::iter_move(--declval<Iterator&>()))
template<indirectly_swappable<Iterator> Iterator2> friend constexpr void iter_swap(const reverse_iterator& x, const reverse_iterator<Iterator2>& y) noexcept(see below);
Effects: Equivalent to: auto xtmp = x.base(); auto ytmp = y.base(); ranges::iter_swap(--xtmp, --ytmp);
Remarks: The exception specification is equivalent to: is_nothrow_copy_constructible_v<Iterator> && is_nothrow_copy_constructible_v<Iterator2> && noexcept(ranges::iter_swap(--declval<Iterator&>(), --declval<Iterator2&>()))
template<class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);
Returns: reverse_iterator<Iterator>(i).

24.5.2 Insert iterators [insert.iterators]

24.5.2.1 General [insert.iterators.general]

To make it possible to deal with insertion in the same way as writing into an array, a special kind of iterator adaptors, called insert iterators, are provided in the library.
With regular iterator classes, while (first != last) *result++ = *first++; causes a range [first, last) to be copied into a range starting with result.
The same code with result being an insert iterator will insert corresponding elements into the container.
This device allows all of the copying algorithms in the library to work in the insert mode instead of the regular overwrite mode.
An insert iterator is constructed from a container and possibly one of its iterators pointing to where insertion takes place if it is neither at the beginning nor at the end of the container.
Insert iterators meet the requirements of output iterators.
operator* returns the insert iterator itself.
The assignment operator=(const T& x) is defined on insert iterators to allow writing into them, it inserts x right before where the insert iterator is pointing.
In other words, an insert iterator is like a cursor pointing into the container where the insertion takes place.
back_insert_iterator inserts elements at the end of a container, front_insert_iterator inserts elements at the beginning of a container, and insert_iterator inserts elements where the iterator points to in a container.
back_inserter, front_inserter, and inserter are three functions making the insert iterators out of a container.

24.5.2.2 Class template back_insert_iterator [back.insert.iterator]

24.5.2.2.1 General [back.insert.iter.general]

namespace std { template<class Container> class back_insert_iterator { protected: Container* container; public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using container_type = Container; constexpr explicit back_insert_iterator(Container& x); constexpr back_insert_iterator& operator=(const typename Container::value_type& value); constexpr back_insert_iterator& operator=(typename Container::value_type&& value); constexpr back_insert_iterator& operator*(); constexpr back_insert_iterator& operator++(); constexpr back_insert_iterator operator++(int); }; }

24.5.2.2.2 Operations [back.insert.iter.ops]

constexpr explicit back_insert_iterator(Container& x);
Effects: Initializes container with addressof(x).
constexpr back_insert_iterator& operator=(const typename Container::value_type& value);
Effects: As if by: container->push_back(value);
Returns: *this.
constexpr back_insert_iterator& operator=(typename Container::value_type&& value);
Effects: As if by: container->push_back(std​::​move(value));
Returns: *this.
constexpr back_insert_iterator& operator*();
Returns: *this.
constexpr back_insert_iterator& operator++(); constexpr back_insert_iterator operator++(int);
Returns: *this.

24.5.2.2.3 back_inserter [back.inserter]

template<class Container> constexpr back_insert_iterator<Container> back_inserter(Container& x);
Returns: back_insert_iterator<Container>(x).

24.5.2.3 Class template front_insert_iterator [front.insert.iterator]

24.5.2.3.1 General [front.insert.iter.general]

namespace std { template<class Container> class front_insert_iterator { protected: Container* container; public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using container_type = Container; constexpr explicit front_insert_iterator(Container& x); constexpr front_insert_iterator& operator=(const typename Container::value_type& value); constexpr front_insert_iterator& operator=(typename Container::value_type&& value); constexpr front_insert_iterator& operator*(); constexpr front_insert_iterator& operator++(); constexpr front_insert_iterator operator++(int); }; }

24.5.2.3.2 Operations [front.insert.iter.ops]

constexpr explicit front_insert_iterator(Container& x);
Effects: Initializes container with addressof(x).
constexpr front_insert_iterator& operator=(const typename Container::value_type& value);
Effects: As if by: container->push_front(value);
Returns: *this.
constexpr front_insert_iterator& operator=(typename Container::value_type&& value);
Effects: As if by: container->push_front(std​::​move(value));
Returns: *this.
constexpr front_insert_iterator& operator*();
Returns: *this.
constexpr front_insert_iterator& operator++(); constexpr front_insert_iterator operator++(int);
Returns: *this.

24.5.2.3.3 front_inserter [front.inserter]

template<class Container> constexpr front_insert_iterator<Container> front_inserter(Container& x);
Returns: front_insert_iterator<Container>(x).

24.5.2.4 Class template insert_iterator [insert.iterator]

24.5.2.4.1 General [insert.iter.general]

namespace std { template<class Container> class insert_iterator { protected: Container* container; ranges::iterator_t<Container> iter; public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using container_type = Container; constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i); constexpr insert_iterator& operator=(const typename Container::value_type& value); constexpr insert_iterator& operator=(typename Container::value_type&& value); constexpr insert_iterator& operator*(); constexpr insert_iterator& operator++(); constexpr insert_iterator& operator++(int); }; }

24.5.2.4.2 Operations [insert.iter.ops]

constexpr insert_iterator(Container& x, ranges::iterator_t<Container> i);
Effects: Initializes container with addressof(x) and iter with i.
constexpr insert_iterator& operator=(const typename Container::value_type& value);
Effects: As if by: iter = container->insert(iter, value); ++iter;
Returns: *this.
constexpr insert_iterator& operator=(typename Container::value_type&& value);
Effects: As if by: iter = container->insert(iter, std::move(value)); ++iter;
Returns: *this.
constexpr insert_iterator& operator*();
Returns: *this.
constexpr insert_iterator& operator++(); constexpr insert_iterator& operator++(int);
Returns: *this.

24.5.2.4.3 inserter [inserter]

template<class Container> constexpr insert_iterator<Container> inserter(Container& x, ranges::iterator_t<Container> i);
Returns: insert_iterator<Container>(x, i).

24.5.3 Constant iterators and sentinels [const.iterators]

24.5.3.1 General [const.iterators.general]

Class template basic_const_iterator is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator's indirection operator to a type such that the adapted iterator is a constant iterator ([iterator.requirements]).
Some generic algorithms can be called with constant iterators to avoid mutation.
Specializations of basic_const_iterator are constant iterators.

24.5.3.2 Alias templates [const.iterators.alias]

template<indirectly_readable It> using iter_const_reference_t = common_reference_t<const iter_value_t<It>&&, iter_reference_t<It>>; template<class It> concept constant-iterator = // exposition only input_iterator<It> && same_as<iter_const_reference_t<It>, iter_reference_t<It>>; template<input_iterator I> using const_iterator = see below;
Result: If I models constant-iterator, I.
Otherwise, basic_const_iterator<I>.
template<semiregular S> using const_sentinel = see below;
Result: If S models input_iterator, const_iterator<S>.
Otherwise, S.

24.5.3.3 Class template basic_const_iterator [const.iterators.iterator]

namespace std { template<class I> concept not-a-const-iterator = see below; // exposition only template<indirectly_readable I> using iter-const-rvalue-reference-t = // exposition only common_reference_t<const iter_value_t<I>&&, iter_rvalue_reference_t<I>>; template<input_iterator Iterator> class basic_const_iterator { Iterator current_ = Iterator(); // exposition only using reference = iter_const_reference_t<Iterator>; // exposition only using rvalue-reference = // exposition only iter-const-rvalue-reference-t<Iterator>; public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = iter_value_t<Iterator>; using difference_type = iter_difference_t<Iterator>; basic_const_iterator() requires default_initializable<Iterator> = default; constexpr basic_const_iterator(Iterator current); template<convertible_to<Iterator> U> constexpr basic_const_iterator(basic_const_iterator<U> current); template<different-from<basic_const_iterator> T> requires convertible_to<T, Iterator> constexpr basic_const_iterator(T&& current); constexpr const Iterator& base() const & noexcept; constexpr Iterator base() &&; constexpr reference operator*() const; constexpr const auto* operator->() const requires is_lvalue_reference_v<iter_reference_t<Iterator>> && same_as<remove_cvref_t<iter_reference_t<Iterator>>, value_type>; constexpr basic_const_iterator& operator++(); constexpr void operator++(int); constexpr basic_const_iterator operator++(int) requires forward_iterator<Iterator>; constexpr basic_const_iterator& operator--() requires bidirectional_iterator<Iterator>; constexpr basic_const_iterator operator--(int) requires bidirectional_iterator<Iterator>; constexpr basic_const_iterator& operator+=(difference_type n) requires random_access_iterator<Iterator>; constexpr basic_const_iterator& operator-=(difference_type n) requires random_access_iterator<Iterator>; constexpr reference operator[](difference_type n) const requires random_access_iterator<Iterator>; template<sentinel_for<Iterator> S> constexpr bool operator==(const S& s) const; template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator const&, CI> constexpr operator CI() const &; template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator, CI> constexpr operator CI() &&; constexpr bool operator<(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator>(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator<=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator>=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr auto operator<=>(const basic_const_iterator& y) const requires random_access_iterator<Iterator> && three_way_comparable<Iterator>; template<different-from<basic_const_iterator> I> constexpr bool operator<(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator<=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator>=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr auto operator<=>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I> && three_way_comparable_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator<(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator>(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator<=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator>=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; friend constexpr basic_const_iterator operator+(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>; friend constexpr basic_const_iterator operator+(difference_type n, const basic_const_iterator& i) requires random_access_iterator<Iterator>; friend constexpr basic_const_iterator operator-(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>; template<sized_sentinel_for<Iterator> S> constexpr difference_type operator-(const S& y) const; template<not-a-const-iterator S> requires sized_sentinel_for<S, Iterator> friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y); friend constexpr rvalue-reference iter_move(const basic_const_iterator& i) noexcept(noexcept(static_cast<rvalue-reference>(ranges::iter_move(i.current_)))) { return static_cast<rvalue-reference>(ranges::iter_move(i.current_)); } }; }
Given some type I, the concept not-a-const-iterator is defined as false if I is a specialization of basic_const_iterator and true otherwise.

24.5.3.4 Member types [const.iterators.types]

basic_const_iterator<Iterator>​::​iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if Iterator models forward_iterator.
In that case, basic_const_iterator<Iterator>​::​iterator_category denotes the type iterator_traits<​Iterator>​::​iterator_category.

24.5.3.5 Operations [const.iterators.ops]

constexpr basic_const_iterator(Iterator current);
Effects: Initializes current_ with std​::​move(current).
template<convertible_to<Iterator> U> constexpr basic_const_iterator(basic_const_iterator<U> current);
Effects: Initializes current_ with std​::​move(current.current_).
template<different-from<basic_const_iterator> T> requires convertible_to<T, Iterator> constexpr basic_const_iterator(T&& current);
Effects: Initializes current_ with std​::​forward<T>(current).
constexpr const Iterator& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr Iterator base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr reference operator*() const;
Effects: Equivalent to: return static_cast<reference>(*current_);
constexpr const auto* operator->() const requires is_lvalue_reference_v<iter_reference_t<Iterator>> && same_as<remove_cvref_t<iter_reference_t<Iterator>>, value_type>;
Returns: If Iterator models contiguous_iterator, to_address(current_); otherwise, addressof(*current_).
constexpr basic_const_iterator& operator++();
Effects: Equivalent to: ++current_; return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++current_;
constexpr basic_const_iterator operator++(int) requires forward_iterator<Iterator>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr basic_const_iterator& operator--() requires bidirectional_iterator<Iterator>;
Effects: Equivalent to: --current_; return *this;
constexpr basic_const_iterator operator--(int) requires bidirectional_iterator<Iterator>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr basic_const_iterator& operator+=(difference_type n) requires random_access_iterator<Iterator>; constexpr basic_const_iterator& operator-=(difference_type n) requires random_access_iterator<Iterator>;
Let op be the operator.
Effects: Equivalent to: current_ op n; return *this;
constexpr reference operator[](difference_type n) const requires random_access_iterator<Iterator>
Effects: Equivalent to: return static_cast<reference>(current_[n]);
template<sentinel_for<Iterator> S> constexpr bool operator==(const S& s) const;
Effects: Equivalent to: return current_ == s;
template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator const&, CI> constexpr operator CI() const &;
Returns: current_.
template<not-a-const-iterator CI> requires constant-iterator<CI> && convertible_to<Iterator, CI> constexpr operator CI() &&;
Returns: std​::​move(current_).
constexpr bool operator<(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator>(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator<=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr bool operator>=(const basic_const_iterator& y) const requires random_access_iterator<Iterator>; constexpr auto operator<=>(const basic_const_iterator& y) const requires random_access_iterator<Iterator> && three_way_comparable<Iterator>;
Let op be the operator.
Effects: Equivalent to: return current_ op y.current_;
template<different-from<basic_const_iterator> I> constexpr bool operator<(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator<=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr bool operator>=(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<different-from<basic_const_iterator> I> constexpr auto operator<=>(const I& y) const requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I> && three_way_comparable_with<Iterator, I>;
Let op be the operator.
Effects: Equivalent to: return current_ op y;
template<not-a-const-iterator I> friend constexpr bool operator<(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator>(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator<=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>; template<not-a-const-iterator I> friend constexpr bool operator>=(const I& x, const basic_const_iterator& y) requires random_access_iterator<Iterator> && totally_ordered_with<Iterator, I>;
Let op be the operator.
Effects: Equivalent to: return x op y.current_;
friend constexpr basic_const_iterator operator+(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>; friend constexpr basic_const_iterator operator+(difference_type n, const basic_const_iterator& i) requires random_access_iterator<Iterator>;
Effects: Equivalent to: return basic_const_iterator(i.current_ + n);
friend constexpr basic_const_iterator operator-(const basic_const_iterator& i, difference_type n) requires random_access_iterator<Iterator>;
Effects: Equivalent to: return basic_const_iterator(i.current_ - n);
template<sized_sentinel_for<Iterator> S> constexpr difference_type operator-(const S& y) const;
Effects: Equivalent to: return current_ - y;
template<not-a-const-iterator S> requires sized_sentinel_for<S, Iterator> friend constexpr difference_type operator-(const S& x, const basic_const_iterator& y);
Effects: Equivalent to: return x - y.current_;

24.5.4 Move iterators and sentinels [move.iterators]

24.5.4.1 General [move.iterators.general]

Class template move_iterator is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator's indirection operator to an rvalue.
Some generic algorithms can be called with move iterators to replace copying with moving.
[Example 1: list<string> s; // populate the list s vector<string> v1(s.begin(), s.end()); // copies strings into v1 vector<string> v2(make_move_iterator(s.begin()), make_move_iterator(s.end())); // moves strings into v2 — end example]

24.5.4.2 Class template move_iterator [move.iterator]

namespace std { template<class Iterator> class move_iterator { public: using iterator_type = Iterator; using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = iter_value_t<Iterator>; using difference_type = iter_difference_t<Iterator>; using pointer = Iterator; using reference = iter_rvalue_reference_t<Iterator>; constexpr move_iterator(); constexpr explicit move_iterator(Iterator i); template<class U> constexpr move_iterator(const move_iterator<U>& u); template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u); constexpr const Iterator& base() const & noexcept; constexpr Iterator base() &&; constexpr reference operator*() const; constexpr move_iterator& operator++(); constexpr auto operator++(int); constexpr move_iterator& operator--(); constexpr move_iterator operator--(int); constexpr move_iterator operator+(difference_type n) const; constexpr move_iterator& operator+=(difference_type n); constexpr move_iterator operator-(difference_type n) const; constexpr move_iterator& operator-=(difference_type n); constexpr reference operator[](difference_type n) const; template<sentinel_for<Iterator> S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel<S>& y); template<sized_sentinel_for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y); template<sized_sentinel_for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_iterator& x, const move_sentinel<S>& y); friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const move_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))); template<indirectly_swappable<Iterator> Iterator2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current))); private: Iterator current; // exposition only }; }
The member typedef-name iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if the qualified-id iterator_traits<Iterator>​::​iterator_category is valid and denotes a type.
In that case, iterator_category denotes
  • random_access_iterator_tag if the type iterator_traits<​Iterator>​::​iterator_category models derived_from<random_access_iterator_tag>, and
  • iterator_traits<​Iterator>​::​iterator_category otherwise.

24.5.4.3 Requirements [move.iter.requirements]

The template parameter Iterator shall either meet the Cpp17InputIterator requirements ([input.iterators]) or model input_iterator ([iterator.concept.input]).
Additionally, if any of the bidirectional traversal functions are instantiated, the template parameter shall either meet the Cpp17BidirectionalIterator requirements ([bidirectional.iterators]) or model bidirectional_iterator ([iterator.concept.bidir]).
If any of the random access traversal functions are instantiated, the template parameter shall either meet the Cpp17RandomAccessIterator requirements ([random.access.iterators]) or model random_access_iterator ([iterator.concept.random.access]).

24.5.4.4 Construction and assignment [move.iter.cons]

constexpr move_iterator();
Effects: Value-initializes current.
constexpr explicit move_iterator(Iterator i);
Effects: Initializes current with std​::​move(i).
template<class U> constexpr move_iterator(const move_iterator<U>& u);
Constraints: is_same_v<U, Iterator> is false and const U& models convertible_to<Iterator>.
Effects: Initializes current with u.current.
template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);
Constraints: is_same_v<U, Iterator> is false, const U& models convertible_to<Iterator>, and assignable_from<Iterator&, const U&> is modeled.
Effects: Assigns u.current to current.
Returns: *this.

24.5.4.5 Conversion [move.iter.op.conv]

constexpr const Iterator& base() const & noexcept;
Returns: current.
constexpr Iterator base() &&;
Returns: std​::​move(current).

24.5.4.6 Element access [move.iter.elem]

constexpr reference operator*() const;
Effects: Equivalent to: return ranges​::​iter_move(current);
constexpr reference operator[](difference_type n) const;
Effects: Equivalent to: return ranges​::​iter_move(current + n);

24.5.4.7 Navigation [move.iter.nav]

constexpr move_iterator& operator++();
Effects: As if by ++current.
Returns: *this.
constexpr auto operator++(int);
Effects: If Iterator models forward_iterator, equivalent to: move_iterator tmp = *this; ++current; return tmp;
Otherwise, equivalent to ++current.
constexpr move_iterator& operator--();
Effects: As if by --current.
Returns: *this.
constexpr move_iterator operator--(int);
Effects: As if by: move_iterator tmp = *this; --current; return tmp;
constexpr move_iterator operator+(difference_type n) const;
Returns: move_iterator(current + n).
constexpr move_iterator& operator+=(difference_type n);
Effects: As if by: current += n;
Returns: *this.
constexpr move_iterator operator-(difference_type n) const;
Returns: move_iterator(current - n).
constexpr move_iterator& operator-=(difference_type n);
Effects: As if by: current -= n;
Returns: *this.

24.5.4.8 Comparisons [move.iter.op.comp]

template<class Iterator1, class Iterator2> constexpr bool operator==(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y); template<sentinel_for<Iterator> S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel<S>& y);
Constraints: x.base() == y.base() is well-formed and convertible to bool.
Returns: x.base() == y.base().
template<class Iterator1, class Iterator2> constexpr bool operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: x.base() < y.base() is well-formed and convertible to bool.
Returns: x.base() < y.base().
template<class Iterator1, class Iterator2> constexpr bool operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: y.base() < x.base() is well-formed and convertible to bool.
Returns: y < x.
template<class Iterator1, class Iterator2> constexpr bool operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: y.base() < x.base() is well-formed and convertible to bool.
Returns: !(y < x).
template<class Iterator1, class Iterator2> constexpr bool operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Constraints: x.base() < y.base() is well-formed and convertible to bool.
Returns: !(x < y).
template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2> constexpr compare_three_way_result_t<Iterator1, Iterator2> operator<=>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
Returns: x.base() <=> y.base().

24.5.4.9 Non-member functions [move.iter.nonmember]

template<class Iterator1, class Iterator2> constexpr auto operator-( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); template<sized_sentinel_for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_sentinel<S>& x, const move_iterator& y); template<sized_sentinel_for<Iterator> S> friend constexpr iter_difference_t<Iterator> operator-(const move_iterator& x, const move_sentinel<S>& y);
Returns: x.base() - y.base().
template<class Iterator> constexpr move_iterator<Iterator> operator+(iter_difference_t<Iterator> n, const move_iterator<Iterator>& x);
Constraints: x.base() + n is well-formed and has type Iterator.
Returns: x + n.
friend constexpr iter_rvalue_reference_t<Iterator> iter_move(const move_iterator& i) noexcept(noexcept(ranges::iter_move(i.current)));
Effects: Equivalent to: return ranges​::​iter_move(i.current);
template<indirectly_swappable<Iterator> Iterator2> friend constexpr void iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
Effects: Equivalent to: ranges​::​iter_swap(x.current, y.current).
template<class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i);
Returns: move_iterator<Iterator>(std​::​move(i)).

24.5.4.10 Class template move_sentinel [move.sentinel]

Class template move_sentinel is a sentinel adaptor useful for denoting ranges together with move_iterator.
When an input iterator type I and sentinel type S model sentinel_for<S, I>, move_sentinel<S> and move_iterator<I> model sentinel_for<move_sentinel<S>, move_iterator<I>> as well.
[Example 1: 
A move_if algorithm is easily implemented with copy_if using move_iterator and move_sentinel: template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, indirect_unary_predicate<I> Pred> requires indirectly_movable<I, O> void move_if(I first, S last, O out, Pred pred) { ranges::copy_if(move_iterator<I>{std::move(first)}, move_sentinel<S>{last}, std::move(out), pred); }
— end example]
namespace std { template<semiregular S> class move_sentinel { public: constexpr move_sentinel(); constexpr explicit move_sentinel(S s); template<class S2> requires convertible_to<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s); template<class S2> requires assignable_from<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s); constexpr S base() const; private: S last; // exposition only }; }

24.5.4.11 Operations [move.sent.ops]

constexpr move_sentinel();
Effects: Value-initializes last.
If is_trivially_default_constructible_v<S> is true, then this constructor is a constexpr constructor.
constexpr explicit move_sentinel(S s);
Effects: Initializes last with std​::​move(s).
template<class S2> requires convertible_to<const S2&, S> constexpr move_sentinel(const move_sentinel<S2>& s);
Effects: Initializes last with s.last.
template<class S2> requires assignable_from<S&, const S2&> constexpr move_sentinel& operator=(const move_sentinel<S2>& s);
Effects: Equivalent to: last = s.last; return *this;
constexpr S base() const;
Returns: last.

24.5.5 Common iterators [iterators.common]

24.5.5.1 Class template common_iterator [common.iterator]

Class template common_iterator is an iterator/sentinel adaptor that is capable of representing a non-common range of elements (where the types of the iterator and sentinel differ) as a common range (where they are the same).
It does this by holding either an iterator or a sentinel, and implementing the equality comparison operators appropriately.
[Note 1: 
The common_iterator type is useful for interfacing with legacy code that expects the begin and end of a range to have the same type.
— end note]
[Example 1: template<class ForwardIterator> void fun(ForwardIterator begin, ForwardIterator end); list<int> s; // populate the list s using CI = common_iterator<counted_iterator<list<int>::iterator>, default_sentinel_t>; // call fun on a range of 10 ints fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — end example]
namespace std { template<input_or_output_iterator I, sentinel_for<I> S> requires (!same_as<I, S> && copyable<I>) class common_iterator { public: constexpr common_iterator() requires default_initializable<I> = default; constexpr common_iterator(I i); constexpr common_iterator(S s); template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x); template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> && assignable_from<I&, const I2&> && assignable_from<S&, const S2&> constexpr common_iterator& operator=(const common_iterator<I2, S2>& x); constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>; constexpr auto operator->() const requires see below; constexpr common_iterator& operator++(); constexpr decltype(auto) operator++(int); template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y); template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> && equality_comparable_with<I, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y); template<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2> requires sized_sentinel_for<S, I2> friend constexpr iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y); friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires input_iterator<I>; template<indirectly_swappable<I> I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>()))); private: variant<I, S> v_; // exposition only }; template<class I, class S> struct incrementable_traits<common_iterator<I, S>> { using difference_type = iter_difference_t<I>; }; template<input_iterator I, class S> struct iterator_traits<common_iterator<I, S>> { using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = iter_value_t<I>; using difference_type = iter_difference_t<I>; using pointer = see below; using reference = iter_reference_t<I>; }; }

24.5.5.2 Associated types [common.iter.types]

The nested typedef-name iterator_category of the specialization of iterator_traits for common_iterator<I, S> is defined if and only if iter_difference_t<I> is an integral type.
In that case, iterator_category denotes forward_iterator_tag if the qualified-id iterator_traits<I>​::​iterator_category is valid and denotes a type that models derived_from<forward_iterator_tag>; otherwise it denotes input_iterator_tag.
The remaining nested typedef-names of the specialization of iterator_traits for common_iterator<I, S> are defined as follows:
  • iterator_concept denotes forward_iterator_tag if I models forward_iterator; otherwise it denotes input_iterator_tag.
  • Let a denote an lvalue of type const common_iterator<I, S>.
    If the expression a.operator->() is well-formed, then pointer denotes decltype(a.operator->()).
    Otherwise, pointer denotes void.

24.5.5.3 Constructors and conversions [common.iter.const]

constexpr common_iterator(I i);
Effects: Initializes v_ as if by v_{in_place_type<I>, std​::​move(i)}.
constexpr common_iterator(S s);
Effects: Initializes v_ as if by v_{in_place_type<S>, std​::​move(s)}.
template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> constexpr common_iterator(const common_iterator<I2, S2>& x);
Preconditions: x.v_.valueless_by_exception() is false.
Effects: Initializes v_ as if by v_{in_place_index<i>, get<i>(x.v_)}, where i is x.v_.index().
template<class I2, class S2> requires convertible_to<const I2&, I> && convertible_to<const S2&, S> && assignable_from<I&, const I2&> && assignable_from<S&, const S2&> constexpr common_iterator& operator=(const common_iterator<I2, S2>& x);
Preconditions: x.v_.valueless_by_exception() is false.
Effects: Equivalent to:
  • If v_.index() == x.v_.index(), then get<i>(v_) = get<i>(x.v_).
  • Otherwise, v_.emplace<i>(get<i>(x.v_)).
where i is x.v_.index().
Returns: *this.

24.5.5.4 Accessors [common.iter.access]

constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>;
Preconditions: holds_alternative<I>(v_) is true.
Effects: Equivalent to: return *get<I>(v_);
constexpr auto operator->() const requires see below;
The expression in the requires-clause is equivalent to: indirectly_readable<const I> && (requires(const I& i) { i.operator->(); } || is_reference_v<iter_reference_t<I>> || constructible_from<iter_value_t<I>, iter_reference_t<I>>)
Preconditions: holds_alternative<I>(v_) is true.
Effects:
  • If I is a pointer type or if the expression get<I>(v_).operator->() is well-formed, equivalent to: return get<I>(v_);
  • Otherwise, if iter_reference_t<I> is a reference type, equivalent to: auto&& tmp = *get<I>(v_); return addressof(tmp);
  • Otherwise, equivalent to: return proxy(*get<I>(v_)); where proxy is the exposition-only class: class proxy { iter_value_t<I> keep_; constexpr proxy(iter_reference_t<I>&& x) : keep_(std::move(x)) {} public: constexpr const iter_value_t<I>* operator->() const noexcept { return addressof(keep_); } };

24.5.5.5 Navigation [common.iter.nav]

constexpr common_iterator& operator++();
Preconditions: holds_alternative<I>(v_) is true.
Effects: Equivalent to ++get<I>(v_).
Returns: *this.
constexpr decltype(auto) operator++(int);
Preconditions: holds_alternative<I>(v_) is true.
Effects: If I models forward_iterator, equivalent to: common_iterator tmp = *this; ++*this; return tmp;
Otherwise, if requires(I& i) { { *i++ } -> can-reference; } is true or indirectly_readable<I> && constructible_from<iter_value_t<I>, iter_reference_t<I>> && move_constructible<iter_value_t<I>> is false, equivalent to: return get<I>(v_)++;
Otherwise, equivalent to: postfix-proxy p(**this); ++*this; return p; where postfix-proxy is the exposition-only class: class postfix-proxy { iter_value_t<I> keep_; constexpr postfix-proxy(iter_reference_t<I>&& x) : keep_(std::forward<iter_reference_t<I>>(x)) {} public: constexpr const iter_value_t<I>& operator*() const noexcept { return keep_; } };

24.5.5.6 Comparisons [common.iter.cmp]

template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);
Preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false.
Returns: true if i == j, and otherwise get<i>(x.v_) == get<j>(y.v_), where i is x.v_.index() and j is y.v_.index().
template<class I2, sentinel_for<I> S2> requires sentinel_for<S, I2> && equality_comparable_with<I, I2> friend constexpr bool operator==( const common_iterator& x, const common_iterator<I2, S2>& y);
Preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false.
Returns: true if i and j are each 1, and otherwise get<i>(x.v_) == get<j>(y.v_), where i is x.v_.index() and j is y.v_.index().
template<sized_sentinel_for<I> I2, sized_sentinel_for<I> S2> requires sized_sentinel_for<S, I2> friend constexpr iter_difference_t<I2> operator-( const common_iterator& x, const common_iterator<I2, S2>& y);
Preconditions: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false.
Returns: 0 if i and j are each 1, and otherwise get<i>(x.v_) - get<j>(y.v_), where i is x.v_.index() and j is y.v_.index().

24.5.5.7 Customizations [common.iter.cust]

friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval<const I&>()))) requires input_iterator<I>;
Preconditions: holds_alternative<I>(i.v_) is true.
Effects: Equivalent to: return ranges​::​iter_move(get<I>(i.v_));
template<indirectly_swappable<I> I2, class S2> friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y) noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));
Preconditions: holds_alternative<I>(x.v_) and holds_alternative<I2>(y.v_) are each true.
Effects: Equivalent to ranges​::​iter_swap(get<I>(x.v_), get<I2>(y.v_)).

24.5.6 Default sentinel [default.sentinel]

namespace std { struct default_sentinel_t { }; }
Class default_sentinel_t is an empty type used to denote the end of a range.
It can be used together with iterator types that know the bound of their range (e.g., counted_iterator ([counted.iterator])).

24.5.7 Counted iterators [iterators.counted]

24.5.7.1 Class template counted_iterator [counted.iterator]

Class template counted_iterator is an iterator adaptor with the same behavior as the underlying iterator except that it keeps track of the distance to the end of its range.
It can be used together with default_sentinel in calls to generic algorithms to operate on a range of N elements starting at a given position without needing to know the end position a priori.
[Example 1: list<string> s; // populate the list s with at least 10 strings vector<string> v; // copies 10 strings into v: ranges::copy(counted_iterator(s.begin(), 10), default_sentinel, back_inserter(v)); — end example]
Two values i1 and i2 of types counted_iterator<I1> and counted_iterator<I2> refer to elements of the same sequence if and only if there exists some integer n such that next(i1.base(), i1.count() + n) and next(i2.base(), i2.count() + n) refer to the same (possibly past-the-end) element.
namespace std { template<input_or_output_iterator I> class counted_iterator { public: using iterator_type = I; using value_type = iter_value_t<I>; // present only // if I models indirectly_readable using difference_type = iter_difference_t<I>; using iterator_concept = typename I::iterator_concept; // present only // if the qualified-id I​::​iterator_concept is valid and denotes a type using iterator_category = typename I::iterator_category; // present only // if the qualified-id I​::​iterator_category is valid and denotes a type constexpr counted_iterator() requires default_initializable<I> = default; constexpr counted_iterator(I x, iter_difference_t<I> n); template<class I2> requires convertible_to<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x); template<class I2> requires assignable_from<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x); constexpr const I& base() const & noexcept; constexpr I base() &&; constexpr iter_difference_t<I> count() const noexcept; constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>; constexpr auto operator->() const noexcept requires contiguous_iterator<I>; constexpr counted_iterator& operator++(); constexpr decltype(auto) operator++(int); constexpr counted_iterator operator++(int) requires forward_iterator<I>; constexpr counted_iterator& operator--() requires bidirectional_iterator<I>; constexpr counted_iterator operator--(int) requires bidirectional_iterator<I>; constexpr counted_iterator operator+(iter_difference_t<I> n) const requires random_access_iterator<I>; friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires random_access_iterator<I>; constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires random_access_iterator<I>; constexpr counted_iterator operator-(iter_difference_t<I> n) const requires random_access_iterator<I>; template<common_with<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y); friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t); friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y); constexpr counted_iterator& operator-=(iter_difference_t<I> n) requires random_access_iterator<I>; constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires random_access_iterator<I>; template<common_with<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y); friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t); template<common_with<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y); friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires input_iterator<I>; template<indirectly_swappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current))); private: I current = I(); // exposition only iter_difference_t<I> length = 0; // exposition only }; template<input_iterator I> requires same_as<ITER_TRAITS(I), iterator_traits<I>> // see [iterator.concepts.general] struct iterator_traits<counted_iterator<I>> : iterator_traits<I> { using pointer = conditional_t<contiguous_iterator<I>, add_pointer_t<iter_reference_t<I>>, void>; }; }

24.5.7.2 Constructors and conversions [counted.iter.const]

constexpr counted_iterator(I i, iter_difference_t<I> n);
Preconditions: n >= 0.
Effects: Initializes current with std​::​move(i) and length with n.
template<class I2> requires convertible_to<const I2&, I> constexpr counted_iterator(const counted_iterator<I2>& x);
Effects: Initializes current with x.current and length with x.length.
template<class I2> requires assignable_from<I&, const I2&> constexpr counted_iterator& operator=(const counted_iterator<I2>& x);
Effects: Assigns x.current to current and x.length to length.
Returns: *this.

24.5.7.3 Accessors [counted.iter.access]

constexpr const I& base() const & noexcept;
Effects: Equivalent to: return current;
constexpr I base() &&;
Returns: std​::​move(current).
constexpr iter_difference_t<I> count() const noexcept;
Effects: Equivalent to: return length;

24.5.7.4 Element access [counted.iter.elem]

constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() const requires dereferenceable<const I>;
Preconditions: length > 0 is true.
Effects: Equivalent to: return *current;
constexpr auto operator->() const noexcept requires contiguous_iterator<I>;
Effects: Equivalent to: return to_address(current);
constexpr decltype(auto) operator[](iter_difference_t<I> n) const requires random_access_iterator<I>;
Preconditions: n < length.
Effects: Equivalent to: return current[n];

24.5.7.5 Navigation [counted.iter.nav]

constexpr counted_iterator& operator++();
Preconditions: length > 0.
Effects: Equivalent to: ++current; --length; return *this;
constexpr decltype(auto) operator++(int);
Preconditions: length > 0.
Effects: Equivalent to: --length; try { return current++; } catch(...) { ++length; throw; }
constexpr counted_iterator operator++(int) requires forward_iterator<I>;
Effects: Equivalent to: counted_iterator tmp = *this; ++*this; return tmp;
constexpr counted_iterator& operator--() requires bidirectional_iterator<I>;
Effects: Equivalent to: --current; ++length; return *this;
constexpr counted_iterator operator--(int) requires bidirectional_iterator<I>;
Effects: Equivalent to: counted_iterator tmp = *this; --*this; return tmp;
constexpr counted_iterator operator+(iter_difference_t<I> n) const requires random_access_iterator<I>;
Effects: Equivalent to: return counted_iterator(current + n, length - n);
friend constexpr counted_iterator operator+( iter_difference_t<I> n, const counted_iterator& x) requires random_access_iterator<I>;
Effects: Equivalent to: return x + n;
constexpr counted_iterator& operator+=(iter_difference_t<I> n) requires random_access_iterator<I>;
Preconditions: n <= length.
Effects: Equivalent to: current += n; length -= n; return *this;
constexpr counted_iterator operator-(iter_difference_t<I> n) const requires random_access_iterator<I>;
Effects: Equivalent to: return counted_iterator(current - n, length + n);
template<common_with<I> I2> friend constexpr iter_difference_t<I2> operator-( const counted_iterator& x, const counted_iterator<I2>& y);
Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return y.length - x.length;
friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t);
Effects: Equivalent to: return -x.length;
friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y);
Effects: Equivalent to: return y.length;
constexpr counted_iterator& operator-=(iter_difference_t<I> n) requires random_access_iterator<I>;
Preconditions: -n <= length.
Effects: Equivalent to: current -= n; length += n; return *this;

24.5.7.6 Comparisons [counted.iter.cmp]

template<common_with<I> I2> friend constexpr bool operator==( const counted_iterator& x, const counted_iterator<I2>& y);
Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return x.length == y.length;
friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t);
Effects: Equivalent to: return x.length == 0;
template<common_with<I> I2> friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator<I2>& y);
Preconditions: x and y refer to elements of the same sequence ([counted.iterator]).
Effects: Equivalent to: return y.length <=> x.length;
[Note 1: 
The argument order in the Effects: element is reversed because length counts down, not up.
— end note]

24.5.7.7 Customizations [counted.iter.cust]

friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires input_iterator<I>;
Preconditions: i.length > 0 is true.
Effects: Equivalent to: return ranges​::​iter_move(i.current);
template<indirectly_swappable<I> I2> friend constexpr void iter_swap(const counted_iterator& x, const counted_iterator<I2>& y) noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
Preconditions: Both x.length > 0 and y.length > 0 are true.
Effects: Equivalent to ranges​::​iter_swap(x.current, y.current).

24.5.8 Unreachable sentinel [unreachable.sentinel]

Class unreachable_sentinel_t can be used with any weakly_incrementable type to denote the “upper bound” of an unbounded interval.
[Example 1: char* p; // set p to point to a character buffer containing newlines char* nl = find(p, unreachable_sentinel, '\n');
Provided a newline character really exists in the buffer, the use of unreachable_sentinel above potentially makes the call to find more efficient since the loop test against the sentinel does not require a conditional branch.
— end example]
namespace std { struct unreachable_sentinel_t { template<weakly_incrementable I> friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept { return false; } }; }

24.6 Stream iterators [stream.iterators]

24.6.1 General [stream.iterators.general]

To make it possible for algorithmic templates to work directly with input/output streams, appropriate iterator-like class templates are provided.
[Example 1: 
partial_sum(istream_iterator<double, char>(cin), istream_iterator<double, char>(), ostream_iterator<double, char>(cout, "\n")); reads a file containing floating-point numbers from cin, and prints the partial sums onto cout.
— end example]

24.6.2 Class template istream_iterator [istream.iterator]

24.6.2.1 General [istream.iterator.general]

The class template istream_iterator is an input iterator ([input.iterators]) that reads successive elements from the input stream for which it was constructed.
namespace std { template<class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t> class istream_iterator { public: using iterator_category = input_iterator_tag; using value_type = T; using difference_type = Distance; using pointer = const T*; using reference = const T&; using char_type = charT; using traits_type = traits; using istream_type = basic_istream<charT,traits>; constexpr istream_iterator(); constexpr istream_iterator(default_sentinel_t); istream_iterator(istream_type& s); constexpr istream_iterator(const istream_iterator& x) noexcept(see below); ~istream_iterator() = default; istream_iterator& operator=(const istream_iterator&) = default; const T& operator*() const; const T* operator->() const; istream_iterator& operator++(); istream_iterator operator++(int); friend bool operator==(const istream_iterator& i, default_sentinel_t); private: basic_istream<charT,traits>* in_stream; // exposition only T value; // exposition only }; }
The type T shall meet the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.

24.6.2.2 Constructors and destructor [istream.iterator.cons]

constexpr istream_iterator(); constexpr istream_iterator(default_sentinel_t);
Effects: Constructs the end-of-stream iterator, value-initializing value.
Postconditions: in_stream == nullptr is true.
Remarks: If the initializer T() in the declaration auto x = T(); is a constant initializer ([expr.const]), then these constructors are constexpr constructors.
istream_iterator(istream_type& s);
Effects: Initializes in_stream with addressof(s), value-initializes value, and then calls operator++().
constexpr istream_iterator(const istream_iterator& x) noexcept(see below);
Effects: Initializes in_stream with x.in_stream and initializes value with x.value.
Remarks: An invocation of this constructor may be used in a core constant expression if and only if the initialization of value from x.value is a constant subexpression ([defns.const.subexpr]).
The exception specification is equivalent to is_nothrow_copy_constructible_v<T>.
~istream_iterator() = default;
Remarks: If is_trivially_destructible_v<T> is true, then this destructor is trivial.

24.6.2.3 Operations [istream.iterator.ops]

const T& operator*() const;
Preconditions: in_stream != nullptr is true.
Returns: value.
const T* operator->() const;
Preconditions: in_stream != nullptr is true.
Returns: addressof(value).
istream_iterator& operator++();
Preconditions: in_stream != nullptr is true.
Effects: Equivalent to: if (!(*in_stream >> value)) in_stream = nullptr;
Returns: *this.
istream_iterator operator++(int);
Preconditions: in_stream != nullptr is true.
Effects: Equivalent to: istream_iterator tmp = *this; ++*this; return tmp;
template<class T, class charT, class traits, class Distance> bool operator==(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y);
Returns: x.in_stream == y.in_stream.
friend bool operator==(const istream_iterator& i, default_sentinel_t);
Returns: !i.in_stream.

24.6.3 Class template ostream_iterator [ostream.iterator]

24.6.3.1 General [ostream.iterator.general]

ostream_iterator writes (using operator<<) successive elements onto the output stream from which it was constructed.
If it was constructed with charT* as a constructor argument, this string, called a delimiter string, is written to the stream after every T is written.
namespace std { template<class T, class charT = char, class traits = char_traits<charT>> class ostream_iterator { public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using char_type = charT; using traits_type = traits; using ostream_type = basic_ostream<charT,traits>; ostream_iterator(ostream_type& s); ostream_iterator(ostream_type& s, const charT* delimiter); ostream_iterator(const ostream_iterator& x); ~ostream_iterator(); ostream_iterator& operator=(const ostream_iterator&) = default; ostream_iterator& operator=(const T& value); ostream_iterator& operator*(); ostream_iterator& operator++(); ostream_iterator& operator++(int); private: basic_ostream<charT,traits>* out_stream; // exposition only const charT* delim; // exposition only }; }

24.6.3.2 Constructors and destructor [ostream.iterator.cons.des]

ostream_iterator(ostream_type& s);
Effects: Initializes out_stream with addressof(s) and delim with nullptr.
ostream_iterator(ostream_type& s, const charT* delimiter);
Effects: Initializes out_stream with addressof(s) and delim with delimiter.

24.6.3.3 Operations [ostream.iterator.ops]

ostream_iterator& operator=(const T& value);
Effects: As if by: *out_stream << value; if (delim) *out_stream << delim; return *this;
ostream_iterator& operator*();
Returns: *this.
ostream_iterator& operator++(); ostream_iterator& operator++(int);
Returns: *this.

24.6.4 Class template istreambuf_iterator [istreambuf.iterator]

24.6.4.1 General [istreambuf.iterator.general]

The class template istreambuf_iterator defines an input iterator that reads successive characters from the streambuf for which it was constructed.
operator* provides access to the current input character, if any.
Each time operator++ is evaluated, the iterator advances to the next input character.
If the end of stream is reached (streambuf_type​::​sgetc() returns traits​::​eof()), the iterator becomes equal to the end-of-stream iterator value.
The default constructor istreambuf_iterator() and the constructor istreambuf_iterator(nullptr) both construct an end-of-stream iterator object suitable for use as an end-of-range.
All specializations of istreambuf_iterator shall have a trivial copy constructor, a constexpr default constructor, and a trivial destructor.
The result of operator*() on an end-of-stream iterator is undefined.
For any other iterator value a char_type value is returned.
It is impossible to assign a character via an input iterator.
namespace std { template<class charT, class traits = char_traits<charT>> class istreambuf_iterator { public: using iterator_category = input_iterator_tag; using value_type = charT; using difference_type = typename traits::off_type; using pointer = unspecified; using reference = charT; using char_type = charT; using traits_type = traits; using int_type = typename traits::int_type; using streambuf_type = basic_streambuf<charT,traits>; using istream_type = basic_istream<charT,traits>; // [istreambuf.iterator.proxy], class istreambuf_iterator​::​proxy class proxy; // exposition only constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel_t) noexcept; istreambuf_iterator(const istreambuf_iterator&) noexcept = default; ~istreambuf_iterator() = default; istreambuf_iterator(istream_type& s) noexcept; istreambuf_iterator(streambuf_type* s) noexcept; istreambuf_iterator(const proxy& p) noexcept; istreambuf_iterator& operator=(const istreambuf_iterator&) noexcept = default; charT operator*() const; istreambuf_iterator& operator++(); proxy operator++(int); bool equal(const istreambuf_iterator& b) const; friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); private: streambuf_type* sbuf_; // exposition only }; }

24.6.4.2 Class istreambuf_iterator​::​proxy [istreambuf.iterator.proxy]

Class istreambuf_iterator<charT,traits>​::​proxy is for exposition only.
An implementation is permitted to provide equivalent functionality without providing a class with this name.
Class istreambuf_iterator<charT, traits>​::​proxy provides a temporary placeholder as the return value of the post-increment operator (operator++).
It keeps the character pointed to by the previous value of the iterator for some possible future access to get the character.
namespace std { template<class charT, class traits> class istreambuf_iterator<charT, traits>::proxy { // exposition only charT keep_; basic_streambuf<charT,traits>* sbuf_; proxy(charT c, basic_streambuf<charT,traits>* sbuf) : keep_(c), sbuf_(sbuf) { } public: charT operator*() { return keep_; } }; }

24.6.4.3 Constructors [istreambuf.iterator.cons]

For each istreambuf_iterator constructor in this subclause, an end-of-stream iterator is constructed if and only if the exposition-only member sbuf_ is initialized with a null pointer value.
constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel_t) noexcept;
Effects: Initializes sbuf_ with nullptr.
istreambuf_iterator(istream_type& s) noexcept;
Effects: Initializes sbuf_ with s.rdbuf().
istreambuf_iterator(streambuf_type* s) noexcept;
Effects: Initializes sbuf_ with s.
istreambuf_iterator(const proxy& p) noexcept;
Effects: Initializes sbuf_ with p.sbuf_.

24.6.4.4 Operations [istreambuf.iterator.ops]

charT operator*() const;
Returns: The character obtained via the streambuf member sbuf_->sgetc().
istreambuf_iterator& operator++();
Effects: As if by sbuf_->sbumpc().
Returns: *this.
proxy operator++(int);
Returns: proxy(sbuf_->sbumpc(), sbuf_).
bool equal(const istreambuf_iterator& b) const;
Returns: true if and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of what streambuf object they use.
template<class charT, class traits> bool operator==(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b);
Returns: a.equal(b).
friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s);
Returns: i.equal(s).

24.6.5 Class template ostreambuf_iterator [ostreambuf.iterator]

24.6.5.1 General [ostreambuf.iterator.general]

The class template ostreambuf_iterator writes successive characters onto the output stream from which it was constructed.
namespace std { template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator { public: using iterator_category = output_iterator_tag; using value_type = void; using difference_type = ptrdiff_t; using pointer = void; using reference = void; using char_type = charT; using traits_type = traits; using streambuf_type = basic_streambuf<charT,traits>; using ostream_type = basic_ostream<charT,traits>; ostreambuf_iterator(ostream_type& s) noexcept; ostreambuf_iterator(streambuf_type* s) noexcept; ostreambuf_iterator& operator=(charT c); ostreambuf_iterator& operator*(); ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int); bool failed() const noexcept; private: streambuf_type* sbuf_; // exposition only }; }

24.6.5.2 Constructors [ostreambuf.iter.cons]

ostreambuf_iterator(ostream_type& s) noexcept;
Preconditions: s.rdbuf() is not a null pointer.
Effects: Initializes sbuf_ with s.rdbuf().
ostreambuf_iterator(streambuf_type* s) noexcept;
Preconditions: s is not a null pointer.
Effects: Initializes sbuf_ with s.

24.6.5.3 Operations [ostreambuf.iter.ops]

ostreambuf_iterator& operator=(charT c);
Effects: If failed() yields false, calls sbuf_->sputc(c); otherwise has no effect.
Returns: *this.
ostreambuf_iterator& operator*();
Returns: *this.
ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int);
Returns: *this.
bool failed() const noexcept;
Returns: true if in any prior use of member operator=, the call to sbuf_->sputc() returned traits​::​eof(); or false otherwise.

24.7 Range access [iterator.range]

In addition to being available via inclusion of the <iterator> header, the function templates in [iterator.range] are available when any of the following headers are included: <array>, <deque>, <flat_map>, <flat_set>, <forward_list>, <inplace_vector>, <list>, <map>, <regex>, <set>, <span>, <string>, <string_view>, <unordered_map>, <unordered_set>, and <vector>.
template<class C> constexpr auto begin(C& c) -> decltype(c.begin()); template<class C> constexpr auto begin(const C& c) -> decltype(c.begin());
Returns: c.begin().
template<class C> constexpr auto end(C& c) -> decltype(c.end()); template<class C> constexpr auto end(const C& c) -> decltype(c.end());
Returns: c.end().
template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;
Returns: array.
template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;
Returns: array + N.
template<class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c));
Returns: std​::​begin(c).
template<class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c));
Returns: std​::​end(c).
template<class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin()); template<class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());
Returns: c.rbegin().
template<class C> constexpr auto rend(C& c) -> decltype(c.rend()); template<class C> constexpr auto rend(const C& c) -> decltype(c.rend());
Returns: c.rend().
template<class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]);
Returns: reverse_iterator<T*>(array + N).
template<class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]);
Returns: reverse_iterator<T*>(array).
template<class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);
Returns: reverse_iterator<const E*>(il.end()).
template<class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);
Returns: reverse_iterator<const E*>(il.begin()).
template<class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));
Returns: std​::​rbegin(c).
template<class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));
Returns: std​::​rend(c).
template<class C> constexpr auto size(const C& c) -> decltype(c.size());
Returns: c.size().
template<class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept;
Returns: N.
template<class C> constexpr auto ssize(const C& c) -> common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>;
Effects: Equivalent to: return static_cast<common_type_t<ptrdiff_t, make_signed_t<decltype(c.size())>>>(c.size());
template<class T, ptrdiff_t N> constexpr ptrdiff_t ssize(const T (&array)[N]) noexcept;
Returns: N.
template<class C> constexpr auto empty(const C& c) -> decltype(c.empty());
Returns: c.empty().
template<class T, size_t N> constexpr bool empty(const T (&array)[N]) noexcept;
Returns: false.
template<class E> constexpr bool empty(initializer_list<E> il) noexcept;
Returns: il.size() == 0.
template<class C> constexpr auto data(C& c) -> decltype(c.data()); template<class C> constexpr auto data(const C& c) -> decltype(c.data());
Returns: c.data().
template<class T, size_t N> constexpr T* data(T (&array)[N]) noexcept;
Returns: array.
template<class E> constexpr const E* data(initializer_list<E> il) noexcept;
Returns: il.begin().

25 Ranges library [ranges]

25.1 General [ranges.general]

This Clause describes components for dealing with ranges of elements.
The following subclauses describe range and view requirements, and components for range primitives and range generators as summarized in Table 79.
Table 79 — Ranges library summary [tab:range.summary]
Subclause
Header
Range access
<ranges>
Requirements
Range utilities
Range factories
Range adaptors
Range generators

25.2 Header <ranges> synopsis [ranges.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] #include <iterator> // see [iterator.synopsis] namespace std::ranges { inline namespace unspecified { // [range.access], range access inline constexpr unspecified begin = unspecified; // freestanding inline constexpr unspecified end = unspecified; // freestanding inline constexpr unspecified cbegin = unspecified; // freestanding inline constexpr unspecified cend = unspecified; // freestanding inline constexpr unspecified rbegin = unspecified; // freestanding inline constexpr unspecified rend = unspecified; // freestanding inline constexpr unspecified crbegin = unspecified; // freestanding inline constexpr unspecified crend = unspecified; // freestanding inline constexpr unspecified size = unspecified; // freestanding inline constexpr unspecified ssize = unspecified; // freestanding inline constexpr unspecified empty = unspecified; // freestanding inline constexpr unspecified data = unspecified; // freestanding inline constexpr unspecified cdata = unspecified; // freestanding } // [range.range], ranges template<class T> concept range = see below; // freestanding template<class T> constexpr bool enable_borrowed_range = false; // freestanding template<class T> concept borrowed_range = see below; // freestanding template<class T> using iterator_t = decltype(ranges::begin(declval<T&>())); // freestanding template<range R> using sentinel_t = decltype(ranges::end(declval<R&>())); // freestanding template<range R> using const_iterator_t = decltype(ranges::cbegin(declval<R&>())); // freestanding template<range R> using const_sentinel_t = decltype(ranges::cend(declval<R&>())); // freestanding template<range R> using range_difference_t = iter_difference_t<iterator_t<R>>; // freestanding template<sized_range R> using range_size_t = decltype(ranges::size(declval<R&>())); // freestanding template<range R> using range_value_t = iter_value_t<iterator_t<R>>; // freestanding template<range R> using range_reference_t = iter_reference_t<iterator_t<R>>; // freestanding template<range R> using range_const_reference_t = iter_const_reference_t<iterator_t<R>>; // freestanding template<range R> using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>; // freestanding template<range R> using range_common_reference_t = iter_common_reference_t<iterator_t<R>>; // freestanding // [range.sized], sized ranges template<class> constexpr bool disable_sized_range = false; // freestanding template<class T> concept sized_range = see below; // freestanding // [range.view], views template<class T> constexpr bool enable_view = see below; // freestanding struct view_base {}; // freestanding template<class T> concept view = see below; // freestanding // [range.refinements], other range refinements template<class R, class T> concept output_range = see below; // freestanding template<class T> concept input_range = see below; // freestanding template<class T> concept forward_range = see below; // freestanding template<class T> concept bidirectional_range = see below; // freestanding template<class T> concept random_access_range = see below; // freestanding template<class T> concept contiguous_range = see below; // freestanding template<class T> concept common_range = see below; // freestanding template<class T> concept viewable_range = see below; // freestanding template<class T> concept constant_range = see below; // freestanding // [view.interface], class template view_interface template<class D> requires is_class_v<D> && same_as<D, remove_cv_t<D>> class view_interface; // freestanding // [range.subrange], sub-ranges enum class subrange_kind : bool { unsized, sized }; // freestanding template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = see below> requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>) class subrange; // freestanding template<class I, class S, subrange_kind K> constexpr bool enable_borrowed_range<subrange<I, S, K>> = true; // freestanding template<size_t N, class I, class S, subrange_kind K> requires ((N == 0 && copyable<I>) || N == 1) constexpr auto get(const subrange<I, S, K>& r); // freestanding template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(subrange<I, S, K>&& r); // freestanding } namespace std { using ranges::get; // freestanding } namespace std::ranges { // [range.dangling], dangling iterator handling struct dangling; // freestanding // [range.elementsof], class template elements_of template<range R, class Allocator = allocator<byte>> struct elements_of; template<range R> using borrowed_iterator_t = see below; // freestanding template<range R> using borrowed_subrange_t = see below; // freestanding // [range.utility.conv], range conversions template<class C, input_range R, class... Args> requires (!view<C>) constexpr C to(R&& r, Args&&... args); // freestanding template<template<class...> class C, input_range R, class... Args> constexpr auto to(R&& r, Args&&... args); // freestanding template<class C, class... Args> requires (!view<C>) constexpr auto to(Args&&... args); // freestanding template<template<class...> class C, class... Args> constexpr auto to(Args&&... args); // freestanding // [range.empty], empty view template<class T> requires is_object_v<T> class empty_view; // freestanding template<class T> constexpr bool enable_borrowed_range<empty_view<T>> = true; // freestanding namespace views { template<class T> constexpr empty_view<T> empty{}; // freestanding } // [range.single], single view template<move_constructible T> requires is_object_v<T> class single_view; // freestanding namespace views { inline constexpr unspecified single = unspecified; } // freestanding template<bool Const, class T> using maybe-const = conditional_t<Const, const T, T>; // exposition only // [range.iota], iota view template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t> requires weakly-equality-comparable-with<W, Bound> && copyable<W> class iota_view; // freestanding template<class W, class Bound> constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true; // freestanding namespace views { inline constexpr unspecified iota = unspecified; } // freestanding // [range.repeat], repeat view template<move_constructible T, semiregular Bound = unreachable_sentinel_t> requires see below class repeat_view; // freestanding namespace views { inline constexpr unspecified repeat = unspecified; } // freestanding // [range.istream], istream view template<movable Val, class CharT, class Traits = char_traits<CharT>> requires see below class basic_istream_view; template<class Val> using istream_view = basic_istream_view<Val, char>; template<class Val> using wistream_view = basic_istream_view<Val, wchar_t>; namespace views { template<class T> constexpr unspecified istream = unspecified; } // [range.adaptor.object], range adaptor objects template<class D> requires is_class_v<D> && same_as<D, remove_cv_t<D>> class range_adaptor_closure { }; // freestanding // [range.all], all view namespace views { inline constexpr unspecified all = unspecified; // freestanding template<viewable_range R> using all_t = decltype(all(declval<R>())); // freestanding } // [range.ref.view], ref view template<range R> requires is_object_v<R> class ref_view; // freestanding template<class T> constexpr bool enable_borrowed_range<ref_view<T>> = true; // freestanding // [range.owning.view], owning view template<range R> requires see below class owning_view; // freestanding template<class T> constexpr bool enable_borrowed_range<owning_view<T>> = // freestanding enable_borrowed_range<T>; // [range.as.rvalue], as rvalue view template<view V> requires input_range<V> class as_rvalue_view; // freestanding template<class T> constexpr bool enable_borrowed_range<as_rvalue_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified as_rvalue = unspecified; } // freestanding // [range.filter], filter view template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view; // freestanding namespace views { inline constexpr unspecified filter = unspecified; } // freestanding // [range.transform], transform view template<input_range V, move_constructible F> requires view<V> && is_object_v<F> && regular_invocable<F&, range_reference_t<V>> && can-reference<invoke_result_t<F&, range_reference_t<V>>> class transform_view; // freestanding namespace views { inline constexpr unspecified transform = unspecified; } // freestanding // [range.take], take view template<view> class take_view; // freestanding template<class T> constexpr bool enable_borrowed_range<take_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified take = unspecified; } // freestanding // [range.take.while], take while view template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class take_while_view; // freestanding namespace views { inline constexpr unspecified take_while = unspecified; } // freestanding // [range.drop], drop view template<view V> class drop_view; // freestanding template<class T> constexpr bool enable_borrowed_range<drop_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified drop = unspecified; } // freestanding // [range.drop.while], drop while view template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class drop_while_view; // freestanding template<class T, class Pred> constexpr bool enable_borrowed_range<drop_while_view<T, Pred>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified drop_while = unspecified; } // freestanding // [range.join], join view template<input_range V> requires view<V> && input_range<range_reference_t<V>> class join_view; // freestanding namespace views { inline constexpr unspecified join = unspecified; } // freestanding // [range.join.with], join with view template<input_range V, forward_range Pattern> requires see below class join_with_view; // freestanding namespace views { inline constexpr unspecified join_with = unspecified; } // freestanding // [range.lazy.split], lazy split view template<class R> concept tiny-range = see below; // exposition only template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || tiny-range<Pattern>) class lazy_split_view; // freestanding // [range.split], split view template<forward_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> class split_view; // freestanding namespace views { inline constexpr unspecified lazy_split = unspecified; // freestanding inline constexpr unspecified split = unspecified; // freestanding } // [range.concat], concat view template<input_range... Views> requires see below class concat_view; // freestanding namespace views { inline constexpr unspecified concat = unspecified; } // freestanding // [range.counted], counted view namespace views { inline constexpr unspecified counted = unspecified; } // freestanding // [range.common], common view template<view V> requires (!common_range<V> && copyable<iterator_t<V>>) class common_view; // freestanding template<class T> constexpr bool enable_borrowed_range<common_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified common = unspecified; } // freestanding // [range.reverse], reverse view template<view V> requires bidirectional_range<V> class reverse_view; // freestanding template<class T> constexpr bool enable_borrowed_range<reverse_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified reverse = unspecified; } // freestanding // [range.as.const], as const view template<input_range R> constexpr auto& possibly-const-range(R& r) noexcept { // exposition only if constexpr (input_range<const R>) { return const_cast<const R&>(r); } else { return r; } } template<view V> requires input_range<V> class as_const_view; // freestanding template<class T> constexpr bool enable_borrowed_range<as_const_view<T>> = // freestanding enable_borrowed_range<T>; namespace views { inline constexpr unspecified as_const = unspecified; } // freestanding // [range.elements], elements view template<input_range V, size_t N> requires see below class elements_view; // freestanding template<class T, size_t N> constexpr bool enable_borrowed_range<elements_view<T, N>> = // freestanding enable_borrowed_range<T>; template<class R> using keys_view = elements_view<R, 0>; // freestanding template<class R> using values_view = elements_view<R, 1>; // freestanding namespace views { template<size_t N> constexpr unspecified elements = unspecified; // freestanding inline constexpr auto keys = elements<0>; // freestanding inline constexpr auto values = elements<1>; // freestanding } // [range.enumerate], enumerate view template<view V> requires see below class enumerate_view; // freestanding template<class View> constexpr bool enable_borrowed_range<enumerate_view<View>> = // freestanding enable_borrowed_range<View>; namespace views { inline constexpr unspecified enumerate = unspecified; } // freestanding // [range.zip], zip view template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) class zip_view; // freestanding template<class... Views> constexpr bool enable_borrowed_range<zip_view<Views...>> = // freestanding (enable_borrowed_range<Views> && ...); namespace views { inline constexpr unspecified zip = unspecified; } // freestanding // [range.zip.transform], zip transform view template<move_constructible F, input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> && regular_invocable<F&, range_reference_t<Views>...> && can-reference<invoke_result_t<F&, range_reference_t<Views>...>> class zip_transform_view; // freestanding namespace views { inline constexpr unspecified zip_transform = unspecified; } // freestanding // [range.adjacent], adjacent view template<forward_range V, size_t N> requires view<V> && (N > 0) class adjacent_view; // freestanding template<class V, size_t N> constexpr bool enable_borrowed_range<adjacent_view<V, N>> = // freestanding enable_borrowed_range<V>; namespace views { template<size_t N> constexpr unspecified adjacent = unspecified; // freestanding inline constexpr auto pairwise = adjacent<2>; // freestanding } // [range.adjacent.transform], adjacent transform view template<forward_range V, move_constructible F, size_t N> requires see below class adjacent_transform_view; // freestanding namespace views { template<size_t N> constexpr unspecified adjacent_transform = unspecified; // freestanding inline constexpr auto pairwise_transform = adjacent_transform<2>; // freestanding } // [range.chunk], chunk view template<view V> requires input_range<V> class chunk_view; // freestanding template<view V> requires forward_range<V> class chunk_view<V>; // freestanding template<class V> constexpr bool enable_borrowed_range<chunk_view<V>> = // freestanding forward_range<V> && enable_borrowed_range<V>; namespace views { inline constexpr unspecified chunk = unspecified; } // freestanding // [range.slide], slide view template<forward_range V> requires view<V> class slide_view; // freestanding template<class V> constexpr bool enable_borrowed_range<slide_view<V>> = // freestanding enable_borrowed_range<V>; namespace views { inline constexpr unspecified slide = unspecified; } // freestanding // [range.chunk.by], chunk by view template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class chunk_by_view; // freestanding namespace views { inline constexpr unspecified chunk_by = unspecified; } // freestanding // [range.stride], stride view template<input_range V> requires view<V> class stride_view; // freestanding template<class V> constexpr bool enable_borrowed_range<stride_view<V>> = // freestanding enable_borrowed_range<V>; namespace views { inline constexpr unspecified stride = unspecified; } // freestanding // [range.cartesian], cartesian product view template<input_range First, forward_range... Vs> requires (view<First> && ... && view<Vs>) class cartesian_product_view; // freestanding namespace views { inline constexpr unspecified cartesian_product = unspecified; } // freestanding // [range.cache.latest], cache latest view template<input_range V> requires view<V> class cache_latest_view; namespace views { inline constexpr unspecified cache_latest = unspecified; } } namespace std { namespace views = ranges::views; // freestanding template<class T> struct tuple_size; // freestanding template<size_t I, class T> struct tuple_element; // freestanding template<class I, class S, ranges::subrange_kind K> struct tuple_size<ranges::subrange<I, S, K>> // freestanding : integral_constant<size_t, 2> {}; template<class I, class S, ranges::subrange_kind K> struct tuple_element<0, ranges::subrange<I, S, K>> { // freestanding using type = I; }; template<class I, class S, ranges::subrange_kind K> struct tuple_element<1, ranges::subrange<I, S, K>> { // freestanding using type = S; }; template<class I, class S, ranges::subrange_kind K> struct tuple_element<0, const ranges::subrange<I, S, K>> { // freestanding using type = I; }; template<class I, class S, ranges::subrange_kind K> struct tuple_element<1, const ranges::subrange<I, S, K>> { // freestanding using type = S; }; struct from_range_t { explicit from_range_t() = default; }; // freestanding inline constexpr from_range_t from_range{}; // freestanding }
Within this Clause, for an integer-like type X ([iterator.concept.winc]), make-unsigned-like-t<X> denotes make_unsigned_t<X> if X is an integer type; otherwise, it denotes a corresponding unspecified unsigned-integer-like type of the same width as X.
For an expression x of type X, to-unsigned-like(x) is x explicitly converted to make-unsigned-like-t<X>.
Also within this Clause, make-signed-like-t<X> for an integer-like type X denotes make_signed_t<X> if X is an integer type; otherwise, it denotes a corresponding unspecified signed-integer-like type of the same width as X.

25.3 Range access [range.access]

25.3.1 General [range.access.general]

In addition to being available via inclusion of the <ranges> header, the customization point objects in [range.access] are available when the header <iterator> is included.
Within [range.access], the reified object of a subexpression E denotes
  • the same object as E if E is a glvalue, or
  • the result of applying the temporary materialization conversion ([conv.rval]) to E otherwise.

25.3.2 ranges​::​begin [range.access.begin]

The name ranges​::​begin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​begin(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​begin(E) is ill-formed with no diagnostic required.
  • Otherwise, if T is an array type, ranges​::​begin(E) is expression-equivalent to t + 0.
  • Otherwise, if auto(t.begin()) is a valid expression whose type models input_or_output_iterator, ranges​::​begin(E) is expression-equivalent to auto(t.begin()).
  • Otherwise, if T is a class or enumeration type and auto(begin(t)) is a valid expression whose type models input_or_output_iterator where the meaning of begin is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​begin(E) is expression-equivalent to that expression.
  • Otherwise, ranges​::​begin(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​begin(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​begin(E) is a valid expression, its type models input_or_output_iterator.
— end note]

25.3.3 ranges​::​end [range.access.end]

The name ranges​::​end denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​end(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​end(E) is ill-formed with no diagnostic required.
  • Otherwise, if T is an array of unknown bound, ranges​::​end(E) is ill-formed.
  • Otherwise, if T is an array, ranges​::​end(E) is expression-equivalent to t + extent_v<T>.
  • Otherwise, if auto(t.end()) is a valid expression whose type models sentinel_for<iterator_t<T>> then ranges​::​end(E) is expression-equivalent to auto(t.end()).
  • Otherwise, if T is a class or enumeration type and auto(end(t)) is a valid expression whose type models sentinel_for<iterator_t<T>> where the meaning of end is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​end(E) is expression-equivalent to that expression.
  • Otherwise, ranges​::​end(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​end(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​end(E) is a valid expression, the types S and I of ranges​::​end(E) and ranges​::​begin(E) model sentinel_for<S, I>.
— end note]

25.3.4 ranges​::​cbegin [range.access.cbegin]

The name ranges​::​cbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cbegin(E) is ill-formed.
  • Otherwise, let U be ranges​::​begin(possibly-const-range(t)).
    ranges​::​cbegin(E) is expression-equivalent to const_iterator<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​cbegin(E) is a valid expression, its type models input_or_output_iterator and constant-iterator.
— end note]

25.3.5 ranges​::​cend [range.access.cend]

The name ranges​::​cend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cend(E) is ill-formed.
  • Otherwise, let U be ranges​::​end(possibly-const-range(t)).
    ranges​::​cend(E) is expression-equivalent to const_sentinel<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​cend(E) is a valid expression, the types S and I of the expressions ranges​::​cend(E) and ranges​::​cbegin(E) model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— end note]

25.3.6 ranges​::​rbegin [range.access.rbegin]

The name ranges​::​rbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​rbegin(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​rbegin(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.rbegin()) is a valid expression whose type models input_or_output_iterator, ranges​::​rbegin(E) is expression-equivalent to auto(t.rbegin()).
  • Otherwise, if T is a class or enumeration type and auto(rbegin(t)) is a valid expression whose type models input_or_output_iterator where the meaning of rbegin is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​rbegin(E) is expression-equivalent to that expression.
  • Otherwise, if both ranges​::​begin(t) and ranges​::​end(t) are valid expressions of the same type which models bidirectional_iterator ([iterator.concept.bidir]), ranges​::​rbegin(E) is expression-equivalent to make_reverse_iterator(ranges​::​end(t)).
  • Otherwise, ranges​::​rbegin(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​rbegin(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​rbegin(E) is a valid expression, its type models input_or_output_iterator.
— end note]

25.3.7 ranges​::​rend [range.access.rend]

The name ranges​::​rend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​rend(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​rend(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.rend()) is a valid expression whose type models sentinel_for<decltype(​ranges​::​rbegin(E))> then ranges​::​rend(E) is expression-equivalent to auto(t.rend()).
  • Otherwise, if T is a class or enumeration type and auto(rend(t)) is a valid expression whose type models sentinel_for<decltype(ranges​::​rbegin(E))> where the meaning of rend is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​rend(E) is expression-equivalent to that expression.
  • Otherwise, if both ranges​::​begin(t) and ranges​::​end(t) are valid expressions of the same type which models bidirectional_iterator ([iterator.concept.bidir]), then ranges​::​rend(E) is expression-equivalent to make_reverse_iterator(ranges​::​begin(t)).
  • Otherwise, ranges​::​rend(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​rend(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​rend(E) is a valid expression, the types S and I of the expressions ranges​::​rend(E) and ranges​::​rbegin(E) model sentinel_for<S, I>.
— end note]

25.3.8 ranges​::​crbegin [range.access.crbegin]

The name ranges​::​crbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​crbegin(E) is ill-formed.
  • Otherwise, let U be ranges​::​rbegin(possibly-const-range(t)).
    ranges​::​crbegin(E) is expression-equivalent to const_iterator<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​crbegin(E) is a valid expression, its type models input_or_output_iterator and constant-iterator.
— end note]

25.3.9 ranges​::​crend [range.access.crend]

The name ranges​::​crend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​crend(E) is ill-formed.
  • Otherwise, let U be ranges​::​rend(possibly-const-range(t)).
    ranges​::​crend(E) is expression-equivalent to const_sentinel<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​crend(E) is a valid expression, the types S and I of the expressions ranges​::​crend(E) and ranges​::​crbegin(E) model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— end note]

25.3.10 ranges​::​size [range.prim.size]

The name ranges​::​size denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If T is an array of unknown bound ([dcl.array]), ranges​::​size(E) is ill-formed.
  • Otherwise, if T is an array type, ranges​::​size(E) is expression-equivalent to auto(extent_v<T>).
  • Otherwise, if disable_sized_range<remove_cv_t<T>> ([range.sized]) is false and auto(t.size()) is a valid expression of integer-like type ([iterator.concept.winc]), ranges​::​size(E) is expression-equivalent to auto(​t.size()).
  • Otherwise, if T is a class or enumeration type, disable_sized_range<remove_cv_t<T>> is false and auto(size(t)) is a valid expression of integer-like type where the meaning of size is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​size(E) is expression-equivalent to that expression.
  • Otherwise, if to-unsigned-like(ranges​::​end(t) - ranges​::​begin(t)) ([ranges.syn]) is a valid expression and the types I and S of ranges​::​begin(t) and ranges​::​end(t) (respectively) model both sized_sentinel_for<S, I> ([iterator.concept.sizedsentinel]) and forward_iterator<I>, then ranges​::​size(E) is expression-equivalent to to-unsigned-like(ranges​::​end(t) - ranges​::​begin(t)).
  • Otherwise, ranges​::​size(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​size(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​size(E) is a valid expression, its type is integer-like.
— end note]

25.3.11 ranges​::​ssize [range.prim.ssize]

The name ranges​::​ssize denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
If ranges​::​size(t) is ill-formed, ranges​::​ssize(E) is ill-formed.
Otherwise let D be make-signed-like-t<decltype(ranges​::​​size(t))>, or ptrdiff_t if it is wider than that type; ranges​::​ssize(E) is expression-equivalent to static_cast<D>(ranges​::​size(t)).

25.3.12 ranges​::​empty [range.prim.empty]

The name ranges​::​empty denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If T is an array of unknown bound ([dcl.array]), ranges​::​empty(E) is ill-formed.
  • Otherwise, if bool(t.empty()) is a valid expression, ranges​::​empty(E) is expression-equivalent to bool(t.empty()).
  • Otherwise, if (ranges​::​size(t) == 0) is a valid expression, ranges​::​empty(E) is expression-equivalent to (ranges​::​size(t) == 0).
  • Otherwise, if bool(ranges​::​begin(t) == ranges​::​end(t)) is a valid expression and the type of ranges​::​begin(t) models forward_iterator, ranges​::​empty(E) is expression-equivalent to bool(​ranges​::​begin(t) == ranges​::​end(t)).
  • Otherwise, ranges​::​empty(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​empty(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​empty(E) is a valid expression, it has type bool.
— end note]

25.3.13 ranges​::​data [range.prim.data]

The name ranges​::​data denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​data(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​data(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.data()) is a valid expression of pointer to object type, ranges​::​data(E) is expression-equivalent to auto(t.data()).
  • Otherwise, if ranges​::​begin(t) is a valid expression whose type models contiguous_iterator, ranges​::​data(E) is expression-equivalent to to_address(ranges​::​begin(t)).
  • Otherwise, ranges​::​data(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​data(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​data(E) is a valid expression, it has pointer to object type.
— end note]

25.3.14 ranges​::​cdata [range.prim.cdata]

template<class T> constexpr auto as-const-pointer(const T* p) noexcept { return p; } // exposition only
The name ranges​::​cdata denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cdata(E) is ill-formed.
  • Otherwise, ranges​::​cdata(E) is expression-equivalent to as-const-pointer(ranges​::​data(possibly-const-range(t))).
[Note 1: 
Whenever ranges​::​cdata(E) is a valid expression, it has pointer to constant object type.
— end note]

25.4 Range requirements [range.req]

25.4.1 General [range.req.general]

Ranges are an abstraction that allows a C++ program to operate on elements of data structures uniformly.
Calling ranges​::​begin on a range returns an object whose type models input_or_output_iterator ([iterator.concept.iterator]).
Calling ranges​::​end on a range returns an object whose type S, together with the type I of the object returned by ranges​::​begin, models sentinel_for<S, I>.
The library formalizes the interfaces, semantics, and complexity of ranges to enable algorithms and range adaptors that work efficiently on different types of sequences.
The range concept requires that ranges​::​begin and ranges​::​end return an iterator and a sentinel, respectively.
The sized_range concept refines range with the requirement that ranges​::​size be amortized .
The view concept specifies requirements on a range type to provide operations with predictable complexity.
Several refinements of range group requirements that arise frequently in concepts and algorithms.
Common ranges are ranges for which ranges​::​begin and ranges​::​end return objects of the same type.
Random access ranges are ranges for which ranges​::​begin returns a type that models random_access_iterator ([iterator.concept.random.access]).
(Contiguous, bidirectional, forward, input, and output ranges are defined similarly.)
Viewable ranges can be converted to views.

25.4.2 Ranges [range.range]

The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.
template<class T> concept range = requires(T& t) { ranges::begin(t); // sometimes equality-preserving (see below) ranges::end(t); };
Given an expression t such that decltype((t)) is T&, T models range only if
  • [ranges​::​begin(t), ranges​::​end(t)) denotes a range ([iterator.requirements.general]),
  • both ranges​::​begin(t) and ranges​::​end(t) are amortized constant time and non-modifying, and
  • if the type of ranges​::​begin(t) models forward_iterator, ranges​::​begin(t) is equality-preserving.
[Note 1: 
Equality preservation of both ranges​::​begin and ranges​::​end enables passing a range whose iterator type models forward_iterator to multiple algorithms and making multiple passes over the range by repeated calls to ranges​::​begin and ranges​::​end.
Since ranges​::​begin is not required to be equality-preserving when the return type does not model forward_iterator, it is possible for repeated calls to not return equal values or to not be well-defined.
— end note]
template<class T> concept borrowed_range = range<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
Let U be remove_reference_t<T> if T is an rvalue reference type, and T otherwise.
Given a variable u of type U, T models borrowed_range only if the validity of iterators obtained from u is not tied to the lifetime of that variable.
[Note 2: 
Since the validity of iterators is not tied to the lifetime of a variable whose type models borrowed_range, a function with a parameter of such a type can return iterators obtained from it without danger of dangling.
— end note]
template<class> constexpr bool enable_borrowed_range = false;
Remarks: Pursuant to [namespace.std], users may specialize enable_borrowed_range for cv-unqualified program-defined types.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.
[Example 1: 
Each specialization S of class template subrange ([range.subrange]) models borrowed_range because
  • enable_borrowed_range<S> is specialized to have the value true, and
  • S's iterators do not have validity tied to the lifetime of an S object because they are “borrowed” from some other range.
— end example]

25.4.3 Sized ranges [range.sized]

The sized_range concept refines range with the requirement that the number of elements in the range can be determined in amortized constant time using ranges​::​size.
template<class T> concept sized_range = range<T> && requires(T& t) { ranges::size(t); };
Given an lvalue t of type remove_reference_t<T>, T models sized_range only if
  • ranges​::​size(t) is amortized , does not modify t, and is equal to ranges​::​distance(​ranges​::​begin(t), ranges​::​end(t)), and
  • if iterator_t<T> models forward_iterator, ranges​::​size(t) is well-defined regardless of the evaluation of ranges​::​begin(t).
    [Note 1: 
    ranges​::​size(t) is otherwise not required to be well-defined after evaluating ranges​::​begin(t).
    For example, it is possible for ranges​::​size(t) to be well-defined for a sized_range whose iterator type does not model forward_iterator only if evaluated before the first call to ranges​::​begin(t).
    — end note]
template<class> constexpr bool disable_sized_range = false;
Remarks: Pursuant to [namespace.std], users may specialize disable_sized_range for cv-unqualified program-defined types.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.
[Note 2: 
disable_sized_range allows use of range types with the library that satisfy but do not in fact model sized_range.
— end note]

25.4.4 Views [range.view]

The view concept specifies the requirements of a range type that has the semantic properties below, which make it suitable for use in constructing range adaptor pipelines ([range.adaptors]).
template<class T> concept view = range<T> && movable<T> && enable_view<T>;
T models view only if
  • T has move construction; and
  • move assignment of an object of type T is no more complex than destruction followed by move construction; and
  • if N copies and/or moves are made from an object of type T that contained M elements, then those N objects have destruction; and
  • copy_constructible<T> is false, or T has copy construction; and
  • copyable<T> is false, or copy assignment of an object of type T is no more complex than destruction followed by copy construction.
[Note 1: 
The constraints on copying and moving imply that a moved-from object of type T has destruction.
— end note]
[Example 1: 
Examples of views are:
  • A range type that wraps a pair of iterators.
  • A range type that holds its elements by shared_ptr and shares ownership with all its copies.
  • A range type that generates its elements on demand.
A container such as vector<string> does not meet the semantic requirements of view since copying the container copies all of the elements, which cannot be done in constant time.
— end example]
Since the difference between range and view is largely semantic, the two are differentiated with the help of enable_view.
template<class T> constexpr bool is-derived-from-view-interface = see below; // exposition only template<class T> constexpr bool enable_view = derived_from<T, view_base> || is-derived-from-view-interface<T>;
For a type T, is-derived-from-view-interface<T> is true if and only if T has exactly one public base class view_interface<U> for some type U and T has no base classes of type view_interface<V> for any other type V.
Remarks: Pursuant to [namespace.std], users may specialize enable_view to true for cv-unqualified program-defined types which model view, and false for types which do not.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.

25.4.5 Other range refinements [range.refinements]

The output_range concept specifies requirements of a range type for which ranges​::​begin returns a model of output_iterator ([iterator.concept.output]).
template<class R, class T> concept output_range = range<R> && output_iterator<iterator_t<R>, T>; template<class T> concept input_range = range<T> && input_iterator<iterator_t<T>>; template<class T> concept forward_range = input_range<T> && forward_iterator<iterator_t<T>>; template<class T> concept bidirectional_range = forward_range<T> && bidirectional_iterator<iterator_t<T>>; template<class T> concept random_access_range = bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
contiguous_range additionally requires that the ranges​::​data customization point object ([range.prim.data]) is usable with the range.
template<class T> concept contiguous_range = random_access_range<T> && contiguous_iterator<iterator_t<T>> && requires(T& t) { { ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>; };
Given an expression t such that decltype((t)) is T&, T models contiguous_range only if to_address(​ranges​::​begin(t)) == ranges​::​data(t) is true.
The common_range concept specifies requirements of a range type for which ranges​::​begin and ranges​::​end return objects of the same type.
[Example 1: 
The standard containers ([containers]) model common_range.
— end example]
template<class T> concept common_range = range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
template<class R> constexpr bool is-initializer-list = see below; // exposition only
For a type R, is-initializer-list<R> is true if and only if remove_cvref_t<R> is a specialization of initializer_list.
The viewable_range concept specifies the requirements of a range type that can be converted to a view safely.
template<class T> concept viewable_range = range<T> && ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) || (!view<remove_cvref_t<T>> && (is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
The constant_range concept specifies the requirements of a range type whose elements are not modifiable.
template<class T> concept constant_range = input_range<T> && constant-iterator<iterator_t<T>>;

25.5 Range utilities [range.utility]

25.5.1 General [range.utility.general]

The components in [range.utility] are general utilities for representing and manipulating ranges.

25.5.2 Helper concepts [range.utility.helpers]

Many of the types in [range.utility] are specified in terms of the following exposition-only concepts: template<class R> concept simple-view = // exposition only view<R> && range<const R> && same_as<iterator_t<R>, iterator_t<const R>> && same_as<sentinel_t<R>, sentinel_t<const R>>; template<class I> concept has-arrow = // exposition only input_iterator<I> && (is_pointer_v<I> || requires(const I i) { i.operator->(); }); template<class T, class U> concept different-from = // exposition only !same_as<remove_cvref_t<T>, remove_cvref_t<U>>; template<class R> concept range-with-movable-references = // exposition only input_range<R> && move_constructible<range_reference_t<R>> && move_constructible<range_rvalue_reference_t<R>>;

25.5.3 View interface [view.interface]

25.5.3.1 General [view.interface.general]

The class template view_interface is a helper for defining view-like types that offer a container-like interface.
It is parameterized with the type that is derived from it.
namespace std::ranges { template<class D> requires is_class_v<D> && same_as<D, remove_cv_t<D>> class view_interface { private: constexpr D& derived() noexcept { // exposition only return static_cast<D&>(*this); } constexpr const D& derived() const noexcept { // exposition only return static_cast<const D&>(*this); } public: constexpr bool empty() requires sized_range<D> || forward_range<D> { if constexpr (sized_range<D>) return ranges::size(derived()) == 0; else return ranges::begin(derived()) == ranges::end(derived()); } constexpr bool empty() const requires sized_range<const D> || forward_range<const D> { if constexpr (sized_range<const D>) return ranges::size(derived()) == 0; else return ranges::begin(derived()) == ranges::end(derived()); } constexpr auto cbegin() requires input_range<D> { return ranges::cbegin(derived()); } constexpr auto cbegin() const requires input_range<const D> { return ranges::cbegin(derived()); } constexpr auto cend() requires input_range<D> { return ranges::cend(derived()); } constexpr auto cend() const requires input_range<const D> { return ranges::cend(derived()); } constexpr explicit operator bool() requires requires { ranges::empty(derived()); } { return !ranges::empty(derived()); } constexpr explicit operator bool() const requires requires { ranges::empty(derived()); } { return !ranges::empty(derived()); } constexpr auto data() requires contiguous_iterator<iterator_t<D>> { return to_address(ranges::begin(derived())); } constexpr auto data() const requires range<const D> && contiguous_iterator<iterator_t<const D>> { return to_address(ranges::begin(derived())); } constexpr auto size() requires forward_range<D> && sized_sentinel_for<sentinel_t<D>, iterator_t<D>> { return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived())); } constexpr auto size() const requires forward_range<const D> && sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> { return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived())); } constexpr decltype(auto) front() requires forward_range<D>; constexpr decltype(auto) front() const requires forward_range<const D>; constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>; constexpr decltype(auto) back() const requires bidirectional_range<const D> && common_range<const D>; template<random_access_range R = D> constexpr decltype(auto) operator[](range_difference_t<R> n) { return ranges::begin(derived())[n]; } template<random_access_range R = const D> constexpr decltype(auto) operator[](range_difference_t<R> n) const { return ranges::begin(derived())[n]; } }; }
The template parameter D for view_interface may be an incomplete type.
Before any member of the resulting specialization of view_interface other than special member functions is referenced, D shall be complete, and model both derived_from<view_interface<D>> and view.

25.5.3.2 Members [view.interface.members]

constexpr decltype(auto) front() requires forward_range<D>; constexpr decltype(auto) front() const requires forward_range<const D>;
Preconditions: !empty() is true.
Effects: Equivalent to: return *ranges​::​begin(derived());
constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>; constexpr decltype(auto) back() const requires bidirectional_range<const D> && common_range<const D>;
Preconditions: !empty() is true.
Effects: Equivalent to: return *ranges​::​prev(ranges​::​end(derived()));

25.5.4 Sub-ranges [range.subrange]

25.5.4.1 General [range.subrange.general]

The subrange class template combines together an iterator and a sentinel into a single object that models the view concept.
Additionally, it models the sized_range concept when the final template parameter is subrange_kind​::​sized.
namespace std::ranges { template<class From, class To> concept uses-nonqualification-pointer-conversion = // exposition only is_pointer_v<From> && is_pointer_v<To> && !convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>; template<class From, class To> concept convertible-to-non-slicing = // exposition only convertible_to<From, To> && !uses-nonqualification-pointer-conversion<decay_t<From>, decay_t<To>>; template<class T, class U, class V> concept pair-like-convertible-from = // exposition only !range<T> && !is_reference_v<T> && pair-like<T> && constructible_from<T, U, V> && convertible-to-non-slicing<U, tuple_element_t<0, T>> && convertible_to<V, tuple_element_t<1, T>>; template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized> requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>) class subrange : public view_interface<subrange<I, S, K>> { private: static constexpr bool StoreSize = // exposition only K == subrange_kind::sized && !sized_sentinel_for<S, I>; I begin_ = I(); // exposition only S end_ = S(); // exposition only make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only // if StoreSize is true public: subrange() requires default_initializable<I> = default; constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize); constexpr subrange(convertible-to-non-slicing<I> auto i, S s, make-unsigned-like-t<iter_difference_t<I>> n) requires (K == subrange_kind::sized); template<different-from<subrange> R> requires borrowed_range<R> && convertible-to-non-slicing<iterator_t<R>, I> && convertible_to<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>); template<borrowed_range R> requires convertible-to-non-slicing<iterator_t<R>, I> && convertible_to<sentinel_t<R>, S> constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n) requires (K == subrange_kind::sized) : subrange{ranges::begin(r), ranges::end(r), n} {} template<different-from<subrange> PairLike> requires pair-like-convertible-from<PairLike, const I&, const S&> constexpr operator PairLike() const; constexpr I begin() const requires copyable<I>; constexpr I begin() requires (!copyable<I>); constexpr S end() const; constexpr bool empty() const; constexpr make-unsigned-like-t<iter_difference_t<I>> size() const requires (K == subrange_kind::sized); constexpr subrange next(iter_difference_t<I> n = 1) const & requires forward_iterator<I>; constexpr subrange next(iter_difference_t<I> n = 1) &&; constexpr subrange prev(iter_difference_t<I> n = 1) const requires bidirectional_iterator<I>; constexpr subrange& advance(iter_difference_t<I> n); }; template<input_or_output_iterator I, sentinel_for<I> S> subrange(I, S) -> subrange<I, S>; template<input_or_output_iterator I, sentinel_for<I> S> subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) -> subrange<I, S, subrange_kind::sized>; template<borrowed_range R> subrange(R&&) -> subrange<iterator_t<R>, sentinel_t<R>, (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>) ? subrange_kind::sized : subrange_kind::unsized>; template<borrowed_range R> subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) -> subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>; }

25.5.4.2 Constructors and conversions [range.subrange.ctor]

constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
Preconditions: [i, s) is a valid range.
Effects: Initializes begin_ with std​::​move(i) and end_ with s.
constexpr subrange(convertible-to-non-slicing<I> auto i, S s, make-unsigned-like-t<iter_difference_t<I>> n) requires (K == subrange_kind::sized);
Preconditions: [i, s) is a valid range, and n == to-unsigned-like(ranges​::​distance(i, s)) is true.
Effects: Initializes begin_ with std​::​move(i) and end_ with s.
If StoreSize is true, initializes size_ with n.
[Note 1: 
Accepting the length of the range and storing it to later return from size() enables subrange to model sized_range even when it stores an iterator and sentinel that do not model sized_sentinel_for.
— end note]
template<different-from<subrange> R> requires borrowed_range<R> && convertible-to-non-slicing<iterator_t<R>, I> && convertible_to<sentinel_t<R>, S> constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
Effects: Equivalent to:
  • If StoreSize is true, subrange(r, static_cast<decltype(size_)>(ranges​::​size(r))).
  • Otherwise, subrange(ranges​::​begin(r), ranges​::​end(r)).
template<different-from<subrange> PairLike> requires pair-like-convertible-from<PairLike, const I&, const S&> constexpr operator PairLike() const;
Effects: Equivalent to: return PairLike(begin_, end_);

25.5.4.3 Accessors [range.subrange.access]

constexpr I begin() const requires copyable<I>;
Effects: Equivalent to: return begin_;
constexpr I begin() requires (!copyable<I>);
Effects: Equivalent to: return std​::​move(begin_);
constexpr S end() const;
Effects: Equivalent to: return end_;
constexpr bool empty() const;
Effects: Equivalent to: return begin_ == end_;
constexpr make-unsigned-like-t<iter_difference_t<I>> size() const requires (K == subrange_kind::sized);
Effects:
  • If StoreSize is true, equivalent to: return size_;
  • Otherwise, equivalent to: return to-unsigned-like(end_ - begin_);
constexpr subrange next(iter_difference_t<I> n = 1) const & requires forward_iterator<I>;
Effects: Equivalent to: auto tmp = *this; tmp.advance(n); return tmp;
constexpr subrange next(iter_difference_t<I> n = 1) &&;
Effects: Equivalent to: advance(n); return std::move(*this);
constexpr subrange prev(iter_difference_t<I> n = 1) const requires bidirectional_iterator<I>;
Effects: Equivalent to: auto tmp = *this; tmp.advance(-n); return tmp;
constexpr subrange& advance(iter_difference_t<I> n);
Effects: Equivalent to: if constexpr (bidirectional_iterator<I>) { if (n < 0) { ranges::advance(begin_, n); if constexpr (StoreSize) size_ += to-unsigned-like(-n); return *this; } } auto d = n - ranges::advance(begin_, n, end_); if constexpr (StoreSize) size_ -= to-unsigned-like(d); return *this;
template<size_t N, class I, class S, subrange_kind K> requires ((N == 0 && copyable<I>) || N == 1) constexpr auto get(const subrange<I, S, K>& r); template<size_t N, class I, class S, subrange_kind K> requires (N < 2) constexpr auto get(subrange<I, S, K>&& r);
Effects: Equivalent to: if constexpr (N == 0) return r.begin(); else return r.end();

25.5.5 Dangling iterator handling [range.dangling]

The type dangling is used together with the template aliases borrowed_iterator_t and borrowed_subrange_t.
When an algorithm that typically returns an iterator into, or a subrange of, a range argument is called with an rvalue range argument that does not model borrowed_range ([range.range]), the return value possibly refers to a range whose lifetime has ended.
In such cases, the type dangling is returned instead of an iterator or subrange.
namespace std::ranges { struct dangling { constexpr dangling() noexcept = default; constexpr dangling(auto&&...) noexcept {} }; }
[Example 1: vector<int> f(); auto result1 = ranges::find(f(), 42); // #1 static_assert(same_as<decltype(result1), ranges::dangling>); auto vec = f(); auto result2 = ranges::find(vec, 42); // #2 static_assert(same_as<decltype(result2), vector<int>::iterator>); auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3 static_assert(same_as<decltype(result3), vector<int>::iterator>);
The call to ranges​::​find at #1 returns ranges​::​dangling since f() is an rvalue vector; it is possible for the vector to be destroyed before a returned iterator is dereferenced.
However, the calls at #2 and #3 both return iterators since the lvalue vec and specializations of subrange model borrowed_range.
— end example]
For a type R that models range:
  • if R models borrowed_range, then borrowed_iterator_t<R> denotes iterator_t<R>, and borrowed_subrange_t<R> denotes subrange<iterator_t<R>>;
  • otherwise, both borrowed_iterator_t<R> and borrowed_subrange_t<R> denote dangling.

25.5.6 Class template elements_of [range.elementsof]

Specializations of elements_of encapsulate a range and act as a tag in overload sets to disambiguate when a range should be treated as a sequence rather than a single value.
[Example 1: template<bool YieldElements> generator<any> f(ranges::input_range auto&& r) { if constexpr (YieldElements) co_yield ranges::elements_of(r); // yield each element of r else co_yield r; // yield r as a single value } — end example]
namespace std::ranges { template<range R, class Allocator = allocator<byte>> struct elements_of { [[no_unique_address]] R range; [[no_unique_address]] Allocator allocator = Allocator(); }; template<class R, class Allocator = allocator<byte>> elements_of(R&&, Allocator = Allocator()) -> elements_of<R&&, Allocator>; }

25.5.7 Range conversions [range.utility.conv]

25.5.7.1 General [range.utility.conv.general]

The range conversion functions construct an object (usually a container) from a range, by using a constructor taking a range, a 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.
ranges​::​to is applied recursively, allowing the conversion of a range of ranges.
[Example 1: string_view str = "the quick brown fox"; auto words = views::split(str, ' ') | to<vector<string>>(); // words is vector<string>{"the", "quick", "brown", "fox"} — end example]
Let reservable-container be defined as follows: template<class Container> constexpr bool reservable-container = // exposition only sized_range<Container> && requires(Container& c, range_size_t<Container> n) { c.reserve(n); { c.capacity() } -> same_as<decltype(n)>; { c.max_size() } -> same_as<decltype(n)>; };
Let container-appendable be defined as follows: template<class Container, class Ref> constexpr bool container-appendable = // exposition only requires(Container& c, Ref&& ref) { requires (requires { c.emplace_back(std::forward<Ref>(ref)); } || requires { c.push_back(std::forward<Ref>(ref)); } || requires { c.emplace(c.end(), std::forward<Ref>(ref)); } || requires { c.insert(c.end(), std::forward<Ref>(ref)); }); };
Let container-append be defined as follows: template<class Container> constexpr auto container-append(Container& c) { // exposition only return [&c]<class Ref>(Ref&& ref) { if constexpr (requires { c.emplace_back(declval<Ref>()); }) c.emplace_back(std::forward<Ref>(ref)); else if constexpr (requires { c.push_back(declval<Ref>()); }) c.push_back(std::forward<Ref>(ref)); else if constexpr (requires { c.emplace(c.end(), declval<Ref>()); }) c.emplace(c.end(), std::forward<Ref>(ref)); else c.insert(c.end(), std::forward<Ref>(ref)); }; }

25.5.7.2 ranges​::​to [range.utility.conv.to]

template<class C, input_range R, class... Args> requires (!view<C>) constexpr C to(R&& r, Args&&... args);
Mandates: C is a cv-unqualified class type.
Returns: An object of type C constructed from the elements of r in the following manner:
  • If C does not satisfy input_range or convertible_to<range_reference_t<R>, range_value_t<C>> is true:
  • Otherwise, if input_range<range_reference_t<R>> is true: to<C>(ref_view(r) | views::transform([](auto&& elem) { return to<range_value_t<C>>(std::forward<decltype(elem)>(elem)); }), std::forward<Args>(args)...);
  • Otherwise, the program is ill-formed.
template<template<class...> class C, input_range R, class... Args> constexpr auto to(R&& r, Args&&... args);
Let input-iterator be an exposition-only type: struct input-iterator { // exposition only using iterator_category = input_iterator_tag; using value_type = range_value_t<R>; using difference_type = ptrdiff_t; using pointer = add_pointer_t<range_reference_t<R>>; using reference = range_reference_t<R>; reference operator*() const; pointer operator->() const; input-iterator& operator++(); input-iterator operator++(int); bool operator==(const input-iterator&) const; };
[Note 1: 
input-iterator meets the syntactic requirements of Cpp17InputIterator.
— end note]
Let DEDUCE_EXPR be defined as follows:
  • C(declval<R>(), declval<Args>()...) if that is a valid expression,
  • otherwise, C(from_range, declval<R>(), declval<Args>()...) if that is a valid expression,
  • otherwise, C(declval<input-iterator>(), declval<input-iterator>(), declval<Args>()...) if that is a valid expression,
  • otherwise, the program is ill-formed.
Returns: to<decltype(DEDUCE_EXPR)>(std​::​forward<R>(r), std​::​forward<Args>(args)...).

25.5.7.3 ranges​::​to adaptors [range.utility.conv.adaptors]

template<class C, class... Args> requires (!view<C>) constexpr auto to(Args&&... args); template<template<class...> class C, class... Args> constexpr auto to(Args&&... args);
Mandates: For the first overload, C is a cv-unqualified class type.
Returns: A range adaptor closure object ([range.adaptor.object]) f that is a perfect forwarding call wrapper ([func.require]) with the following properties:
  • It has no target object.
  • Its bound argument entities bound_args consist of objects of types decay_t<Args>... direct-non-list-initialized with std​::​forward<Args>(args)..., respectively.
  • Its call pattern is to<C>(r, bound_args...), where r is the argument used in a function call expression of f.

25.6 Range factories [range.factories]

25.6.1 General [range.factories.general]

Subclause [range.factories] defines range factories, which are utilities to create a view.
Range factories are declared in namespace std​::​ranges​::​views.

25.6.2 Empty view [range.empty]

25.6.2.1 Overview [range.empty.overview]

empty_view produces a view of no elements of a particular type.
[Example 1: auto e = views::empty<int>; static_assert(ranges::empty(e)); static_assert(0 == e.size()); — end example]

25.6.2.2 Class template empty_view [range.empty.view]

namespace std::ranges { template<class T> requires is_object_v<T> class empty_view : public view_interface<empty_view<T>> { public: static constexpr T* begin() noexcept { return nullptr; } static constexpr T* end() noexcept { return nullptr; } static constexpr T* data() noexcept { return nullptr; } static constexpr size_t size() noexcept { return 0; } static constexpr bool empty() noexcept { return true; } }; }

25.6.3 Single view [range.single]

25.6.3.1 Overview [range.single.overview]

single_view produces a view that contains exactly one element of a specified value.
The name views​::​single denotes a customization point object ([customization.point.object]).
Given a subexpression E, the expression views​::​single(E) is expression-equivalent to single_view<decay_t<decltype((E))>>(E).
[Example 1: for (int i : views::single(4)) cout << i; // prints 4 — end example]

25.6.3.2 Class template single_view [range.single.view]

namespace std::ranges { template<move_constructible T> requires is_object_v<T> class single_view : public view_interface<single_view<T>> { private: movable-box<T> value_; // exposition only (see [range.move.wrap]) public: single_view() requires default_initializable<T> = default; constexpr explicit single_view(const T& t) requires copy_constructible<T>; constexpr explicit single_view(T&& t); template<class... Args> requires constructible_from<T, Args...> constexpr explicit single_view(in_place_t, Args&&... args); constexpr T* begin() noexcept; constexpr const T* begin() const noexcept; constexpr T* end() noexcept; constexpr const T* end() const noexcept; static constexpr bool empty() noexcept; static constexpr size_t size() noexcept; constexpr T* data() noexcept; constexpr const T* data() const noexcept; }; template<class T> single_view(T) -> single_view<T>; }
constexpr explicit single_view(const T& t) requires copy_constructible<T>;
Effects: Initializes value_ with t.
constexpr explicit single_view(T&& t);
Effects: Initializes value_ with std​::​move(t).
template<class... Args> requires constructible_from<T, Args...> constexpr explicit single_view(in_place_t, Args&&... args);
Effects: Initializes value_ as if by value_{in_place, std​::​forward<Args>(args)...}.
constexpr T* begin() noexcept; constexpr const T* begin() const noexcept;
Effects: Equivalent to: return data();
constexpr T* end() noexcept; constexpr const T* end() const noexcept;
Effects: Equivalent to: return data() + 1;
static constexpr bool empty() noexcept;
Effects: Equivalent to: return false;
static constexpr size_t size() noexcept;
Effects: Equivalent to: return 1;
constexpr T* data() noexcept; constexpr const T* data() const noexcept;
Effects: Equivalent to: return value_.operator->();

25.6.4 Iota view [range.iota]

25.6.4.1 Overview [range.iota.overview]

iota_view generates a sequence of elements by repeatedly incrementing an initial value.
The name views​::​iota denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expressions views​::​iota(E) and views​::​iota(E, F) are expression-equivalent to iota_view<decay_t<decltype((E))>>(E) and iota_view(E, F), respectively.
[Example 1: for (int i : views::iota(1, 10)) cout << i << ' '; // prints 1 2 3 4 5 6 7 8 9 — end example]

25.6.4.2 Class template iota_view [range.iota.view]

namespace std::ranges { template<class I> concept decrementable = see below; // exposition only template<class I> concept advanceable = see below; // exposition only template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t> requires weakly-equality-comparable-with<W, Bound> && copyable<W> class iota_view : public view_interface<iota_view<W, Bound>> { private: // [range.iota.iterator], class iota_view​::​iterator struct iterator; // exposition only // [range.iota.sentinel], class iota_view​::​sentinel struct sentinel; // exposition only W value_ = W(); // exposition only Bound bound_ = Bound(); // exposition only public: iota_view() requires default_initializable<W> = default; constexpr explicit iota_view(W value); constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound); constexpr explicit iota_view(iterator first, see below last); constexpr iterator begin() const; constexpr auto end() const; constexpr iterator end() const requires same_as<W, Bound>; constexpr bool empty() const; constexpr auto size() const requires see below; }; template<class W, class Bound> requires (!is-integer-like<W> || !is-integer-like<Bound> || (is-signed-integer-like<W> == is-signed-integer-like<Bound>)) iota_view(W, Bound) -> iota_view<W, Bound>; }
Let IOTA-DIFF-T(W) be defined as follows:
  • If W is not an integral type, or if it is an integral type and sizeof(iter_difference_t<W>) is greater than sizeof(W), then IOTA-DIFF-T(W) denotes iter_difference_t<W>.
  • Otherwise, IOTA-DIFF-T(W) is a signed integer type of width greater than the width of W if such a type exists.
  • Otherwise, IOTA-DIFF-T(W) is an unspecified signed-integer-like type ([iterator.concept.winc]) of width not less than the width of W.
    [Note 1: 
    It is unspecified whether this type satisfies weakly_incrementable.
    — end note]
The exposition-only decrementable concept is equivalent to:
template<class I> concept decrementable = // exposition only incrementable<I> && requires(I i) { { --i } -> same_as<I&>; { i-- } -> same_as<I>; };
When an object is in the domain of both pre- and post-decrement, the object is said to be decrementable.
Let a and b be equal objects of type I.
I models decrementable only if
  • If a and b are decrementable, then the following are all true:
  • If a and b are incrementable, then bool(--(++a) == b).
The exposition-only advanceable concept is equivalent to:
template<class I> concept advanceable = // exposition only decrementable<I> && totally_ordered<I> && requires(I i, const I j, const IOTA-DIFF-T(I) n) { { i += n } -> same_as<I&>; { i -= n } -> same_as<I&>; I(j + n); I(n + j); I(j - n); { j - j } -> convertible_to<IOTA-DIFF-T(I)>; };
Let D be IOTA-DIFF-T(I).
Let a and b be objects of type I such that b is reachable from a after n applications of ++a, for some value n of type D.
I models advanceable only if
  • (a += n) is equal to b.
  • addressof(a += n) is equal to addressof(a).
  • I(a + n) is equal to (a += n).
  • For any two positive values x and y of type D, if I(a + D(x + y)) is well-defined, then I(a + D(x + y)) is equal to I(I(a + x) + y).
  • I(a + D(0)) is equal to a.
  • If I(a + D(n - 1)) is well-defined, then I(a + n) is equal to [](I c) { return ++c; }(I(a + D(n - 1))).
  • (b += -n) is equal to a.
  • (b -= n) is equal to a.
  • addressof(b -= n) is equal to addressof(b).
  • I(b - n) is equal to (b -= n).
  • D(b - a) is equal to n.
  • D(a - b) is equal to D(-n).
  • bool(a <= b) is true.
constexpr explicit iota_view(W value);
Preconditions: Bound denotes unreachable_sentinel_t or Bound() is reachable from value.
When W and Bound model totally_ordered_with, then bool(value <= Bound()) is true.
Effects: Initializes value_ with value.
constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
Preconditions: Bound denotes unreachable_sentinel_t or bound is reachable from value.
When W and Bound model totally_ordered_with, then bool(value <= bound) is true.
Effects: Initializes value_ with value and bound_ with bound.
constexpr explicit iota_view(iterator first, see below last);
Effects: Equivalent to:
  • If same_as<W, Bound> is true, iota_view(first.value_, last.value_).
  • Otherwise, if Bound denotes unreachable_sentinel_t, iota_view(first.value_, last).
  • Otherwise, iota_view(first.value_, last.bound_).
Remarks: The type of last is:
constexpr iterator begin() const;
Effects: Equivalent to: return iterator{value_};
constexpr auto end() const;
Effects: Equivalent to: if constexpr (same_as<Bound, unreachable_sentinel_t>) return unreachable_sentinel; else return sentinel{bound_};
constexpr iterator end() const requires same_as<W, Bound>;
Effects: Equivalent to: return iterator{bound_};
constexpr bool empty() const;
Effects: Equivalent to: return value_ == bound_;
constexpr auto size() const requires see below;
Effects: Equivalent to: if constexpr (is-integer-like<W> && is-integer-like<Bound>) return (value_ < 0) ? ((bound_ < 0) ? to-unsigned-like(-value_) - to-unsigned-like(-bound_) : to-unsigned-like(bound_) + to-unsigned-like(-value_)) : to-unsigned-like(bound_) - to-unsigned-like(value_); else return to-unsigned-like(bound_ - value_);
Remarks: The expression in the requires-clause is equivalent to: (same_as<W, Bound> && advanceable<W>) || (is-integer-like<W> && is-integer-like<Bound>) || sized_sentinel_for<Bound, W>

25.6.4.3 Class iota_view​::​iterator [range.iota.iterator]

namespace std::ranges { template<weakly_incrementable W, semiregular Bound> requires weakly-equality-comparable-with<W, Bound> && copyable<W> struct iota_view<W, Bound>::iterator { private: W value_ = W(); // exposition only public: using iterator_concept = see below; using iterator_category = input_iterator_tag; // present only if W models incrementable and // IOTA-DIFF-T(W) is an integral type using value_type = W; using difference_type = IOTA-DIFF-T(W); iterator() requires default_initializable<W> = default; constexpr explicit iterator(W value); constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>); constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires incrementable<W>; constexpr iterator& operator--() requires decrementable<W>; constexpr iterator operator--(int) requires decrementable<W>; constexpr iterator& operator+=(difference_type n) requires advanceable<W>; constexpr iterator& operator-=(difference_type n) requires advanceable<W>; constexpr W operator[](difference_type n) const requires advanceable<W>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<W>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires totally_ordered<W>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires totally_ordered<W>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires totally_ordered<W>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires totally_ordered<W>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires totally_ordered<W> && three_way_comparable<W>; friend constexpr iterator operator+(iterator i, difference_type n) requires advanceable<W>; friend constexpr iterator operator+(difference_type n, iterator i) requires advanceable<W>; friend constexpr iterator operator-(iterator i, difference_type n) requires advanceable<W>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires advanceable<W>; }; }
iterator​::​iterator_concept is defined as follows:
  • If W models advanceable, then iterator_concept is random_access_iterator_tag.
  • Otherwise, if W models decrementable, then iterator_concept is bidirectional_iterator_tag.
  • Otherwise, if W models incrementable, then iterator_concept is forward_iterator_tag.
  • Otherwise, iterator_concept is input_iterator_tag.
[Note 1: 
Overloads for iter_move and iter_swap are omitted intentionally.
— end note]
constexpr explicit iterator(W value);
Effects: Initializes value_ with value.
constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
Effects: Equivalent to: return value_;
[Note 2: 
The noexcept clause is needed by the default iter_move implementation.
— end note]
constexpr iterator& operator++();
Effects: Equivalent to: ++value_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires incrementable<W>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires decrementable<W>;
Effects: Equivalent to: --value_; return *this;
constexpr iterator operator--(int) requires decrementable<W>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type n) requires advanceable<W>;
Effects: Equivalent to: if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) { if (n >= difference_type(0)) value_ += static_cast<W>(n); else value_ -= static_cast<W>(-n); } else { value_ += n; } return *this;
constexpr iterator& operator-=(difference_type n) requires advanceable<W>;
Effects: Equivalent to: if constexpr (is-integer-like<W> && !is-signed-integer-like<W>) { if (n >= difference_type(0)) value_ -= static_cast<W>(n); else value_ += static_cast<W>(-n); } else { value_ -= n; } return *this;
constexpr W operator[](difference_type n) const requires advanceable<W>;
Effects: Equivalent to: return W(value_ + n);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<W>;
Effects: Equivalent to: return x.value_ == y.value_;
friend constexpr bool operator<(const iterator& x, const iterator& y) requires totally_ordered<W>;
Effects: Equivalent to: return x.value_ < y.value_;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires totally_ordered<W>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires totally_ordered<W>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires totally_ordered<W>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires totally_ordered<W> && three_way_comparable<W>;
Effects: Equivalent to: return x.value_ <=> y.value_;
friend constexpr iterator operator+(iterator i, difference_type n) requires advanceable<W>;
Effects: Equivalent to: i += n; return i;
friend constexpr iterator operator+(difference_type n, iterator i) requires advanceable<W>;
Effects: Equivalent to: return i + n;
friend constexpr iterator operator-(iterator i, difference_type n) requires advanceable<W>;
Effects: Equivalent to: i -= n; return i;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires advanceable<W>;
Effects: Equivalent to: using D = difference_type; if constexpr (is-integer-like<W>) { if constexpr (is-signed-integer-like<W>) return D(D(x.value_) - D(y.value_)); else return (y.value_ > x.value_) ? D(-D(y.value_ - x.value_)) : D(x.value_ - y.value_); } else { return x.value_ - y.value_; }

25.6.4.4 Class iota_view​::​sentinel [range.iota.sentinel]

namespace std::ranges { template<weakly_incrementable W, semiregular Bound> requires weakly-equality-comparable-with<W, Bound> && copyable<W> struct iota_view<W, Bound>::sentinel { private: Bound bound_ = Bound(); // exposition only public: sentinel() = default; constexpr explicit sentinel(Bound bound); friend constexpr bool operator==(const iterator& x, const sentinel& y); friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y) requires sized_sentinel_for<Bound, W>; friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y) requires sized_sentinel_for<Bound, W>; }; }
constexpr explicit sentinel(Bound bound);
Effects: Initializes bound_ with bound.
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.value_ == y.bound_;
friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y) requires sized_sentinel_for<Bound, W>;
Effects: Equivalent to: return x.value_ - y.bound_;
friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y) requires sized_sentinel_for<Bound, W>;
Effects: Equivalent to: return -(y - x);

25.6.5 Repeat view [range.repeat]

25.6.5.1 Overview [range.repeat.overview]

repeat_view generates a sequence of elements by repeatedly producing the same value.
The name views​::​repeat denotes a customization point object ([customization.point.object]).
Given subexpressions E and F, the expressions views​::​repeat(E) and views​::​repeat(E, F) are expression-equivalent to repeat_view<decay_t<decltype((E))>>(E) and repeat_view(E, F), respectively.
[Example 1: for (int i : views::repeat(17, 4)) cout << i << ' '; // prints 17 17 17 17 — end example]

25.6.5.2 Class template repeat_view [range.repeat.view]

namespace std::ranges { template<class T> concept integer-like-with-usable-difference-type = // exposition only is-signed-integer-like<T> || (is-integer-like<T> && weakly_incrementable<T>); template<move_constructible T, semiregular Bound = unreachable_sentinel_t> requires (is_object_v<T> && same_as<T, remove_cv_t<T>> && (integer-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>)) class repeat_view : public view_interface<repeat_view<T, Bound>> { private: // [range.repeat.iterator], class repeat_view​::​iterator struct iterator; // exposition only movable-box<T> value_; // exposition only, see [range.move.wrap] Bound bound_ = Bound(); // exposition only public: repeat_view() requires default_initializable<T> = default; constexpr explicit repeat_view(const T& value, Bound bound = Bound()) requires copy_constructible<T>; constexpr explicit repeat_view(T&& value, Bound bound = Bound()); template<class... TArgs, class... BoundArgs> requires constructible_from<T, TArgs...> && constructible_from<Bound, BoundArgs...> constexpr explicit repeat_view(piecewise_construct_t, tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{}); constexpr iterator begin() const; constexpr iterator end() const requires (!same_as<Bound, unreachable_sentinel_t>); constexpr unreachable_sentinel_t end() const noexcept; constexpr auto size() const requires (!same_as<Bound, unreachable_sentinel_t>); }; template<class T, class Bound = unreachable_sentinel_t> repeat_view(T, Bound = Bound()) -> repeat_view<T, Bound>; }
constexpr explicit repeat_view(const T& value, Bound bound = Bound()) requires copy_constructible<T>;
Preconditions: If Bound is not unreachable_sentinel_t, bound  ≥ 0.
Effects: Initializes value_ with value and bound_ with bound.
constexpr explicit repeat_view(T&& value, Bound bound = Bound());
Preconditions: If Bound is not unreachable_sentinel_t, bound  ≥ 0.
Effects: Initializes value_ with std​::​move(value) and bound_ with bound.
template<class... TArgs, class... BoundArgs> requires constructible_from<T, TArgs...> && constructible_from<Bound, BoundArgs...> constexpr explicit repeat_view(piecewise_construct_t, tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{});
Effects: Initializes value_ with make_from_tuple<T>(std​::​move(value_args)) and initializes bound_ with make_from_tuple<Bound>(std​::​move(bound_args)).
The behavior is undefined if Bound is not unreachable_sentinel_t and bound_ is negative.
constexpr iterator begin() const;
Effects: Equivalent to: return iterator(addressof(*value_));
constexpr iterator end() const requires (!same_as<Bound, unreachable_sentinel_t>);
Effects: Equivalent to: return iterator(addressof(*value_), bound_);
constexpr unreachable_sentinel_t end() const noexcept;
Effects: Equivalent to: return unreachable_sentinel;
constexpr auto size() const requires (!same_as<Bound, unreachable_sentinel_t>);
Effects: Equivalent to: return to-unsigned-like(bound_);

25.6.5.3 Class repeat_view​::​iterator [range.repeat.iterator]

namespace std::ranges { template<move_constructible T, semiregular Bound> requires (is_object_v<T> && same_as<T, remove_cv_t<T>> && (integer-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>)) class repeat_view<T, Bound>::iterator { private: using index-type = // exposition only conditional_t<same_as<Bound, unreachable_sentinel_t>, ptrdiff_t, Bound>; const T* value_ = nullptr; // exposition only index-type current_ = index-type(); // exposition only constexpr explicit iterator(const T* value, index-type b = index-type()); // exposition only public: using iterator_concept = random_access_iterator_tag; using iterator_category = random_access_iterator_tag; using value_type = T; using difference_type = see below; iterator() = default; constexpr const T& operator*() const noexcept; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--(); constexpr iterator operator--(int); constexpr iterator& operator+=(difference_type n); constexpr iterator& operator-=(difference_type n); constexpr const T& operator[](difference_type n) const noexcept; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr auto operator<=>(const iterator& x, const iterator& y); friend constexpr iterator operator+(iterator i, difference_type n); friend constexpr iterator operator+(difference_type n, iterator i); friend constexpr iterator operator-(iterator i, difference_type n); friend constexpr difference_type operator-(const iterator& x, const iterator& y); }; }
If is-signed-integer-like<index-type> is true, the member typedef-name difference_type denotes index-type.
Otherwise, it denotes IOTA-DIFF-T(index-type) ([range.iota.view]).
constexpr explicit iterator(const T* value, index-type b = index-type());
Preconditions: If Bound is not unreachable_sentinel_t, b  ≥ 0.
Effects: Initializes value_ with value and current_ with b.
constexpr const T& operator*() const noexcept;
Effects: Equivalent to: return *value_;
constexpr iterator& operator++();
Effects: Equivalent to: ++current_; return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--();
Preconditions: If Bound is not unreachable_sentinel_t, .
Effects: Equivalent to: --current_; return *this;
constexpr iterator operator--(int);
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type n);
Preconditions: If Bound is not unreachable_sentinel_t, .
Effects: Equivalent to: current_ += n; return *this;
constexpr iterator& operator-=(difference_type n);
Preconditions: If Bound is not unreachable_sentinel_t, .
Effects: Equivalent to: current_ -= n; return *this;
constexpr const T& operator[](difference_type n) const noexcept;
Effects: Equivalent to: return *(*this + n);
friend constexpr bool operator==(const iterator& x, const iterator& y);
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr auto operator<=>(const iterator& x, const iterator& y);
Effects: Equivalent to: return x.current_ <=> y.current_;
friend constexpr iterator operator+(iterator i, difference_type n); friend constexpr iterator operator+(difference_type n, iterator i);
Effects: Equivalent to: i += n; return i;
friend constexpr iterator operator-(iterator i, difference_type n);
Effects: Equivalent to: i -= n; return i;
friend constexpr difference_type operator-(const iterator& x, const iterator& y);
Effects: Equivalent to: return static_cast<difference_type>(x.current_) - static_cast<difference_type>(y.current_);

25.6.6 Istream view [range.istream]

25.6.6.1 Overview [range.istream.overview]

basic_istream_view models input_range and reads (using operator>>) successive elements from its corresponding input stream.
The name views​::​istream<T> denotes a customization point object ([customization.point.object]).
Given a type T and a subexpression E of type U, if U models derived_from<basic_istream<typename U​::​char_type, typename U​::​traits_type>>, then the expression views​::​istream<T>(E) is expression-equivalent to basic_istream_view<T, typename U​::​char_type, typename U​::​traits_type>(E); otherwise, views​::​istream<T>(E) is ill-formed.
[Example 1: auto ints = istringstream{"0 1 2 3 4"}; ranges::copy(views::istream<int>(ints), ostream_iterator<int>{cout, "-"}); // prints 0-1-2-3-4- — end example]

25.6.6.2 Class template basic_istream_view [range.istream.view]

namespace std::ranges { template<class Val, class CharT, class Traits> concept stream-extractable = // exposition only requires(basic_istream<CharT, Traits>& is, Val& t) { is >> t; }; template<movable Val, class CharT, class Traits = char_traits<CharT>> requires default_initializable<Val> && stream-extractable<Val, CharT, Traits> class basic_istream_view : public view_interface<basic_istream_view<Val, CharT, Traits>> { public: constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream); constexpr auto begin() { *stream_ >> value_; return iterator{*this}; } constexpr default_sentinel_t end() const noexcept; private: // [range.istream.iterator], class basic_istream_view​::​iterator struct iterator; // exposition only basic_istream<CharT, Traits>* stream_; // exposition only Val value_ = Val(); // exposition only }; }
constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
Effects: Initializes stream_ with addressof(stream).
constexpr default_sentinel_t end() const noexcept;
Effects: Equivalent to: return default_sentinel;

25.6.6.3 Class basic_istream_view​::​iterator [range.istream.iterator]

namespace std::ranges { template<movable Val, class CharT, class Traits> requires default_initializable<Val> && stream-extractable<Val, CharT, Traits> class basic_istream_view<Val, CharT, Traits>::iterator { public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; using value_type = Val; constexpr explicit iterator(basic_istream_view& parent) noexcept; iterator(const iterator&) = delete; iterator(iterator&&) = default; iterator& operator=(const iterator&) = delete; iterator& operator=(iterator&&) = default; iterator& operator++(); void operator++(int); Val& operator*() const; friend bool operator==(const iterator& x, default_sentinel_t); private: basic_istream_view* parent_; // exposition only }; }
constexpr explicit iterator(basic_istream_view& parent) noexcept;
Effects: Initializes parent_ with addressof(parent).
iterator& operator++();
Effects: Equivalent to: *parent_->stream_ >> parent_->value_; return *this;
void operator++(int);
Effects: Equivalent to ++*this.
Val& operator*() const;
Effects: Equivalent to: return parent_->value_;
friend bool operator==(const iterator& x, default_sentinel_t);
Effects: Equivalent to: return !*x.parent_->stream_;

25.7 Range adaptors [range.adaptors]

25.7.1 General [range.adaptors.general]

Subclause [range.adaptors] defines range adaptors, which are utilities that transform a range into a view with custom behaviors.
These adaptors can be chained to create pipelines of range transformations that evaluate lazily as the resulting view is iterated.
Range adaptors are declared in namespace std​::​ranges​::​views.
The bitwise or operator is overloaded for the purpose of creating adaptor chain pipelines.
The adaptors also support function call syntax with equivalent semantics.
[Example 1: vector<int> ints{0,1,2,3,4,5}; auto even = [](int i) { return 0 == i % 2; }; auto square = [](int i) { return i * i; }; for (int i : ints | views::filter(even) | views::transform(square)) { cout << i << ' '; // prints 0 4 16 } assert(ranges::equal(ints | views::filter(even), views::filter(ints, even))); — end example]

25.7.2 Range adaptor objects [range.adaptor.object]

A range adaptor closure object is a unary function object that accepts a range argument.
For a range adaptor closure object C and an expression R such that decltype((R)) models range, the following expressions are equivalent: C(R) R | C
Given an additional range adaptor closure object D, the expression C | D produces another range adaptor closure object E.
E is a perfect forwarding call wrapper ([func.require]) with the following properties:
  • Its target object is an object d of type decay_t<decltype((D))> direct-non-list-initialized with D.
  • It has one bound argument entity, an object c of type decay_t<decltype((C))> direct-non-list-initialized with C.
  • Its call pattern is d(c(arg)), where arg is the argument used in a function call expression of E.
The expression C | D is well-formed if and only if the initializations of the state entities of E are all well-formed.
Given an object t of type T, where
  • t is a unary function object that accepts a range argument,
  • T models derived_from<range_adaptor_closure<T>>,
  • T has no other base classes of type range_adaptor_closure<U> for any other type U, and
  • T does not model range
then the implementation ensures that t is a range adaptor closure object.
The template parameter D for range_adaptor_closure may be an incomplete type.
If an expression of type cv D is used as an operand to the | operator, D shall be complete and model derived_from<range_adaptor_closure<D>>.
The behavior of an expression involving an object of type cv D as an operand to the | operator is undefined if overload resolution selects a program-defined operator| function.
If an expression of type cv U is used as an operand to the | operator, where U has a base class of type range_adaptor_closure<T> for some type T other than U, the behavior is undefined.
The behavior of a program that adds a specialization for range_adaptor_closure is undefined.
A range adaptor object is a customization point object ([customization.point.object]) that accepts a viewable_range as its first argument and returns a view.
If a range adaptor object accepts only one argument, then it is a range adaptor closure object.
If a range adaptor object adaptor accepts more than one argument, then let range be an expression such that decltype((range)) models viewable_range, let args... be arguments such that adaptor(range, args...) is a well-formed expression as specified in the rest of subclause [range.adaptors], and let BoundArgs be a pack that denotes decay_t<decltype((args))>....
The expression adaptor(args...) produces a range adaptor closure object f that is a perfect forwarding call wrapper ([func.require]) with the following properties:
  • Its target object is a copy of adaptor.
  • Its bound argument entities bound_args consist of objects of types BoundArgs... direct-non-list-initialized with std​::​forward<decltype((args))>(args)..., respectively.
  • Its call pattern is adaptor(r, bound_args...), where r is the argument used in a function call expression of f.
The expression adaptor(args...) is well-formed if and only if the initialization of the bound argument entities of the result, as specified above, are all well-formed.

25.7.3 Movable wrapper [range.move.wrap]

Many types in this subclause are specified in terms of an exposition-only class template movable-box.
movable-box<T> behaves exactly like optional<T> with the following differences:
  • movable-box<T> constrains its type parameter T with move_constructible<T> && is_object_v<T>.
  • The default constructor of movable-box<T> is equivalent to: constexpr movable-box() noexcept(is_nothrow_default_constructible_v<T>) requires default_initializable<T> : movable-box{in_place} {}
  • If copyable<T> is not modeled, the copy assignment operator is equivalent to: constexpr movable-box& operator=(const movable-box& that) noexcept(is_nothrow_copy_constructible_v<T>) requires copy_constructible<T> { if (this != addressof(that)) { if (that) emplace(*that); else reset(); } return *this; }
  • If movable<T> is not modeled, the move assignment operator is equivalent to: constexpr movable-box& operator=(movable-box&& that) noexcept(is_nothrow_move_constructible_v<T>) { if (this != addressof(that)) { if (that) emplace(std::move(*that)); else reset(); } return *this; }
Recommended practice:
  • If copy_constructible<T> is true, movable-box<T> should store only a T if either T models copyable, or is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T> is true.
  • Otherwise, movable-box<T> should store only a T if either T models movable or is_nothrow_move_constructible_v<T> is true.

25.7.4 Non-propagating cache [range.nonprop.cache]

Some types in [range.adaptors] are specified in terms of an exposition-only class template non-propagating-​cache.
non-propagating-cache<T> behaves exactly like optional<T> with the following differences:
  • non-propagating-cache<T> constrains its type parameter T with is_object_v<T>.
  • The copy constructor is equivalent to: constexpr non-propagating-cache(const non-propagating-cache&) noexcept {}
  • The move constructor is equivalent to: constexpr non-propagating-cache(non-propagating-cache&& other) noexcept { other.reset(); }
  • The copy assignment operator is equivalent to: constexpr non-propagating-cache& operator=(const non-propagating-cache& other) noexcept { if (addressof(other) != this) reset(); return *this; }
  • The move assignment operator is equivalent to: constexpr non-propagating-cache& operator=(non-propagating-cache&& other) noexcept { reset(); other.reset(); return *this; }
  • non-propagating-cache<T> has an additional member function template specified as follows:
    template<class I> constexpr T& emplace-deref(const I& i); // exposition only
    Mandates: The declaration T t(*i); is well-formed for some invented variable t.
    [Note 1: 
    If *i is a prvalue of type cv T, there is no requirement that it is movable ([dcl.init.general]).
    — end note]
    Effects: Calls reset().
    Then direct-non-list-initializes the contained value with *i.
    Postconditions: *this contains a value.
    Returns: A reference to the new contained value.
    Throws: Any exception thrown by the initialization of the contained value.
    Remarks: If an exception is thrown during the initialization of T, *this does not contain a value, and the previous value (if any) has been destroyed.
[Note 2: 
non-propagating-cache enables an input view to temporarily cache values as it is iterated over.
— end note]

25.7.5 Range adaptor helpers [range.adaptor.helpers]

namespace std::ranges { template<class F, class Tuple> constexpr auto tuple-transform(F&& f, Tuple&& t) { // exposition only return apply([&]<class... Ts>(Ts&&... elements) { return tuple<invoke_result_t<F&, Ts>...>(invoke(f, std::forward<Ts>(elements))...); }, std::forward<Tuple>(t)); } template<class F, class Tuple> constexpr void tuple-for-each(F&& f, Tuple&& t) { // exposition only apply([&]<class... Ts>(Ts&&... elements) { (static_cast<void>(invoke(f, std::forward<Ts>(elements))), ...); }, std::forward<Tuple>(t)); } template<class T> constexpr T& as-lvalue(T&& t) { // exposition only return static_cast<T&>(t); } template<bool Const, class... Views> concept all-random-access = // exposition only (random_access_range<maybe-const<Const, Views>> && ...); template<bool Const, class... Views> concept all-bidirectional = // exposition only (bidirectional_range<maybe-const<Const, Views>> && ...); template<bool Const, class... Views> concept all-forward = // exposition only (forward_range<maybe-const<Const, Views>> && ...); }

25.7.6 All view [range.all]

25.7.6.1 General [range.all.general]

views​::​all returns a view that includes all elements of its range argument.
The name views​::​all denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​all(E) is expression-equivalent to:
  • decay-copy(E) if the decayed type of E models view.
  • Otherwise, ref_view{E} if that expression is well-formed.
  • Otherwise, owning_view{E}.

25.7.6.2 Class template ref_view [range.ref.view]

ref_view is a view of the elements of some other range.
namespace std::ranges { template<range R> requires is_object_v<R> class ref_view : public view_interface<ref_view<R>> { private: R* r_; // exposition only public: template<different-from<ref_view> T> requires see below constexpr ref_view(T&& t); constexpr R& base() const { return *r_; } constexpr iterator_t<R> begin() const { return ranges::begin(*r_); } constexpr sentinel_t<R> end() const { return ranges::end(*r_); } constexpr bool empty() const requires requires { ranges::empty(*r_); } { return ranges::empty(*r_); } constexpr auto size() const requires sized_range<R> { return ranges::size(*r_); } constexpr auto data() const requires contiguous_range<R> { return ranges::data(*r_); } }; template<class R> ref_view(R&) -> ref_view<R>; }
template<different-from<ref_view> T> requires see below constexpr ref_view(T&& t);
Effects: Initializes r_ with addressof(static_cast<R&>(std​::​forward<T>(t))).
Remarks: Let FUN denote the exposition-only functions void FUN(R&); void FUN(R&&) = delete;
The expression in the requires-clause is equivalent to: convertible_to<T, R&> && requires { FUN(declval<T>()); }

25.7.6.3 Class template owning_view [range.owning.view]

owning_view is a move-only view of the elements of some other range.
namespace std::ranges { template<range R> requires movable<R> && (!is-initializer-list<R>) // see [range.refinements] class owning_view : public view_interface<owning_view<R>> { private: R r_ = R(); // exposition only public: owning_view() requires default_initializable<R> = default; constexpr owning_view(R&& t); owning_view(owning_view&&) = default; owning_view& operator=(owning_view&&) = default; constexpr R& base() & noexcept { return r_; } constexpr const R& base() const & noexcept { return r_; } constexpr R&& base() && noexcept { return std::move(r_); } constexpr const R&& base() const && noexcept { return std::move(r_); } constexpr iterator_t<R> begin() { return ranges::begin(r_); } constexpr sentinel_t<R> end() { return ranges::end(r_); } constexpr auto begin() const requires range<const R> { return ranges::begin(r_); } constexpr auto end() const requires range<const R> { return ranges::end(r_); } constexpr bool empty() requires requires { ranges::empty(r_); } { return ranges::empty(r_); } constexpr bool empty() const requires requires { ranges::empty(r_); } { return ranges::empty(r_); } constexpr auto size() requires sized_range<R> { return ranges::size(r_); } constexpr auto size() const requires sized_range<const R> { return ranges::size(r_); } constexpr auto data() requires contiguous_range<R> { return ranges::data(r_); } constexpr auto data() const requires contiguous_range<const R> { return ranges::data(r_); } }; }
constexpr owning_view(R&& t);
Effects: Initializes r_ with std​::​move(t).

25.7.7 As rvalue view [range.as.rvalue]

25.7.7.1 Overview [range.as.rvalue.overview]

as_rvalue_view presents a view of an underlying sequence with the same behavior as the underlying sequence except that its elements are rvalues.
Some generic algorithms can be called with an as_rvalue_view to replace copying with moving.
The name views​::​as_rvalue denotes a range adaptor object ([range.adaptor.object]).
Let E be an expression and let T be decltype((E)).
The expression views​::​as_rvalue(E) is expression-equivalent to:
  • views​::​all(E) if T models input_range and same_as<range_rvalue_reference_t<T>, range_reference_t<T>> is true.
  • Otherwise, as_rvalue_view(E).
[Example 1: vector<string> words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"}; vector<string> new_words; ranges::copy(words | views::as_rvalue, back_inserter(new_words)); // moves each string from words into new_words — end example]

25.7.7.2 Class template as_rvalue_view [range.as.rvalue.view]

namespace std::ranges { template<view V> requires input_range<V> class as_rvalue_view : public view_interface<as_rvalue_view<V>> { V base_ = V(); // exposition only public: as_rvalue_view() requires default_initializable<V> = default; constexpr explicit as_rvalue_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { return move_iterator(ranges::begin(base_)); } constexpr auto begin() const requires range<const V> { return move_iterator(ranges::begin(base_)); } constexpr auto end() requires (!simple-view<V>) { if constexpr (common_range<V>) { return move_iterator(ranges::end(base_)); } else { return move_sentinel(ranges::end(base_)); } } constexpr auto end() const requires range<const V> { if constexpr (common_range<const V>) { return move_iterator(ranges::end(base_)); } else { return move_sentinel(ranges::end(base_)); } } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } }; template<class R> as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>; }
constexpr explicit as_rvalue_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.8 Filter view [range.filter]

25.7.8.1 Overview [range.filter.overview]

filter_view presents a view of the elements of an underlying sequence that satisfy a predicate.
The name views​::​filter denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and P, the expression views​::​filter(E, P) is expression-equivalent to filter_view(E, P).
[Example 1: vector<int> is{ 0, 1, 2, 3, 4, 5, 6 }; auto evens = views::filter(is, [](int i) { return 0 == i % 2; }); for (int i : evens) cout << i << ' '; // prints 0 2 4 6 — end example]

25.7.8.2 Class template filter_view [range.filter.view]

namespace std::ranges { template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view : public view_interface<filter_view<V, Pred>> { private: V base_ = V(); // exposition only movable-box<Pred> pred_; // exposition only // [range.filter.iterator], class filter_view​::​iterator class iterator; // exposition only // [range.filter.sentinel], class filter_view​::​sentinel class sentinel; // exposition only public: filter_view() requires default_initializable<V> && default_initializable<Pred> = default; constexpr explicit filter_view(V base, Pred pred); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const; constexpr iterator begin(); constexpr auto end() { if constexpr (common_range<V>) return iterator{*this, ranges::end(base_)}; else return sentinel{*this}; } }; template<class R, class Pred> filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>; }
constexpr explicit filter_view(V base, Pred pred);
Effects: Initializes base_ with std​::​move(base) and initializes pred_ with std​::​move(pred).
constexpr const Pred& pred() const;
Effects: Equivalent to: return *pred_;
constexpr iterator begin();
Preconditions: pred_.has_value() is true.
Returns: {*this, ranges​::​find_if(base_, ref(*pred_))}.
Remarks: In order to provide the amortized constant time complexity required by the range concept when filter_view models forward_range, this function caches the result within the filter_view for use on subsequent calls.

25.7.8.3 Class filter_view​::​iterator [range.filter.iterator]

namespace std::ranges { template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view<V, Pred>::iterator { private: iterator_t<V> current_ = iterator_t<V>(); // exposition only filter_view* parent_ = nullptr; // exposition only public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = range_value_t<V>; using difference_type = range_difference_t<V>; iterator() requires default_initializable<iterator_t<V>> = default; constexpr iterator(filter_view& parent, iterator_t<V> current); constexpr const iterator_t<V>& base() const & noexcept; constexpr iterator_t<V> base() &&; constexpr range_reference_t<V> operator*() const; constexpr iterator_t<V> operator->() const requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<V>; constexpr iterator& operator--() requires bidirectional_range<V>; constexpr iterator operator--(int) requires bidirectional_range<V>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<V>>; friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<V>>; }; }
Modification of the element a filter_view​::​iterator denotes is permitted, but results in undefined behavior if the resulting value does not satisfy the filter predicate.
iterator​::​iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if V models forward_range.
In that case, iterator​::​iterator_category is defined as follows:
  • Let C denote the type iterator_traits<iterator_t<V>>​::​iterator_category.
  • If C models derived_from<bidirectional_iterator_tag>, then iterator_category denotes bidirectional_iterator_tag.
  • Otherwise, if C models derived_from<forward_iterator_tag>, then iterator_category denotes forward_iterator_tag.
  • Otherwise, iterator_category denotes C.
constexpr iterator(filter_view& parent, iterator_t<V> current);
Effects: Initializes current_ with std​::​move(current) and parent_ with addressof(parent).
constexpr const iterator_t<V>& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr iterator_t<V> base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr range_reference_t<V> operator*() const;
Effects: Equivalent to: return *current_;
constexpr iterator_t<V> operator->() const requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
Effects: Equivalent to: return current_;
constexpr iterator& operator++();
Effects: Equivalent to: current_ = ranges::find_if(std::move(++current_), ranges::end(parent_->base_), ref(*parent_->pred_)); return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires forward_range<V>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<V>;
Effects: Equivalent to: do --current_; while (!invoke(*parent_->pred_, *current_)); return *this;
constexpr iterator operator--(int) requires bidirectional_range<V>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<V>>;
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)));
Effects: Equivalent to: return ranges​::​iter_move(i.current_);
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<V>>;
Effects: Equivalent to ranges​::​iter_swap(x.current_, y.current_).

25.7.8.4 Class filter_view​::​sentinel [range.filter.sentinel]

namespace std::ranges { template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view<V, Pred>::sentinel { private: sentinel_t<V> end_ = sentinel_t<V>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(filter_view& parent); constexpr sentinel_t<V> base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); }; }
constexpr explicit sentinel(filter_view& parent);
Effects: Initializes end_ with ranges​::​end(parent.base_).
constexpr sentinel_t<V> base() const;
Effects: Equivalent to: return end_;
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.current_ == y.end_;

25.7.9 Transform view [range.transform]

25.7.9.1 Overview [range.transform.overview]

transform_view presents a view of an underlying sequence after applying a transformation function to each element.
The name views​::​transform denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​transform(E, F) is expression-equivalent to transform_view(E, F).
[Example 1: vector<int> is{ 0, 1, 2, 3, 4 }; auto squares = views::transform(is, [](int i) { return i * i; }); for (int i : squares) cout << i << ' '; // prints 0 1 4 9 16 — end example]

25.7.9.2 Class template transform_view [range.transform.view]

namespace std::ranges { template<input_range V, move_constructible F> requires view<V> && is_object_v<F> && regular_invocable<F&, range_reference_t<V>> && can-reference<invoke_result_t<F&, range_reference_t<V>>> class transform_view : public view_interface<transform_view<V, F>> { private: // [range.transform.iterator], class template transform_view​::​iterator template<bool> struct iterator; // exposition only // [range.transform.sentinel], class template transform_view​::​sentinel template<bool> struct sentinel; // exposition only V base_ = V(); // exposition only movable-box<F> fun_; // exposition only public: transform_view() requires default_initializable<V> && default_initializable<F> = default; constexpr explicit transform_view(V base, F fun); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr iterator<false> begin(); constexpr iterator<true> begin() const requires range<const V> && regular_invocable<const F&, range_reference_t<const V>>; constexpr sentinel<false> end(); constexpr iterator<false> end() requires common_range<V>; constexpr sentinel<true> end() const requires range<const V> && regular_invocable<const F&, range_reference_t<const V>>; constexpr iterator<true> end() const requires common_range<const V> && regular_invocable<const F&, range_reference_t<const V>>; constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } }; template<class R, class F> transform_view(R&&, F) -> transform_view<views::all_t<R>, F>; }
constexpr explicit transform_view(V base, F fun);
Effects: Initializes base_ with std​::​move(base) and fun_ with std​::​move(fun).
constexpr iterator<false> begin();
Effects: Equivalent to: return iterator<false>{*this, ranges::begin(base_)};
constexpr iterator<true> begin() const requires range<const V> && regular_invocable<const F&, range_reference_t<const V>>;
Effects: Equivalent to: return iterator<true>{*this, ranges::begin(base_)};
constexpr sentinel<false> end();
Effects: Equivalent to: return sentinel<false>{ranges::end(base_)};
constexpr iterator<false> end() requires common_range<V>;
Effects: Equivalent to: return iterator<false>{*this, ranges::end(base_)};
constexpr sentinel<true> end() const requires range<const V> && regular_invocable<const F&, range_reference_t<const V>>;
Effects: Equivalent to: return sentinel<true>{ranges::end(base_)};
constexpr iterator<true> end() const requires common_range<const V> && regular_invocable<const F&, range_reference_t<const V>>;
Effects: Equivalent to: return iterator<true>{*this, ranges::end(base_)};

25.7.9.3 Class template transform_view​::​iterator [range.transform.iterator]

namespace std::ranges { template<input_range V, move_constructible F> requires view<V> && is_object_v<F> && regular_invocable<F&, range_reference_t<V>> && can-reference<invoke_result_t<F&, range_reference_t<V>>> template<bool Const> class transform_view<V, F>::iterator { private: using Parent = maybe-const<Const, transform_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only Parent* parent_ = nullptr; // exposition only public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = remove_cvref_t<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>; using difference_type = range_difference_t<Base>; iterator() requires default_initializable<iterator_t<Base>> = default; constexpr iterator(Parent& parent, iterator_t<Base> current); constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr const iterator_t<Base>& base() const & noexcept; constexpr iterator_t<Base> base() &&; constexpr decltype(auto) operator*() const noexcept(noexcept(invoke(*parent_->fun_, *current_))) { return invoke(*parent_->fun_, *current_); } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>; constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base> { return invoke(*parent_->fun_, current_[n]); } friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<Base>>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(iterator i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, iterator i) requires random_access_range<Base>; friend constexpr iterator operator-(iterator i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; }; }
iterator​::​iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if Base models forward_range.
In that case, iterator​::​iterator_category is defined as follows: Let C denote the type iterator_traits<iterator_t<Base>>​::​iterator_category.
  • If is_reference_v<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>> is true, then
    • if C models derived_from<contiguous_iterator_tag>, iterator_category denotes random_access_iterator_tag;
    • otherwise, iterator_category denotes C.
  • Otherwise, iterator_category denotes input_iterator_tag.
constexpr iterator(Parent& parent, iterator_t<Base> current);
Effects: Initializes current_ with std​::​move(current) and parent_ with addressof(parent).
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_) and parent_ with i.parent_.
constexpr const iterator_t<Base>& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr iterator_t<Base> base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr iterator& operator++();
Effects: Equivalent to: ++current_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++current_.
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --current_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ += n; return *this;
constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ -= n; return *this;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<Base>>;
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return x.current_ < y.current_;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Effects: Equivalent to: return x.current_ <=> y.current_;
friend constexpr iterator operator+(iterator i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, iterator i) requires random_access_range<Base>;
Effects: Equivalent to: return iterator{*i.parent_, i.current_ + n};
friend constexpr iterator operator-(iterator i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: return iterator{*i.parent_, i.current_ - n};
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return x.current_ - y.current_;

25.7.9.4 Class template transform_view​::​sentinel [range.transform.sentinel]

namespace std::ranges { template<input_range V, move_constructible F> requires view<V> && is_object_v<F> && regular_invocable<F&, range_reference_t<V>> && can-reference<invoke_result_t<F&, range_reference_t<V>>> template<bool Const> class transform_view<V, F>::sentinel { private: using Parent = maybe-const<Const, transform_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& y, const iterator<OtherConst>& x); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(i.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ == y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ - y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& y, const iterator<OtherConst>& x);
Effects: Equivalent to: return y.end_ - x.current_;

25.7.10 Take view [range.take]

25.7.10.1 Overview [range.take.overview]

take_view produces a view of the first N elements from another view, or all the elements if the adapted view contains fewer than N.
The name views​::​take denotes a range adaptor object ([range.adaptor.object]).
Let E and F be expressions, let T be remove_cvref_t<decltype((E))>, and let D be range_difference_t<decltype((E))>.
If decltype((F)) does not model convertible_to<D>, views​::​take(E, F) is ill-formed.
Otherwise, the expression views​::​take(E, F) is expression-equivalent to:
  • If T is a specialization of empty_view ([range.empty.view]), then ((void)F, decay-copy(E)), except that the evaluations of E and F are indeterminately sequenced.
  • Otherwise, if T models random_access_range and sized_range and is a specialization of span ([views.span]), basic_string_view ([string.view]), or subrange ([range.subrange]), then U(ranges​::​begin(E), ranges​::​begin(E) + std​::​min<D>(ranges​::​distance(E), F)), except that E is evaluated only once, where U is a type determined as follows:
    • if T is a specialization of span, then U is span<typename T​::​element_type>;
    • otherwise, if T is a specialization of basic_string_view, then U is T;
    • otherwise, T is a specialization of subrange, and U is subrange<iterator_t<T>>;
  • otherwise, if T is a specialization of iota_view ([range.iota.view]) that models random_access_range and sized_range, then iota_view(*ranges​::​begin(E), *(ranges​::​begin(E) + std​::​min<D>(ranges​::​distance(E), F))), except that E is evaluated only once.
  • Otherwise, if T is a specialization of repeat_view ([range.repeat.view]):
    • if T models sized_range, then views::repeat(*E.value_, std::min<D>(ranges::distance(E), F)) except that E is evaluated only once;
    • otherwise, views​::​repeat(*E.value_, static_cast<D>(F)).
  • Otherwise, take_view(E, F).
[Example 1: vector<int> is{0,1,2,3,4,5,6,7,8,9}; for (int i : is | views::take(5)) cout << i << ' '; // prints 0 1 2 3 4 — end example]

25.7.10.2 Class template take_view [range.take.view]

namespace std::ranges { template<view V> class take_view : public view_interface<take_view<V>> { private: V base_ = V(); // exposition only range_difference_t<V> count_ = 0; // exposition only // [range.take.sentinel], class template take_view​::​sentinel template<bool> class sentinel; // exposition only public: take_view() requires default_initializable<V> = default; constexpr explicit take_view(V base, range_difference_t<V> count); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { if constexpr (sized_range<V>) { if constexpr (random_access_range<V>) { return ranges::begin(base_); } else { auto sz = range_difference_t<V>(size()); return counted_iterator(ranges::begin(base_), sz); } } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) { auto it = ranges::begin(base_); auto sz = std::min(count_, ranges::end(base_) - it); return counted_iterator(std::move(it), sz); } else { return counted_iterator(ranges::begin(base_), count_); } } constexpr auto begin() const requires range<const V> { if constexpr (sized_range<const V>) { if constexpr (random_access_range<const V>) { return ranges::begin(base_); } else { auto sz = range_difference_t<const V>(size()); return counted_iterator(ranges::begin(base_), sz); } } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) { auto it = ranges::begin(base_); auto sz = std::min(count_, ranges::end(base_) - it); return counted_iterator(std::move(it), sz); } else { return counted_iterator(ranges::begin(base_), count_); } } constexpr auto end() requires (!simple-view<V>) { if constexpr (sized_range<V>) { if constexpr (random_access_range<V>) return ranges::begin(base_) + range_difference_t<V>(size()); else return default_sentinel; } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) { return default_sentinel; } else { return sentinel<false>{ranges::end(base_)}; } } constexpr auto end() const requires range<const V> { if constexpr (sized_range<const V>) { if constexpr (random_access_range<const V>) return ranges::begin(base_) + range_difference_t<const V>(size()); else return default_sentinel; } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) { return default_sentinel; } else { return sentinel<true>{ranges::end(base_)}; } } constexpr auto size() requires sized_range<V> { auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); } constexpr auto size() const requires sized_range<const V> { auto n = ranges::size(base_); return ranges::min(n, static_cast<decltype(n)>(count_)); } }; template<class R> take_view(R&&, range_difference_t<R>) -> take_view<views::all_t<R>>; }
constexpr explicit take_view(V base, range_difference_t<V> count);
Preconditions: count >= 0 is true.
Effects: Initializes base_ with std​::​move(base) and count_ with count.

25.7.10.3 Class template take_view​::​sentinel [range.take.sentinel]

namespace std::ranges { template<view V> template<bool Const> class take_view<V>::sentinel { private: using Base = maybe-const<Const, V>; // exposition only template<bool OtherConst> using CI = counted_iterator<iterator_t<maybe-const<OtherConst, V>>>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; friend constexpr bool operator==(const CI<Const>& y, const sentinel& x); template<bool OtherConst = !Const> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(s.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
friend constexpr bool operator==(const CI<Const>& y, const sentinel& x); template<bool OtherConst = !Const> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
Effects: Equivalent to: return y.count() == 0 || y.base() == x.end_;

25.7.11 Take while view [range.take.while]

25.7.11.1 Overview [range.take.while.overview]

Given a unary predicate pred and a view r, take_while_view produces a view of the range [ranges​::​begin(r), ranges​::​find_if_not(r, pred)).
The name views​::​take_while denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​take_while(E, F) is expression-equivalent to take_while_view(E, F).
[Example 1: auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"}; auto small = [](const auto x) noexcept { return x < 5; }; auto small_ints = views::istream<int>(input) | views::take_while(small); for (const auto i : small_ints) { cout << i << ' '; // prints 0 1 2 3 4 } auto i = 0; input >> i; cout << i; // prints 6 — end example]

25.7.11.2 Class template take_while_view [range.take.while.view]

namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class take_while_view : public view_interface<take_while_view<V, Pred>> { // [range.take.while.sentinel], class template take_while_view​::​sentinel template<bool> class sentinel; // exposition only V base_ = V(); // exposition only movable-box<Pred> pred_; // exposition only public: take_while_view() requires default_initializable<V> && default_initializable<Pred> = default; constexpr explicit take_while_view(V base, Pred pred); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const; constexpr auto begin() requires (!simple-view<V>) { return ranges::begin(base_); } constexpr auto begin() const requires range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>> { return ranges::begin(base_); } constexpr auto end() requires (!simple-view<V>) { return sentinel<false>(ranges::end(base_), addressof(*pred_)); } constexpr auto end() const requires range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>> { return sentinel<true>(ranges::end(base_), addressof(*pred_)); } }; template<class R, class Pred> take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>; }
constexpr explicit take_while_view(V base, Pred pred);
Effects: Initializes base_ with std​::​move(base) and pred_ with std​::​move(pred).
constexpr const Pred& pred() const;
Effects: Equivalent to: return *pred_;

25.7.11.3 Class template take_while_view​::​sentinel [range.take.while.sentinel]

namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> template<bool Const> class take_while_view<V, Pred>::sentinel { using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only const Pred* pred_ = nullptr; // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred); constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const { return end_; } friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y); template<bool OtherConst = !Const> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x, const sentinel& y); }; }
constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
Effects: Initializes end_ with end and pred_ with pred.
constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(s.end_) and pred_ with s.pred_.
friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y); template<bool OtherConst = !Const> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x, const sentinel& y);
Effects: Equivalent to: return y.end_ == x || !invoke(*y.pred_, *x);

25.7.12 Drop view [range.drop]

25.7.12.1 Overview [range.drop.overview]

drop_view produces a view excluding the first N elements from another view, or an empty range if the adapted view contains fewer than N elements.
The name views​::​drop denotes a range adaptor object ([range.adaptor.object]).
Let E and F be expressions, let T be remove_cvref_t<decltype((E))>, and let D be range_difference_t<decltype((E))>.
If decltype((F)) does not model convertible_to<D>, views​::​drop(E, F) is ill-formed.
Otherwise, the expression views​::​drop(E, F) is expression-equivalent to:
  • If T is a specialization of empty_view ([range.empty.view]), then ((void)F, decay-copy(E)), except that the evaluations of E and F are indeterminately sequenced.
  • Otherwise, if T models random_access_range and sized_range and is then U(ranges​::​begin(E) + std​::​min<D>(ranges​::​distance(E), F), ranges​::​end(E)), except that E is evaluated only once, where U is span<typename T​::​element_type> if T is a specialization of span and T otherwise.
  • Otherwise, if T is a specialization of subrange that models random_access_range and sized_range, then T(ranges​::​begin(E) + std​::​min<D>(ranges​::​distance(E), F), ranges​::​end(E), to-unsigned-like(ranges​::​distance(E) - std​::​min<D>(ranges​::​distance(E), F))), except that E and F are each evaluated only once.
  • Otherwise, if T is a specialization of repeat_view ([range.repeat.view]):
    • if T models sized_range, then views::repeat(*E.value_, ranges::distance(E) - std::min<D>(ranges::distance(E), F)) except that E is evaluated only once;
    • otherwise, ((void)F, decay-copy(E)), except that the evaluations of E and F are indeterminately sequenced.
  • Otherwise, drop_view(E, F).
[Example 1: auto ints = views::iota(0) | views::take(10); for (auto i : ints | views::drop(5)) { cout << i << ' '; // prints 5 6 7 8 9 } — end example]

25.7.12.2 Class template drop_view [range.drop.view]

namespace std::ranges { template<view V> class drop_view : public view_interface<drop_view<V>> { public: drop_view() requires default_initializable<V> = default; constexpr explicit drop_view(V base, range_difference_t<V> count); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!(simple-view<V> && random_access_range<const V> && sized_range<const V>)); constexpr auto begin() const requires random_access_range<const V> && sized_range<const V>; constexpr auto end() requires (!simple-view<V>) { return ranges::end(base_); } constexpr auto end() const requires range<const V> { return ranges::end(base_); } constexpr auto size() requires sized_range<V> { const auto s = ranges::size(base_); const auto c = static_cast<decltype(s)>(count_); return s < c ? 0 : s - c; } constexpr auto size() const requires sized_range<const V> { const auto s = ranges::size(base_); const auto c = static_cast<decltype(s)>(count_); return s < c ? 0 : s - c; } private: V base_ = V(); // exposition only range_difference_t<V> count_ = 0; // exposition only }; template<class R> drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>; }
constexpr explicit drop_view(V base, range_difference_t<V> count);
Preconditions: count >= 0 is true.
Effects: Initializes base_ with std​::​move(base) and count_ with count.
constexpr auto begin() requires (!(simple-view<V> && random_access_range<const V> && sized_range<const V>)); constexpr auto begin() const requires random_access_range<const V> && sized_range<const V>;
Returns: ranges​::​next(ranges​::​begin(base_), count_, ranges​::​end(base_)).
Remarks: In order to provide the amortized constant-time complexity required by the range concept when drop_view models forward_range, the first overload caches the result within the drop_view for use on subsequent calls.
[Note 1: 
Without this, applying a reverse_view over a drop_view would have quadratic iteration complexity.
— end note]

25.7.13 Drop while view [range.drop.while]

25.7.13.1 Overview [range.drop.while.overview]

Given a unary predicate pred and a view r, drop_while_view produces a view of the range [ranges​::​find_if_not(r, pred), ranges​::​end(r)).
The name views​::​drop_while denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​drop_while(E, F) is expression-equivalent to drop_while_view(E, F).
[Example 1: constexpr auto source = " \t \t \t hello there"sv; auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; }; auto skip_ws = views::drop_while(source, is_invisible); for (auto c : skip_ws) { cout << c; // prints hello there with no leading space } — end example]

25.7.13.2 Class template drop_while_view [range.drop.while.view]

namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class drop_while_view : public view_interface<drop_while_view<V, Pred>> { public: drop_while_view() requires default_initializable<V> && default_initializable<Pred> = default; constexpr explicit drop_while_view(V base, Pred pred); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const; constexpr auto begin(); constexpr auto end() { return ranges::end(base_); } private: V base_ = V(); // exposition only movable-box<Pred> pred_; // exposition only }; template<class R, class Pred> drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>; }
constexpr explicit drop_while_view(V base, Pred pred);
Effects: Initializes base_ with std​::​move(base) and pred_ with std​::​move(pred).
constexpr const Pred& pred() const;
Effects: Equivalent to: return *pred_;
constexpr auto begin();
Preconditions: pred_.has_value() is true.
Returns: ranges​::​find_if_not(base_, cref(*pred_)).
Remarks: In order to provide the amortized constant-time complexity required by the range concept when drop_while_view models forward_range, the first call caches the result within the drop_while_view for use on subsequent calls.
[Note 1: 
Without this, applying a reverse_view over a drop_while_view would have quadratic iteration complexity.
— end note]

25.7.14 Join view [range.join]

25.7.14.1 Overview [range.join.overview]

join_view flattens a view of ranges into a view.
The name views​::​join denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​join(E) is expression-equivalent to join_view<views​::​all_t<decltype((E))>>{E}.
[Example 1: vector<string> ss{"hello", " ", "world", "!"}; for (char ch : ss | views::join) cout << ch; // prints hello world! — end example]

25.7.14.2 Class template join_view [range.join.view]

namespace std::ranges { template<input_range V> requires view<V> && input_range<range_reference_t<V>> class join_view : public view_interface<join_view<V>> { private: using InnerRng = range_reference_t<V>; // exposition only // [range.join.iterator], class template join_view​::​iterator template<bool Const> struct iterator; // exposition only // [range.join.sentinel], class template join_view​::​sentinel template<bool Const> struct sentinel; // exposition only V base_ = V(); // exposition only non-propagating-cache<iterator_t<V>> outer_; // exposition only, present only // when !forward_range<V> non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only // if is_reference_v<InnerRng> is false public: join_view() requires default_initializable<V> = default; constexpr explicit join_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() { if constexpr (forward_range<V>) { constexpr bool use_const = simple-view<V> && is_reference_v<InnerRng>; return iterator<use_const>{*this, ranges::begin(base_)}; } else { outer_ = ranges::begin(base_); return iterator<false>{*this}; } } constexpr auto begin() const requires forward_range<const V> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> { return iterator<true>{*this, ranges::begin(base_)}; } constexpr auto end() { if constexpr (forward_range<V> && is_reference_v<InnerRng> && forward_range<InnerRng> && common_range<V> && common_range<InnerRng>) return iterator<simple-view<V>>{*this, ranges::end(base_)}; else return sentinel<simple-view<V>>{*this}; } constexpr auto end() const requires forward_range<const V> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> { if constexpr (forward_range<range_reference_t<const V>> && common_range<const V> && common_range<range_reference_t<const V>>) return iterator<true>{*this, ranges::end(base_)}; else return sentinel<true>{*this}; } }; template<class R> explicit join_view(R&&) -> join_view<views::all_t<R>>; }
constexpr explicit join_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.14.3 Class template join_view​::​iterator [range.join.iterator]

namespace std::ranges { template<input_range V> requires view<V> && input_range<range_reference_t<V>> template<bool Const> struct join_view<V>::iterator { private: using Parent = maybe-const<Const, join_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only using OuterIter = iterator_t<Base>; // exposition only using InnerIter = iterator_t<range_reference_t<Base>>; // exposition only static constexpr bool ref-is-glvalue = // exposition only is_reference_v<range_reference_t<Base>>; OuterIter outer_ = OuterIter(); // exposition only, present only // if Base models forward_range optional<InnerIter> inner_; // exposition only Parent* parent_ = nullptr; // exposition only constexpr void satisfy(); // exposition only constexpr OuterIter& outer(); // exposition only constexpr const OuterIter& outer() const; // exposition only constexpr iterator(Parent& parent, OuterIter outer) requires forward_range<Base>; // exposition only constexpr explicit iterator(Parent& parent) requires (!forward_range<Base>); // exposition only public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = range_value_t<range_reference_t<Base>>; using difference_type = see below; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, OuterIter> && convertible_to<iterator_t<InnerRng>, InnerIter>; constexpr decltype(auto) operator*() const { return **inner_; } constexpr InnerIter operator->() const requires has-arrow<InnerIter> && copyable<InnerIter>; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ref-is-glvalue && forward_range<Base> && forward_range<range_reference_t<Base>>; constexpr iterator& operator--() requires ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>; constexpr iterator operator--(int) requires ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && forward_range<Base> && equality_comparable<iterator_t<range_reference_t<Base>>>; friend constexpr decltype(auto) iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(*i.inner_))) { return ranges::iter_move(*i.inner_); } friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_))) requires indirectly_swappable<InnerIter>; }; }
iterator​::​iterator_concept is defined as follows:
  • If ref-is-glvalue is true, Base models bidirectional_range, and range_reference_t<Base> models both bidirectional_range and common_range, then iterator_concept denotes bidirectional_iterator_tag.
  • Otherwise, if ref-is-glvalue is true and Base and range_reference_t<Base> each model forward_range, then iterator_concept denotes forward_iterator_tag.
  • Otherwise, iterator_concept denotes input_iterator_tag.
The member typedef-name iterator_category is defined if and only if ref-is-glvalue is true, Base models forward_range, and range_reference_t<Base> models forward_range.
In that case, iterator​::​iterator_category is defined as follows:
  • Let OUTERC denote iterator_traits<iterator_t<Base>>​::​iterator_category, and let INNERC denote iterator_traits<iterator_t<range_reference_t<Base>>>​::​iterator_category.
  • If OUTERC and INNERC each model derived_from<bidirectional_iterator_tag> and range_reference_t<Base> models common_range, iterator_category denotes bidirectional_iterator_tag.
  • Otherwise, if OUTERC and INNERC each model derived_from<forward_iterator_tag>, iterator_category denotes forward_iterator_tag.
  • Otherwise, iterator_category denotes input_iterator_tag.
iterator​::​difference_type denotes the type: common_type_t< range_difference_t<Base>, range_difference_t<range_reference_t<Base>>>
join_view iterators use the satisfy function to skip over empty inner ranges.
constexpr OuterIter& outer(); constexpr const OuterIter& outer() const;
Returns: outer_ if Base models forward_range; otherwise, *parent_->outer_.
constexpr void satisfy();
Effects: Equivalent to: auto update_inner = [this](const iterator_t<Base>& x) -> auto&& { if constexpr (ref-is-glvalue) // *x is a reference return *x; else return parent_->inner_.emplace-deref(x); }; for (; outer() != ranges::end(parent_->base_); ++outer()) { auto&& inner = update_inner(outer()); inner_ = ranges::begin(inner); if (*inner_ != ranges::end(inner)) return; } if constexpr (ref-is-glvalue) inner_.reset();
constexpr iterator(Parent& parent, OuterIter outer) requires forward_range<Base>;
Effects: Initializes outer_ with std​::​move(outer) and parent_ with addressof(parent); then calls satisfy().
constexpr explicit iterator(Parent& parent) requires (!forward_range<Base>);
Effects: Initializes parent_ with addressof(parent); then calls satisfy().
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, OuterIter> && convertible_to<iterator_t<InnerRng>, InnerIter>;
Effects: Initializes outer_ with std​::​move(i.outer_), inner_ with std​::​move(i.inner_), and parent_ with i.parent_.
[Note 1: 
Const can only be true when Base models forward_range.
— end note]
constexpr InnerIter operator->() const requires has-arrow<InnerIter> && copyable<InnerIter>;
Effects: Equivalent to: return *inner_;
constexpr iterator& operator++();
Let inner-range be:
  • If ref-is-glvalue is true, *outer().
  • Otherwise, *parent_->inner_.
Effects: Equivalent to: if (++*inner_ == ranges::end(as-lvalue(inner-range))) { ++outer(); satisfy(); } return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++*this.
constexpr iterator operator++(int) requires ref-is-glvalue && forward_range<Base> && forward_range<range_reference_t<Base>>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>;
Effects: Equivalent to: if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(as-lvalue(*--outer_)); while (*inner_ == ranges::begin(as-lvalue(*outer_))) *inner_ = ranges::end(as-lvalue(*--outer_)); --*inner_; return *this;
constexpr iterator operator--(int) requires ref-is-glvalue && bidirectional_range<Base> && bidirectional_range<range_reference_t<Base>> && common_range<range_reference_t<Base>>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && forward_range<Base> && equality_comparable<iterator_t<range_reference_t<Base>>>;
Effects: Equivalent to: return x.outer_ == y.outer_ && x.inner_ == y.inner_;
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_))) requires indirectly_swappable<InnerIter>;
Effects: Equivalent to: return ranges​::​iter_swap(*x.inner_, *y.inner_);

25.7.14.4 Class template join_view​::​sentinel [range.join.sentinel]

namespace std::ranges { template<input_range V> requires view<V> && input_range<range_reference_t<V>> template<bool Const> struct join_view<V>::sentinel { private: using Parent = maybe-const<Const, join_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(Parent& parent); constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); }; }
constexpr explicit sentinel(Parent& parent);
Effects: Initializes end_ with ranges​::​end(parent.base_).
constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(s.end_).
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.outer() == y.end_;

25.7.15 Join with view [range.join.with]

25.7.15.1 Overview [range.join.with.overview]

join_with_view takes a view and a delimiter, and flattens the view, inserting every element of the delimiter in between elements of the view.
The delimiter can be a single element or a view of elements.
The name views​::​join_with denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​join_with(E, F) is expression-equivalent to join_with_view(E, F).
[Example 1: vector<string> vs = {"the", "quick", "brown", "fox"}; for (char c : vs | views::join_with('-')) { cout << c; } // The above prints the-quick-brown-fox — end example]

25.7.15.2 Class template join_with_view [range.join.with.view]

namespace std::ranges { template<class R> concept bidirectional-common = bidirectional_range<R> && common_range<R>; // exposition only template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> && concatable<range_reference_t<V>, Pattern> class join_with_view : public view_interface<join_with_view<V, Pattern>> { using InnerRng = range_reference_t<V>; // exposition only V base_ = V(); // exposition only non-propagating-cache<iterator_t<V>> outer_it_; // exposition only, present only // when !forward_range<V> non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only // if is_reference_v<InnerRng> is false Pattern pattern_ = Pattern(); // exposition only // [range.join.with.iterator], class template join_with_view​::​iterator template<bool Const> struct iterator; // exposition only // [range.join.with.sentinel], class template join_with_view​::​sentinel template<bool Const> struct sentinel; // exposition only public: join_with_view() requires default_initializable<V> && default_initializable<Pattern> = default; constexpr explicit join_with_view(V base, Pattern pattern); template<input_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<InnerRng>>> constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() { if constexpr (forward_range<V>) { constexpr bool use_const = simple-view<V> && is_reference_v<InnerRng> && simple-view<Pattern>; return iterator<use_const>{*this, ranges::begin(base_)}; } else { outer_it_ = ranges::begin(base_); return iterator<false>{*this}; } } constexpr auto begin() const requires forward_range<const V> && forward_range<const Pattern> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> && concatable<range_reference_t<const V>, const Pattern> { return iterator<true>{*this, ranges::begin(base_)}; } constexpr auto end() { if constexpr (forward_range<V> && is_reference_v<InnerRng> && forward_range<InnerRng> && common_range<V> && common_range<InnerRng>) return iterator<simple-view<V> && simple-view<Pattern>>{*this, ranges::end(base_)}; else return sentinel<simple-view<V> && simple-view<Pattern>>{*this}; } constexpr auto end() const requires forward_range<const V> && forward_range<const Pattern> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> && concatable<range_reference_t<const V>, const Pattern> { using InnerConstRng = range_reference_t<const V>; if constexpr (forward_range<InnerConstRng> && common_range<const V> && common_range<InnerConstRng>) return iterator<true>{*this, ranges::end(base_)}; else return sentinel<true>{*this}; } }; template<class R, class P> join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>; template<input_range R> join_with_view(R&&, range_value_t<range_reference_t<R>>) -> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>; }
constexpr explicit join_with_view(V base, Pattern pattern);
Effects: Initializes base_ with std​::​move(base) and pattern_ with std​::​move(pattern).
template<input_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<InnerRng>>> constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
Effects: Initializes base_ with views​::​all(std​::​forward<R>(r)) and pattern_ with views​::​single(std​::​move(e)).

25.7.15.3 Class template join_with_view​::​iterator [range.join.with.iterator]

namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> && concatable<range_reference_t<V>, Pattern> template<bool Const> class join_with_view<V, Pattern>::iterator { using Parent = maybe-const<Const, join_with_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only using InnerBase = range_reference_t<Base>; // exposition only using PatternBase = maybe-const<Const, Pattern>; // exposition only using OuterIter = iterator_t<Base>; // exposition only using InnerIter = iterator_t<InnerBase>; // exposition only using PatternIter = iterator_t<PatternBase>; // exposition only static constexpr bool ref-is-glvalue = is_reference_v<InnerBase>; // exposition only Parent* parent_ = nullptr; // exposition only OuterIter outer_it_ = OuterIter(); // exposition only, present only // if Base models forward_range variant<PatternIter, InnerIter> inner_it_; // exposition only constexpr iterator(Parent& parent, OuterIter outer) requires forward_range<Base>; // exposition only constexpr explicit iterator(Parent& parent) requires (!forward_range<Base>); // exposition only constexpr OuterIter& outer(); // exposition only constexpr const OuterIter& outer() const; // exposition only constexpr auto& update-inner(); // exposition only constexpr auto& get-inner(); // exposition only constexpr void satisfy(); // exposition only public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = see below; using difference_type = see below; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, OuterIter> && convertible_to<iterator_t<InnerRng>, InnerIter> && convertible_to<iterator_t<Pattern>, PatternIter>; constexpr decltype(auto) operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ref-is-glvalue && forward_iterator<OuterIter> && forward_iterator<InnerIter>; constexpr iterator& operator--() requires ref-is-glvalue && bidirectional_range<Base> && bidirectional-common<InnerBase> && bidirectional-common<PatternBase>; constexpr iterator operator--(int) requires ref-is-glvalue && bidirectional_range<Base> && bidirectional-common<InnerBase> && bidirectional-common<PatternBase>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && forward_range<Base> && equality_comparable<InnerIter>; friend constexpr decltype(auto) iter_move(const iterator& x) { using rvalue_reference = common_reference_t< iter_rvalue_reference_t<InnerIter>, iter_rvalue_reference_t<PatternIter>>; return visit<rvalue_reference>(ranges::iter_move, x.inner_it_); } friend constexpr void iter_swap(const iterator& x, const iterator& y) requires indirectly_swappable<InnerIter, PatternIter> { visit(ranges::iter_swap, x.inner_it_, y.inner_it_); } }; }
iterator​::​iterator_concept is defined as follows:
  • If ref-is-glvalue is true, Base models bidirectional_range, and InnerBase and PatternBase each model bidirectional-common, then iterator_concept denotes bidirectional_iterator_tag.
  • Otherwise, if ref-is-glvalue is true and Base and InnerBase each model forward_range, then iterator_concept denotes forward_iterator_tag.
  • Otherwise, iterator_concept denotes input_iterator_tag.
The member typedef-name iterator_category is defined if and only if ref-is-glvalue is true, and Base and InnerBase each model forward_range.
In that case, iterator​::​iterator_category is defined as follows:
  • Let OUTERC denote iterator_traits<OuterIter>​::​iterator_category, let INNERC denote iterator_traits<InnerIter>​::​iterator_category, and let PATTERNC denote iterator_traits<PatternIter>​::​iterator_category.
  • If is_reference_v<common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>> is false, iterator_category denotes input_iterator_tag.
  • Otherwise, if OUTERC, INNERC, and PATTERNC each model derived_from<bidirectional_iterator_tag> and InnerBase and PatternBase each model common_range, iterator_category denotes bidirectional_iterator_tag.
  • Otherwise, if OUTERC, INNERC, and PATTERNC each model derived_from<forward_iterator_tag>, iterator_category denotes forward_iterator_tag.
  • Otherwise, iterator_category denotes input_iterator_tag.
iterator​::​value_type denotes the type: common_type_t<iter_value_t<InnerIter>, iter_value_t<PatternIter>>
iterator​::​difference_type denotes the type: common_type_t< iter_difference_t<OuterIter>, iter_difference_t<InnerIter>, iter_difference_t<PatternIter>>
constexpr OuterIter& outer(); constexpr const OuterIter& outer() const;
Returns: outer_it_ if Base models forward_range; otherwise, *parent_->outer_it_.
constexpr auto& update-inner();
Effects: Equivalent to: if constexpr (ref-is-glvalue) return as-lvalue(*outer()); else return parent_->inner_.emplace-deref(outer());
constexpr auto& get-inner();
Effects: Equivalent to: if constexpr (ref-is-glvalue) return as-lvalue(*outer()); else return *parent_->inner_;
constexpr void satisfy();
Effects: Equivalent to: while (true) { if (inner_it_.index() == 0) { if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_)) break; inner_it_.template emplace<1>(ranges::begin(update-inner())); } else { if (std::get<1>(inner_it_) != ranges::end(get-inner())) break; if (++outer() == ranges::end(parent_->base_)) { if constexpr (ref-is-glvalue) inner_it_.template emplace<0>(); break; } inner_it_.template emplace<0>(ranges::begin(parent_->pattern_)); } }
[Note 1: 
join_with_view iterators use the satisfy function to skip over empty inner ranges.
— end note]
constexpr iterator(Parent& parent, OuterIter outer) requires forward_range<Base>; constexpr explicit iterator(Parent& parent) requires (!forward_range<Base>);
Effects: Initializes parent_ with addressof(parent).
For the first overload, also initializes outer_it_ with std​::​move(outer).
Then, equivalent to: if (outer() != ranges::end(parent_->base_)) { inner_it_.template emplace<1>(ranges::begin(update-inner())); satisfy(); }
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, OuterIter> && convertible_to<iterator_t<InnerRng>, InnerIter> && convertible_to<iterator_t<Pattern>, PatternIter>;
Effects: Initializes outer_it_ with std​::​move(i.outer_it_) and parent_ with i.parent_.
Then, equivalent to: if (i.inner_it_.index() == 0) inner_it_.template emplace<0>(std::get<0>(std::move(i.inner_it_))); else inner_it_.template emplace<1>(std::get<1>(std::move(i.inner_it_)));
[Note 2: 
Const can only be true when Base models forward_range.
— end note]
constexpr decltype(auto) operator*() const;
Effects: Equivalent to: using reference = common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>; return visit([](auto& it) -> reference { return *it; }, inner_it_);
constexpr iterator& operator++();
Effects: Equivalent to: visit([](auto& it){ ++it; }, inner_it_); satisfy(); return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires ref-is-glvalue && forward_iterator<OuterIter> && forward_iterator<InnerIter>;
Effects: Equivalent to: iterator tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires ref-is-glvalue && bidirectional_range<Base> && bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
Effects: Equivalent to: if (outer_it_ == ranges::end(parent_->base_)) { auto&& inner = *--outer_it_; inner_it_.template emplace<1>(ranges::end(inner)); } while (true) { if (inner_it_.index() == 0) { auto& it = std::get<0>(inner_it_); if (it == ranges::begin(parent_->pattern_)) { auto&& inner = *--outer_it_; inner_it_.template emplace<1>(ranges::end(inner)); } else { break; } } else { auto& it = std::get<1>(inner_it_); auto&& inner = *outer_it_; if (it == ranges::begin(inner)) { inner_it_.template emplace<0>(ranges::end(parent_->pattern_)); } else { break; } } } visit([](auto& it){ --it; }, inner_it_); return *this;
constexpr iterator operator--(int) requires ref-is-glvalue && bidirectional_range<Base> && bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
Effects: Equivalent to: iterator tmp = *this; --*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref-is-glvalue && forward_range<Base> && equality_comparable<InnerIter>;
Effects: Equivalent to: return x.outer_it_ == y.outer_it_ && x.inner_it_ == y.inner_it_;

25.7.15.4 Class template join_with_view​::​sentinel [range.join.with.sentinel]

namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> && concatable<range_reference_t<V>, Pattern> template<bool Const> class join_with_view<V, Pattern>::sentinel { using Parent = maybe-const<Const, join_with_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only constexpr explicit sentinel(Parent& parent); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); }; }
constexpr explicit sentinel(Parent& parent);
Effects: Initializes end_ with ranges​::​end(parent.base_).
constexpr sentinel(sentinel<!Const> s) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(s.end_).
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.outer() == y.end_;

25.7.16 Lazy split view [range.lazy.split]

25.7.16.1 Overview [range.lazy.split.overview]

lazy_split_view takes a view and a delimiter, and splits the view into subranges on the delimiter.
The delimiter can be a single element or a view of elements.
The name views​::​lazy_split denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​lazy_split(E, F) is expression-equivalent to lazy_split_view(E, F).
[Example 1: string str{"the quick brown fox"}; for (auto word : str | views::lazy_split(' ')) { for (char ch : word) cout << ch; cout << '*'; } // The above prints the*quick*brown*fox* — end example]

25.7.16.2 Class template lazy_split_view [range.lazy.split.view]

namespace std::ranges { template<auto> struct require-constant; // exposition only template<class R> concept tiny-range = // exposition only sized_range<R> && requires { typename require-constant<remove_reference_t<R>::size()>; } && (remove_reference_t<R>::size() <= 1); template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || tiny-range<Pattern>) class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> { private: V base_ = V(); // exposition only Pattern pattern_ = Pattern(); // exposition only non-propagating-cache<iterator_t<V>> current_; // exposition only, present only // if forward_range<V> is false // [range.lazy.split.outer], class template lazy_split_view​::​outer-iterator template<bool> struct outer-iterator; // exposition only // [range.lazy.split.inner], class template lazy_split_view​::​inner-iterator template<bool> struct inner-iterator; // exposition only public: lazy_split_view() requires default_initializable<V> && default_initializable<Pattern> = default; constexpr explicit lazy_split_view(V base, Pattern pattern); template<input_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<R>>> constexpr explicit lazy_split_view(R&& r, range_value_t<R> e); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() { if constexpr (forward_range<V>) { return outer-iterator<simple-view<V> && simple-view<Pattern>> {*this, ranges::begin(base_)}; } else { current_ = ranges::begin(base_); return outer-iterator<false>{*this}; } } constexpr auto begin() const requires forward_range<V> && forward_range<const V> { return outer-iterator<true>{*this, ranges::begin(base_)}; } constexpr auto end() requires forward_range<V> && common_range<V> { return outer-iterator<simple-view<V> && simple-view<Pattern>> {*this, ranges::end(base_)}; } constexpr auto end() const { if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>) return outer-iterator<true>{*this, ranges::end(base_)}; else return default_sentinel; } }; template<class R, class P> lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>; template<input_range R> lazy_split_view(R&&, range_value_t<R>) -> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>; }
constexpr explicit lazy_split_view(V base, Pattern pattern);
Effects: Initializes base_ with std​::​move(base), and pattern_ with std​::​move(pattern).
template<input_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<R>>> constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
Effects: Initializes base_ with views​::​all(std​::​forward<R>(r)), and pattern_ with views​::​single(std​::​move(e)).

25.7.16.3 Class template lazy_split_view​::​outer-iterator [range.lazy.split.outer]

namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || tiny-range<Pattern>) template<bool Const> struct lazy_split_view<V, Pattern>::outer-iterator { private: using Parent = maybe-const<Const, lazy_split_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only Parent* parent_ = nullptr; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only, present only // if V models forward_range bool trailing_empty_ = false; // exposition only public: using iterator_concept = conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>; using iterator_category = input_iterator_tag; // present only if Base // models forward_range // [range.lazy.split.outer.value], class lazy_split_view​::​outer-iterator​::​value_type struct value_type; using difference_type = range_difference_t<Base>; outer-iterator() = default; constexpr explicit outer-iterator(Parent& parent) requires (!forward_range<Base>); constexpr outer-iterator(Parent& parent, iterator_t<Base> current) requires forward_range<Base>; constexpr outer-iterator(outer-iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr value_type operator*() const; constexpr outer-iterator& operator++(); constexpr decltype(auto) operator++(int) { if constexpr (forward_range<Base>) { auto tmp = *this; ++*this; return tmp; } else ++*this; } friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y) requires forward_range<Base>; friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t); }; }
Many of the specifications in [range.lazy.split] refer to the notional member current of outer-iterator.
current is equivalent to current_ if V models forward_range, and *parent_->current_ otherwise.
constexpr explicit outer-iterator(Parent& parent) requires (!forward_range<Base>);
Effects: Initializes parent_ with addressof(parent).
constexpr outer-iterator(Parent& parent, iterator_t<Base> current) requires forward_range<Base>;
Effects: Initializes parent_ with addressof(parent) and current_ with std​::​move(current).
constexpr outer-iterator(outer-iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes parent_ with i.parent_, current_ with std​::​move(i.current_), and trailing_empty_ with i.trailing_empty_.
constexpr value_type operator*() const;
Effects: Equivalent to: return value_type{*this};
constexpr outer-iterator& operator++();
Effects: Equivalent to: const auto end = ranges::end(parent_->base_); if (current == end) { trailing_empty_ = false; return *this; } const auto [pbegin, pend] = subrange{parent_->pattern_}; if (pbegin == pend) ++current; else if constexpr (tiny-range<Pattern>) { current = ranges::find(std::move(current), end, *pbegin); if (current != end) { ++current; if (current == end) trailing_empty_ = true; } } else { do { auto [b, p] = ranges::mismatch(current, end, pbegin, pend); if (p == pend) { current = b; if (current == end) trailing_empty_ = true; break; // The pattern matched; skip it } } while (++current != end); } return *this;
friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y) requires forward_range<Base>;
Effects: Equivalent to: return x.current_ == y.current_ && x.trailing_empty_ == y.trailing_empty_;
friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
Effects: Equivalent to: return x.current == ranges::end(x.parent_->base_) && !x.trailing_empty_;

25.7.16.4 Class lazy_split_view​::​outer-iterator​::​value_type [range.lazy.split.outer.value]

namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || tiny-range<Pattern>) template<bool Const> struct lazy_split_view<V, Pattern>::outer-iterator<Const>::value_type : view_interface<value_type> { private: outer-iterator i_ = outer-iterator(); // exposition only constexpr explicit value_type(outer-iterator i); // exposition only public: constexpr inner-iterator<Const> begin() const; constexpr default_sentinel_t end() const noexcept; }; }
constexpr explicit value_type(outer-iterator i);
Effects: Initializes i_ with std​::​move(i).
constexpr inner-iterator<Const> begin() const;
Effects: Equivalent to: return inner-iterator<Const>{i_};
constexpr default_sentinel_t end() const noexcept;
Effects: Equivalent to: return default_sentinel;

25.7.16.5 Class template lazy_split_view​::​inner-iterator [range.lazy.split.inner]

namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> && (forward_range<V> || tiny-range<Pattern>) template<bool Const> struct lazy_split_view<V, Pattern>::inner-iterator { private: using Base = maybe-const<Const, V>; // exposition only outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only bool incremented_ = false; // exposition only public: using iterator_concept = typename outer-iterator<Const>::iterator_concept; using iterator_category = see below; // present only if Base // models forward_range using value_type = range_value_t<Base>; using difference_type = range_difference_t<Base>; inner-iterator() = default; constexpr explicit inner-iterator(outer-iterator<Const> i); constexpr const iterator_t<Base>& base() const & noexcept; constexpr iterator_t<Base> base() && requires forward_range<V>; constexpr decltype(auto) operator*() const { return *i_.current; } constexpr inner-iterator& operator++(); constexpr decltype(auto) operator++(int) { if constexpr (forward_range<Base>) { auto tmp = *this; ++*this; return tmp; } else ++*this; } friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y) requires forward_range<Base>; friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t); friend constexpr decltype(auto) iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(i.i_.current))) { return ranges::iter_move(i.i_.current); } friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current))) requires indirectly_swappable<iterator_t<Base>>; }; }
If Base does not model forward_range there is no member iterator_category.
Otherwise, the typedef-name iterator_category denotes:
  • forward_iterator_tag if iterator_traits<iterator_t<Base>>​::​iterator_category models derived_from<forward_iterator_tag>;
  • otherwise, iterator_traits<iterator_t<Base>>​::​iterator_category.
constexpr explicit inner-iterator(outer-iterator<Const> i);
Effects: Initializes i_ with std​::​move(i).
constexpr const iterator_t<Base>& base() const & noexcept;
Effects: Equivalent to: return i_.current;
constexpr iterator_t<Base> base() && requires forward_range<V>;
Effects: Equivalent to: return std​::​move(i_.current);
constexpr inner-iterator& operator++();
Effects: Equivalent to: incremented_ = true; if constexpr (!forward_range<Base>) { if constexpr (Pattern::size() == 0) { return *this; } } ++i_.current; return *this;
friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y) requires forward_range<Base>;
Effects: Equivalent to: return x.i_.current == y.i_.current;
friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
Effects: Equivalent to: auto [pcur, pend] = subrange{x.i_.parent_->pattern_}; auto end = ranges::end(x.i_.parent_->base_); if constexpr (tiny-range<Pattern>) { const auto & cur = x.i_.current; if (cur == end) return true; if (pcur == pend) return x.incremented_; return *cur == *pcur; } else { auto cur = x.i_.current; if (cur == end) return true; if (pcur == pend) return x.incremented_; do { if (*cur != *pcur) return false; if (++pcur == pend) return true; } while (++cur != end); return false; }
friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current))) requires indirectly_swappable<iterator_t<Base>>;
Effects: Equivalent to ranges​::​iter_swap(x.i_.current, y.i_.current).

25.7.17 Split view [range.split]

25.7.17.1 Overview [range.split.overview]

split_view takes a view and a delimiter, and splits the view into subranges on the delimiter.
The delimiter can be a single element or a view of elements.
The name views​::​split denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​split(E, F) is expression-equivalent to split_view(E, F).
[Example 1: string str{"the quick brown fox"}; for (auto word : views::split(str, ' ')) { cout << string_view(word) << '*'; } // The above prints the*quick*brown*fox* — end example]

25.7.17.2 Class template split_view [range.split.view]

namespace std::ranges { template<forward_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> class split_view : public view_interface<split_view<V, Pattern>> { private: V base_ = V(); // exposition only Pattern pattern_ = Pattern(); // exposition only // [range.split.iterator], class split_view​::​iterator struct iterator; // exposition only // [range.split.sentinel], class split_view​::​sentinel struct sentinel; // exposition only public: split_view() requires default_initializable<V> && default_initializable<Pattern> = default; constexpr explicit split_view(V base, Pattern pattern); template<forward_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<R>>> constexpr explicit split_view(R&& r, range_value_t<R> e); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr iterator begin(); constexpr auto end() { if constexpr (common_range<V>) { return iterator{*this, ranges::end(base_), {}}; } else { return sentinel{*this}; } } constexpr subrange<iterator_t<V>> find-next(iterator_t<V>); // exposition only }; template<class R, class P> split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>; template<forward_range R> split_view(R&&, range_value_t<R>) -> split_view<views::all_t<R>, single_view<range_value_t<R>>>; }
constexpr explicit split_view(V base, Pattern pattern);
Effects: Initializes base_ with std​::​move(base), and pattern_ with std​::​move(pattern).
template<forward_range R> requires constructible_from<V, views::all_t<R>> && constructible_from<Pattern, single_view<range_value_t<R>>> constexpr explicit split_view(R&& r, range_value_t<R> e);
Effects: Initializes base_ with views​::​all(std​::​forward<R>(r)), and pattern_ with views​::​single(std​::​move(e)).
constexpr iterator begin();
Returns: {*this, ranges​::​begin(base_), find-next(ranges​::​begin(base_))}.
Remarks: In order to provide the amortized constant time complexity required by the range concept, this function caches the result within the split_view for use on subsequent calls.
constexpr subrange<iterator_t<V>> find-next(iterator_t<V> it);
Effects: Equivalent to: auto [b, e] = ranges::search(subrange(it, ranges::end(base_)), pattern_); if (b != ranges::end(base_) && ranges::empty(pattern_)) { ++b; ++e; } return {b, e};

25.7.17.3 Class split_view​::​iterator [range.split.iterator]

namespace std::ranges { template<forward_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> class split_view<V, Pattern>::iterator { private: split_view* parent_ = nullptr; // exposition only iterator_t<V> cur_ = iterator_t<V>(); // exposition only subrange<iterator_t<V>> next_ = subrange<iterator_t<V>>(); // exposition only bool trailing_empty_ = false; // exposition only public: using iterator_concept = forward_iterator_tag; using iterator_category = input_iterator_tag; using value_type = subrange<iterator_t<V>>; using difference_type = range_difference_t<V>; iterator() = default; constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next); constexpr iterator_t<V> base() const; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); friend constexpr bool operator==(const iterator& x, const iterator& y); }; }
constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
Effects: Initializes parent_ with addressof(parent), cur_ with std​::​move(current), and next_ with std​::​move(next).
constexpr iterator_t<V> base() const;
Effects: Equivalent to: return cur_;
constexpr value_type operator*() const;
Effects: Equivalent to: return {cur_, next_.begin()};
constexpr iterator& operator++();
Effects: Equivalent to: cur_ = next_.begin(); if (cur_ != ranges::end(parent_->base_)) { cur_ = next_.end(); if (cur_ == ranges::end(parent_->base_)) { trailing_empty_ = true; next_ = {cur_, cur_}; } else { next_ = parent_->find-next(cur_); } } else { trailing_empty_ = false; } return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y);
Effects: Equivalent to: return x.cur_ == y.cur_ && x.trailing_empty_ == y.trailing_empty_;

25.7.17.4 Class split_view​::​sentinel [range.split.sentinel]

namespace std::ranges { template<forward_range V, forward_range Pattern> requires view<V> && view<Pattern> && indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> struct split_view<V, Pattern>::sentinel { private: sentinel_t<V> end_ = sentinel_t<V>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(split_view& parent); friend constexpr bool operator==(const iterator& x, const sentinel& y); }; }
constexpr explicit sentinel(split_view& parent);
Effects: Initializes end_ with ranges​::​end(parent.base_).
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.cur_ == y.end_ && !x.trailing_empty_;

25.7.18 Concat view [range.concat]

25.7.18.1 Overview [range.concat.overview]

concat_view presents a view that concatenates all the underlying ranges.
The name views​::​concat denotes a customization point object ([customization.point.object]).
Given a pack of subexpressions Es..., the expression views​::​concat(Es...) is expression-equivalent to
  • views​::​all(Es...) if Es is a pack with only one element whose type models input_range,
  • otherwise, concat_view(Es...).
[Example 1: vector<int> v1{1, 2, 3}, v2{4, 5}, v3{}; array a{6, 7, 8}; auto s = views::single(9); for (auto&& i : views::concat(v1, v2, v3, a, s)) { print("{} ", i); // prints 1 2 3 4 5 6 7 8 9 } — end example]

25.7.18.2 Class template concat_view [range.concat.view]

namespace std::ranges { template<class... Rs> using concat-reference-t = common_reference_t<range_reference_t<Rs>...>; // exposition only template<class... Rs> using concat-value-t = common_type_t<range_value_t<Rs>...>; // exposition only template<class... Rs> using concat-rvalue-reference-t = // exposition only common_reference_t<range_rvalue_reference_t<Rs>...>; template<class... Rs> concept concat-indirectly-readable = see below; // exposition only template<class... Rs> concept concatable = see below; // exposition only template<bool Const, class... Rs> concept concat-is-random-access = see below; // exposition only template<bool Const, class... Rs> concept concat-is-bidirectional = see below; // exposition only template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...> class concat_view : public view_interface<concat_view<Views...>> { tuple<Views...> views_; // exposition only // [range.concat.iterator], class template concat_view​::​iterator template<bool> class iterator; // exposition only public: constexpr concat_view() = default; constexpr explicit concat_view(Views... views); constexpr iterator<false> begin() requires (!(simple-view<Views> && ...)); constexpr iterator<true> begin() const requires (range<const Views> && ...) && concatable<const Views...>; constexpr auto end() requires (!(simple-view<Views> && ...)); constexpr auto end() const requires (range<const Views> && ...) && concatable<const Views...>; constexpr auto size() requires (sized_range<Views> && ...); constexpr auto size() const requires (sized_range<const Views> && ...); }; template<class... R> concat_view(R&&...) -> concat_view<views::all_t<R>...>; }
template<class... Rs> concept concat-indirectly-readable = see below; // exposition only
The exposition-only concat-indirectly-readable concept is equivalent to: template<class Ref, class RRef, class It> concept concat-indirectly-readable-impl = // exposition only requires (const It it) { { *it } -> convertible_to<Ref>; { ranges::iter_move(it) } -> convertible_to<RRef>; }; template<class... Rs> concept concat-indirectly-readable = // exposition only common_reference_with<concat-reference-t<Rs...>&&, concat-value-t<Rs...>&> && common_reference_with<concat-reference-t<Rs...>&&, concat-rvalue-reference-t<Rs...>&&> && common_reference_with<concat-rvalue-reference-t<Rs...>&&, concat-value-t<Rs...> const&> && (concat-indirectly-readable-impl<concat-reference-t<Rs...>, concat-rvalue-reference-t<Rs...>, iterator_t<Rs>> && ...);
template<class... Rs> concept concatable = see below; // exposition only
The exposition-only concatable concept is equivalent to: template<class... Rs> concept concatable = requires { // exposition only typename concat-reference-t<Rs...>; typename concat-value-t<Rs...>; typename concat-rvalue-reference-t<Rs...>; } && concat-indirectly-readable<Rs...>;
template<bool Const, class... Rs> concept concat-is-random-access = see below; // exposition only
Let Fs be the pack that consists of all elements of Rs except the last element, then concat-is-random-access is equivalent to: template<bool Const, class... Rs> concept concat-is-random-access = // exposition only all-random-access<Const, Rs...> && (common_range<maybe-const<Const, Fs>> && ...);
template<bool Const, class... Rs> concept concat-is-bidirectional = see below; // exposition only
Let Fs be the pack that consists of all elements of Rs except the last element, then concat-is-bidirectional is equivalent to: template<bool Const, class... Rs> concept concat-is-bidirectional = // exposition only all-bidirectional<Const, Rs...> && (common_range<maybe-const<Const, Fs>> && ...);
constexpr explicit concat_view(Views... views);
Effects: Initializes views_ with std​::​move(views)....
constexpr iterator<false> begin() requires (!(simple-view<Views> && ...)); constexpr iterator<true> begin() const requires (range<const Views> && ...) && concatable<const Views...>;
Effects: Let is-const be true for the const-qualified overload, and false otherwise.
Equivalent to: iterator<is-const> it(this, in_place_index<0>, ranges::begin(std::get<0>(views_))); it.template satisfy<0>(); return it;
constexpr auto end() requires (!(simple-view<Views> && ...)); constexpr auto end() const requires (range<const Views> && ...) && concatable<const Views...>;
Effects: Let is-const be true for the const-qualified overload, and false otherwise.
Equivalent to: constexpr auto N = sizeof...(Views); if constexpr (common_range<maybe-const<is-const, Views...[N - 1]>>) { return iterator<is-const>(this, in_place_index<N - 1>, ranges::end(std::get<N - 1>(views_))); } else { return default_sentinel; }
constexpr auto size() requires (sized_range<Views> && ...); constexpr auto size() const requires (sized_range<const Views> && ...);
Effects: Equivalent to: return apply( [](auto... sizes) { using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>; return (CT(sizes) + ...); }, tuple-transform(ranges::size, views_));

25.7.18.3 Class concat_view​::​iterator [range.concat.iterator]

namespace std::ranges { template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...> template<bool Const> class concat_view<Views...>::iterator { public: using iterator_category = see below; // not always present using iterator_concept = see below; using value_type = concat-value-t<maybe-const<Const, Views>...>; using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>; private: using base-iter = // exposition only variant<iterator_t<maybe-const<Const, Views>>...>; maybe-const<Const, concat_view>* parent_ = nullptr; // exposition only base-iter it_; // exposition only template<size_t N> constexpr void satisfy(); // exposition only template<size_t N> constexpr void prev(); // exposition only template<size_t N> constexpr void advance-fwd(difference_type offset, // exposition only difference_type steps); template<size_t N> constexpr void advance-bwd(difference_type offset, // exposition only difference_type steps); template<class... Args> constexpr explicit iterator(maybe-const<Const, concat_view>* parent, // exposition only Args&&... args) requires constructible_from<base-iter, Args&&...>; public: iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...); constexpr decltype(auto) operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires all-forward<Const, Views...>; constexpr iterator& operator--() requires concat-is-bidirectional<Const, Views...>; constexpr iterator operator--(int) requires concat-is-bidirectional<Const, Views...>; constexpr iterator& operator+=(difference_type n) requires concat-is-random-access<Const, Views...>; constexpr iterator& operator-=(difference_type n) requires concat-is-random-access<Const, Views...>; constexpr decltype(auto) operator[](difference_type n) const requires concat-is-random-access<Const, Views...>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...); friend constexpr bool operator==(const iterator& it, default_sentinel_t); friend constexpr bool operator<(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires (all-random-access<Const, Views...> && (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...)); friend constexpr iterator operator+(const iterator& it, difference_type n) requires concat-is-random-access<Const, Views...>; friend constexpr iterator operator+(difference_type n, const iterator& it) requires concat-is-random-access<Const, Views...>; friend constexpr iterator operator-(const iterator& it, difference_type n) requires concat-is-random-access<Const, Views...>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires concat-is-random-access<Const, Views...>; friend constexpr difference_type operator-(const iterator& x, default_sentinel_t) requires see below; friend constexpr difference_type operator-(default_sentinel_t, const iterator& x) requires see below; friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below) requires see below; }; }
iterator​::​iterator_concept is defined as follows:
  • If concat-is-random-access<Const, Views...> is modeled, then iterator_concept denotes random_access_iterator_tag.
  • Otherwise, if concat-is-bidirectional<Const, Views...> is modeled, then iterator_concept denotes bidirectional_iterator_tag.
  • Otherwise, if all-forward<Const, Views...> is modeled, then iterator_concept denotes forward_iterator_tag.
  • Otherwise, iterator_concept denotes input_iterator_tag.
The member typedef-name iterator_category is defined if and only if all-forward<Const, Views...> is modeled.
In that case, iterator​::​iterator_category is defined as follows:
  • If is_reference_v<concat-reference-t<maybe-const<Const, Views>...>> is false, then iterator_category denotes input_iterator_tag.
  • Otherwise, let Cs denote the pack of types iterator_traits<iterator_t<maybe-const<Const, Views>>>​::​iterator_category....
    • If (derived_from<Cs, random_access_iterator_tag> && ...) && concat-is-random-access<Const, Views...> is true, iterator_category denotes random_access_iterator_tag.
    • Otherwise, if (derived_from<Cs, bidirectional_iterator_tag> && ...) && concat-is-bidirectional<Const, Views...> is true, iterator_category denotes bidirectional_iterator_tag.
    • Otherwise, if (derived_from<Cs, forward_iterator_tag> && ...) is true, iterator_category denotes forward_iterator_tag.
    • Otherwise, iterator_category denotes input_iterator_tag.
template<size_t N> constexpr void satisfy();
Effects: Equivalent to: if constexpr (N < (sizeof...(Views) - 1)) { if (std::get<N>(it_) == ranges::end(std::get<N>(parent_->views_))) { it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_))); satisfy<N + 1>(); } }
template<size_t N> constexpr void prev();
Effects: Equivalent to: if constexpr (N == 0) { --std::get<0>(it_); } else { if (std::get<N>(it_) == ranges::begin(std::get<N>(parent_->views_))) { it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_))); prev<N - 1>(); } else { --std::get<N>(it_); } }
template<size_t N> constexpr void advance-fwd(difference_type offset, difference_type steps);
Effects: Equivalent to: using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>; if constexpr (N == sizeof...(Views) - 1) { std::get<N>(it_) += static_cast<underlying_diff_type>(steps); } else { auto n_size = ranges::distance(std::get<N>(parent_->views_)); if (offset + steps < n_size) { std::get<N>(it_) += static_cast<underlying_diff_type>(steps); } else { it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_))); advance-fwd<N + 1>(0, offset + steps - n_size); } }
template<size_t N> constexpr void advance-bwd(difference_type offset, difference_type steps);
Effects: Equivalent to: using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>; if constexpr (N == 0) { std::get<N>(it_) -= static_cast<underlying_diff_type>(steps); } else { if (offset >= steps) { std::get<N>(it_) -= static_cast<underlying_diff_type>(steps); } else { auto prev_size = ranges::distance(std::get<N - 1>(parent_->views_)); it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_))); advance-bwd<N - 1>(prev_size, steps - offset); } }
template<class... Args> constexpr explicit iterator(maybe-const<Const, concat_view>* parent, Args&&... args) requires constructible_from<base-iter, Args&&...>;
Effects: Initializes parent_ with parent, and initializes it_ with std​::​forward<Args>(args)....
constexpr iterator(iterator<!Const> it) requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
Preconditions: it.it_.valueless_by_exception() is false.
Effects: Initializes parent_ with it.parent_, and let i be it.it_.index(), initializes it_ with base-iter(in_place_index<i>, std​::​get<i>(std​::​move(it.it_))).
constexpr decltype(auto) operator*() const;
Preconditions: it_.valueless_by_exception() is false.
Effects: Equivalent to: using reference = concat-reference-t<maybe-const<Const, Views>...>; return std::visit([](auto&& it) -> reference { return *it; }, it_);
constexpr iterator& operator++();
Preconditions: it_.valueless_by_exception() is false.
Effects: Let i be it_.index().
Equivalent to: ++std::get<i>(it_); satisfy<i>(); return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++*this;
constexpr iterator operator++(int) requires all-forward<Const, Views...>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires concat-is-bidirectional<Const, Views...>;
Preconditions: it_.valueless_by_exception() is false.
Effects: Let i be it_.index().
Equivalent to: prev<i>(); return *this;
constexpr iterator operator--(int) requires concat-is-bidirectional<Const, Views...>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type n) requires concat-is-random-access<Const, Views...>;
Preconditions: it_.valueless_by_exception() is false.
Effects: Let i be it_.index().
Equivalent to: if (n > 0) { advance-fwd<i>(std::get<i>(it_) - ranges::begin(std::get<i>(parent_->views_)), n); } else if (n < 0) { advance-bwd<i>(std::get<i>(it_) - ranges::begin(std::get<i>(parent_->views_)), -n); } return *this;
constexpr iterator& operator-=(difference_type n) requires concat-is-random-access<Const, Views...>;
Effects: Equivalent to: *this += -n; return *this;
constexpr decltype(auto) operator[](difference_type n) const requires concat-is-random-access<Const, Views...>;
Effects: Equivalent to: return *((*this) + n);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
Preconditions: x.it_.valueless_by_exception() and y.it_.valueless_by_exception() are each false.
Effects: Equivalent to: return x.it_ == y.it_;
friend constexpr bool operator==(const iterator& it, default_sentinel_t);
Preconditions: it.it_.valueless_by_exception() is false.
Effects: Equivalent to: constexpr auto last_idx = sizeof...(Views) - 1; return it.it_.index() == last_idx && std::get<last_idx>(it.it_) == ranges::end(std::get<last_idx>(it.parent_->views_));
friend constexpr bool operator<(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires (all-random-access<Const, Views...> && (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...));
Preconditions: x.it_.valueless_by_exception() and y.it_.valueless_by_exception() are each false.
Let op be the operator.
Effects: Equivalent to: return x.it_ op y.it_;
friend constexpr iterator operator+(const iterator& it, difference_type n) requires concat-is-random-access<Const, Views...>;
Effects: Equivalent to: auto temp = it; temp += n; return temp;
friend constexpr iterator operator+(difference_type n, const iterator& it) requires concat-is-random-access<Const, Views...>;
Effects: Equivalent to: return it + n;
friend constexpr iterator operator-(const iterator& it, difference_type n) requires concat-is-random-access<Const, Views...>;
Effects: Equivalent to: auto temp = it; temp -= n; return temp;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires concat-is-random-access<Const, Views...>;
Preconditions: x.it_.valueless_by_exception() and y.it_.valueless_by_exception() are each false.
Effects: Let denote x.it_.index() and denote y.it_.index().
  • If > , let be ranges​::​distance(std​::​get<>(y.it_), ranges​::​end(std​::​get<>(y.parent_->views_))), be ranges​::​distance(ranges​::​begin(std​::​get<>(x.parent_->views_)), std​::​get<>(x.it_)).
    Let s denote the sum of the sizes of all the ranges std​::​get<i>(x.parent_->views_) for every integer i in the range [ + 1, ) if there is any, and 0 otherwise, of type difference_type, equivalent to: return + s + ;
  • otherwise, if < is true, equivalent to: return -(y - x);
  • otherwise, equivalent to: return std::get<>(x.it_) - std::get<>(y.it_);
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t) requires see below;
Preconditions: x.it_.valueless_by_exception() is false.
Effects: Let denote x.it_.index(), be ranges​::​distance(std​::​get<>(x.it_), ranges​::​end(std​::​get<>(x.parent_->views_))).
Let s denote the sum of the sizes of all the ranges std​::​get<i>(x.parent_->views_) for every integer i in the range [ + 1, sizeof...(Views)) if there is any, and 0 otherwise, of type difference_type, equivalent to: return -( + s);
Remarks: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the requires-clause is equivalent to: (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...) && (sized_range<maybe-const<Const, Fs>> && ...)
friend constexpr difference_type operator-(default_sentinel_t, const iterator& x) requires see below;
Effects: Equivalent to: return -(x - default_sentinel);
Remarks: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the requires-clause is equivalent to: (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...) && (sized_range<maybe-const<Const, Fs>> && ...)
friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
Preconditions: it.it_.valueless_by_exception() is false.
Effects: Equivalent to: return std::visit([](const auto& i) -> concat-rvalue-reference-t<maybe-const<Const, Views>...> { return ranges::iter_move(i); }, it.it_);
Remarks: The exception specification is equivalent to: ((is_nothrow_invocable_v<decltype(ranges::iter_move), const iterator_t<maybe-const<Const, Views>>&> && is_nothrow_convertible_v<range_rvalue_reference_t<maybe-const<Const, Views>>, concat-rvalue-reference-t<maybe-const<Const, Views>...>>) && ...)
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below) requires see below;
Preconditions: x.it_.valueless_by_exception() and y.it_.valueless_by_exception() are each false.
Effects: Equivalent to: std::visit([&](const auto& it1, const auto& it2) { if constexpr (is_same_v<decltype(it1), decltype(it2)>) { ranges::iter_swap(it1, it2); } else { ranges::swap(*x, *y); } }, x.it_, y.it_);
Remarks: The exception specification is equivalent to (noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its))) where its is a pack of lvalues of type const iterator_t<maybe-const<Const, Views>> respectively.
The expression in the requires-clause is equivalent to swappable_with<iter_reference_t<iterator>, iter_reference_t<iterator>> && (... && indirectly_swappable<iterator_t<maybe-const<Const, Views>>>)

25.7.19 Counted view [range.counted]

A counted view presents a view of the elements of the counted range ([iterator.requirements.general]) for an iterator i and non-negative integer n.
The name views​::​counted denotes a customization point object ([customization.point.object]).
Let E and F be expressions, let T be decay_t<decltype((E))>, and let D be iter_difference_t<T>.
If decltype((F)) does not model convertible_to<D>, views​::​counted(E, F) is ill-formed.
[Note 1: 
This case can result in substitution failure when views​::​counted(E, F) appears in the immediate context of a template instantiation.
— end note]
Otherwise, views​::​counted(E, F) is expression-equivalent to:
  • If T models contiguous_iterator, then span(to_address(E), static_cast<size_t>(static_cast<D>(F))).
  • Otherwise, if T models random_access_iterator, then subrange(E, E + static_cast<D>(F)), except that E is evaluated only once.
  • Otherwise, subrange(counted_iterator(E, F), default_sentinel).

25.7.20 Common view [range.common]

25.7.20.1 Overview [range.common.overview]

common_view takes a view which has different types for its iterator and sentinel and turns it into a view of the same elements with an iterator and sentinel of the same type.
[Note 1: 
common_view is useful for calling legacy algorithms that expect a range's iterator and sentinel types to be the same.
— end note]
The name views​::​common denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​common(E) is expression-equivalent to:
  • views​::​all(E), if decltype((E)) models common_range and views​::​all(E) is a well-formed expression.
  • Otherwise, common_view{E}.
[Example 1: // Legacy algorithm: template<class ForwardIterator> size_t count(ForwardIterator first, ForwardIterator last); template<forward_range R> void my_algo(R&& r) { auto&& common = views::common(r); auto cnt = count(common.begin(), common.end()); // ... } — end example]

25.7.20.2 Class template common_view [range.common.view]

namespace std::ranges { template<view V> requires (!common_range<V> && copyable<iterator_t<V>>) class common_view : public view_interface<common_view<V>> { private: V base_ = V(); // exposition only public: common_view() requires default_initializable<V> = default; constexpr explicit common_view(V r); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { if constexpr (random_access_range<V> && sized_range<V>) return ranges::begin(base_); else return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_)); } constexpr auto begin() const requires range<const V> { if constexpr (random_access_range<const V> && sized_range<const V>) return ranges::begin(base_); else return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_)); } constexpr auto end() requires (!simple-view<V>) { if constexpr (random_access_range<V> && sized_range<V>) return ranges::begin(base_) + ranges::distance(base_); else return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_)); } constexpr auto end() const requires range<const V> { if constexpr (random_access_range<const V> && sized_range<const V>) return ranges::begin(base_) + ranges::distance(base_); else return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_)); } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } }; template<class R> common_view(R&&) -> common_view<views::all_t<R>>; }
constexpr explicit common_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.21 Reverse view [range.reverse]

25.7.21.1 Overview [range.reverse.overview]

reverse_view takes a bidirectional view and produces another view that iterates the same elements in reverse order.
The name views​::​reverse denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​reverse(E) is expression-equivalent to:
  • If the type of E is a (possibly cv-qualified) specialization of reverse_view, then E.base().
  • Otherwise, if the type of E is cv subrange<reverse_iterator<I>, reverse_iterator<I>, K> for some iterator type I and value K of type subrange_kind,
    • if K is subrange_kind​::​sized, then subrange<I, I, K>(E.end().base(), E.begin().base(), E.size());
    • otherwise, subrange<I, I, K>(E.end().base(), E.begin().base()).
    However, in either case E is evaluated only once.
  • Otherwise, reverse_view{E}.
[Example 1: vector<int> is {0,1,2,3,4}; for (int i : is | views::reverse) cout << i << ' '; // prints 4 3 2 1 0 — end example]

25.7.21.2 Class template reverse_view [range.reverse.view]

namespace std::ranges { template<view V> requires bidirectional_range<V> class reverse_view : public view_interface<reverse_view<V>> { private: V base_ = V(); // exposition only public: reverse_view() requires default_initializable<V> = default; constexpr explicit reverse_view(V r); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr reverse_iterator<iterator_t<V>> begin(); constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>; constexpr auto begin() const requires common_range<const V>; constexpr reverse_iterator<iterator_t<V>> end(); constexpr auto end() const requires common_range<const V>; constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } }; template<class R> reverse_view(R&&) -> reverse_view<views::all_t<R>>; }
constexpr explicit reverse_view(V base);
Effects: Initializes base_ with std​::​move(base).
constexpr reverse_iterator<iterator_t<V>> begin();
Returns: make_reverse_iterator(ranges::next(ranges::begin(base_), ranges::end(base_)))
Remarks: In order to provide the amortized constant time complexity required by the range concept, this function caches the result within the reverse_view for use on subsequent calls.
constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>; constexpr auto begin() const requires common_range<const V>;
Effects: Equivalent to: return make_reverse_iterator(ranges​::​end(base_));
constexpr reverse_iterator<iterator_t<V>> end(); constexpr auto end() const requires common_range<const V>;
Effects: Equivalent to: return make_reverse_iterator(ranges​::​begin(base_));

25.7.22 As const view [range.as.const]

25.7.22.1 Overview [range.as.const.overview]

as_const_view presents a view of an underlying sequence as constant.
That is, the elements of an as_const_view cannot be modified.
The name views​::​as_const denotes a range adaptor object ([range.adaptor.object]).
Let E be an expression, let T be decltype((E)), and let U be remove_cvref_t<T>.
The expression views​::​as_const(E) is expression-equivalent to:
  • If views​::​all_t<T> models constant_range, then views​::​all(E).
  • Otherwise, if U denotes empty_view<X> for some type X, then auto(views​::​empty<const X>).
  • Otherwise, if U denotes span<X, Extent> for some type X and some extent Extent, then span<const X, Extent>(E).
  • Otherwise, if U denotes ref_view<X> for some type X and const X models constant_range, then ref_view(static_cast<const X&>(E.base())).
  • Otherwise, if E is an lvalue, const U models constant_range, and U does not model view, then ref_view(static_cast<const U&>(E)).
  • Otherwise, as_const_view(E).
[Example 1: template<constant_range R> void cant_touch_this(R&&); vector<char> hammer = {'m', 'c'}; span<char> beat = hammer; cant_touch_this(views::as_const(beat)); // will not modify the elements of hammer — end example]

25.7.22.2 Class template as_const_view [range.as.const.view]

namespace std::ranges { template<view V> requires input_range<V> class as_const_view : public view_interface<as_const_view<V>> { V base_ = V(); // exposition only public: as_const_view() requires default_initializable<V> = default; constexpr explicit as_const_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { return ranges::cbegin(base_); } constexpr auto begin() const requires range<const V> { return ranges::cbegin(base_); } constexpr auto end() requires (!simple-view<V>) { return ranges::cend(base_); } constexpr auto end() const requires range<const V> { return ranges::cend(base_); } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } }; template<class R> as_const_view(R&&) -> as_const_view<views::all_t<R>>; }
constexpr explicit as_const_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.23 Elements view [range.elements]

25.7.23.1 Overview [range.elements.overview]

elements_view takes a view of tuple-like values and a size_t, and produces a view with a value-type of the element of the adapted view's value-type.
The name views​::​elements<N> denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E and constant expression N, the expression views​::​elements<N>(E) is expression-equivalent to elements_view<views​::​all_t<decltype((E))>, N>{E}.
[Example 1: 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 Babbage Hamilton Lovelace Turing } auto birth_years = historical_figures | views::elements<1>; for (auto&& born : birth_years) { cout << born << ' '; // prints 1791 1936 1815 1912 } — end example]
keys_view is an alias for elements_view<R, 0>, and is useful for extracting keys from associative containers.
[Example 2: auto names = historical_figures | views::keys; for (auto&& name : names) { cout << name << ' '; // prints Babbage Hamilton Lovelace Turing } — end example]
values_view is an alias for elements_view<R, 1>, and is useful for extracting values from associative containers.
[Example 3: auto is_even = [](const auto x) { return x % 2 == 0; }; cout << ranges::count_if(historical_figures | views::values, is_even); // prints 2 — end example]

25.7.23.2 Class template elements_view [range.elements.view]

namespace std::ranges { template<class T, size_t N> concept has-tuple-element = // exposition only tuple-like<T> && N < tuple_size_v<T>; template<class T, size_t N> concept returnable-element = // exposition only is_reference_v<T> || move_constructible<tuple_element_t<N, T>>; template<input_range V, size_t N> requires view<V> && has-tuple-element<range_value_t<V>, N> && has-tuple-element<remove_reference_t<range_reference_t<V>>, N> && returnable-element<range_reference_t<V>, N> class elements_view : public view_interface<elements_view<V, N>> { public: elements_view() requires default_initializable<V> = default; constexpr explicit elements_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(ranges::begin(base_)); } constexpr auto begin() const requires range<const V> { return iterator<true>(ranges::begin(base_)); } constexpr auto end() requires (!simple-view<V> && !common_range<V>) { return sentinel<false>{ranges::end(base_)}; } constexpr auto end() requires (!simple-view<V> && common_range<V>) { return iterator<false>{ranges::end(base_)}; } constexpr auto end() const requires range<const V> { return sentinel<true>{ranges::end(base_)}; } constexpr auto end() const requires common_range<const V> { return iterator<true>{ranges::end(base_)}; } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } private: // [range.elements.iterator], class template elements_view​::​iterator template<bool> class iterator; // exposition only // [range.elements.sentinel], class template elements_view​::​sentinel template<bool> class sentinel; // exposition only V base_ = V(); // exposition only }; }
constexpr explicit elements_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.23.3 Class template elements_view​::​iterator [range.elements.iterator]

namespace std::ranges { template<input_range V, size_t N> requires view<V> && has-tuple-element<range_value_t<V>, N> && has-tuple-element<remove_reference_t<range_reference_t<V>>, N> && returnable-element<range_reference_t<V>, N> template<bool Const> class elements_view<V, N>::iterator { using Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only static constexpr decltype(auto) get-element(const iterator_t<Base>& i); // exposition only public: using iterator_concept = see below; using iterator_category = see below; // not always present using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>; using difference_type = range_difference_t<Base>; iterator() requires default_initializable<iterator_t<Base>> = default; constexpr explicit iterator(iterator_t<Base> current); constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr const iterator_t<Base>& base() const & noexcept; constexpr iterator_t<Base> base() &&; constexpr decltype(auto) operator*() const { return get-element(current_); } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base> { return get-element(current_ + n); } friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<Base>>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; }; }
The member typedef-name iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if Base models forward_range.
In that case, iterator_category is defined as follows: Let C denote the type iterator_traits<iterator_t<Base>>​::​iterator_category.
  • If std​::​get<N>(*current_) is an rvalue, iterator_category denotes input_iterator_tag.
  • Otherwise, if C models derived_from<random_access_iterator_tag>, iterator_category denotes random_access_iterator_tag.
  • Otherwise, iterator_category denotes C.
static constexpr decltype(auto) get-element(const iterator_t<Base>& i);
Effects: Equivalent to: if constexpr (is_reference_v<range_reference_t<Base>>) { return std::get<N>(*i); } else { using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>; return static_cast<E>(std::get<N>(*i)); }
constexpr explicit iterator(iterator_t<Base> current);
Effects: Initializes current_ with std​::​move(current).
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_).
constexpr const iterator_t<Base>& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr iterator_t<Base> base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr iterator& operator++();
Effects: Equivalent to: ++current_; return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++current_.
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto temp = *this; ++current_; return temp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --current_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto temp = *this; --current_; return temp;
constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ += n; return *this;
constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ -= n; return *this;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<Base>;
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return x.current_ < y.current_;
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Effects: Equivalent to: return x.current_ <=> y.current_;
friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: return iterator{x} += y;
friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y + x;
friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: return iterator{x} -= y;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return x.current_ - y.current_;

25.7.23.4 Class template elements_view​::​sentinel [range.elements.sentinel]

namespace std::ranges { template<input_range V, size_t N> requires view<V> && has-tuple-element<range_value_t<V>, N> && has-tuple-element<remove_reference_t<range_reference_t<V>>, N> && returnable-element<range_reference_t<V>, N> template<bool Const> class elements_view<V, N>::sentinel { private: using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only public: sentinel() = default; constexpr explicit sentinel(sentinel_t<Base> end); constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(other.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ == y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ - y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y);
Effects: Equivalent to: return x.end_ - y.current_;

25.7.24 Enumerate view [range.enumerate]

25.7.24.1 Overview [range.enumerate.overview]

enumerate_view is a view whose elements represent both the position and value from a sequence of elements.
The name views​::​enumerate denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E, the expression views​::​enumerate(E) is expression-equivalent to enumerate_view<views​::​all_t<decltype((E))>>(E).
[Example 1: vector<int> vec{ 1, 2, 3 }; for (auto [index, value] : views::enumerate(vec)) cout << index << ":" << value << ' '; // prints 0:1 1:2 2:3 — end example]

25.7.24.2 Class template enumerate_view [range.enumerate.view]

namespace std::ranges { template<view V> requires range-with-movable-references<V> class enumerate_view : public view_interface<enumerate_view<V>> { V base_ = V(); // exposition only // [range.enumerate.iterator], class template enumerate_view​::​iterator template<bool Const> class iterator; // exposition only // [range.enumerate.sentinel], class template enumerate_view​::​sentinel template<bool Const> class sentinel; // exposition only public: constexpr enumerate_view() requires default_initializable<V> = default; constexpr explicit enumerate_view(V base); constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(ranges::begin(base_), 0); } constexpr auto begin() const requires range-with-movable-references<const V> { return iterator<true>(ranges::begin(base_), 0); } constexpr auto end() requires (!simple-view<V>) { if constexpr (forward_range<V> && common_range<V> && sized_range<V>) return iterator<false>(ranges::end(base_), ranges::distance(base_)); else return sentinel<false>(ranges::end(base_)); } constexpr auto end() const requires range-with-movable-references<const V> { if constexpr (forward_range<const V> && common_range<const V> && sized_range<const V>) return iterator<true>(ranges::end(base_), ranges::distance(base_)); else return sentinel<true>(ranges::end(base_)); } constexpr auto size() requires sized_range<V> { return ranges::size(base_); } constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); } constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } }; template<class R> enumerate_view(R&&) -> enumerate_view<views::all_t<R>>; }
constexpr explicit enumerate_view(V base);
Effects: Initializes base_ with std​::​move(base).

25.7.24.3 Class template enumerate_view​::​iterator [range.enumerate.iterator]

namespace std::ranges { template<view V> requires range-with-movable-references<V> template<bool Const> class enumerate_view<V>::iterator { using Base = maybe-const<Const, V>; // exposition only public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using difference_type = range_difference_t<Base>; using value_type = tuple<difference_type, range_value_t<Base>>; private: using reference-type = // exposition only tuple<difference_type, range_reference_t<Base>>; iterator_t<Base> current_ = iterator_t<Base>(); // exposition only difference_type pos_ = 0; // exposition only constexpr explicit iterator(iterator_t<Base> current, difference_type pos); // exposition only public: iterator() requires default_initializable<iterator_t<Base>> = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr const iterator_t<Base>& base() const & noexcept; constexpr iterator_t<Base> base() &&; constexpr difference_type index() const noexcept; constexpr auto operator*() const { return reference-type(pos_, *current_); } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr auto operator[](difference_type n) const requires random_access_range<Base> { return reference-type(pos_ + n, current_[n]); } friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept; friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept; friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept; friend constexpr auto iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)) && is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) { return tuple<difference_type, range_rvalue_reference_t<Base>>(i.pos_, ranges::iter_move(i.current_)); } }; }
The member typedef-name iterator​::​iterator_concept is defined as follows:
constexpr explicit iterator(iterator_t<Base> current, difference_type pos);
Effects: Initializes current_ with std​::​move(current) and pos_ with pos.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_) and pos_ with i.pos_.
constexpr const iterator_t<Base>& base() const & noexcept;
Effects: Equivalent to: return current_;
constexpr iterator_t<Base> base() &&;
Effects: Equivalent to: return std​::​move(current_);
constexpr difference_type index() const noexcept;
Effects: Equivalent to: return pos_;
constexpr iterator& operator++();
Effects: Equivalent to: ++current_; ++pos_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto temp = *this; ++*this; return temp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --current_; --pos_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto temp = *this; --*this; return temp;
constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ += n; pos_ += n; return *this;
constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: current_ -= n; pos_ -= n; return *this;
friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ == y.pos_;
friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ <=> y.pos_;
friend constexpr iterator operator+(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: auto temp = x; temp += y; return temp;
friend constexpr iterator operator+(difference_type x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y + x;
friend constexpr iterator operator-(const iterator& x, difference_type y) requires random_access_range<Base>;
Effects: Equivalent to: auto temp = x; temp -= y; return temp;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept;
Effects: Equivalent to: return x.pos_ - y.pos_;

25.7.24.4 Class template enumerate_view​::​sentinel [range.enumerate.sentinel]

namespace std::ranges { template<view V> requires range-with-movable-references<V> template<bool Const> class enumerate_view<V>::sentinel { using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only constexpr explicit sentinel(sentinel_t<Base> end); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr sentinel_t<Base> base() const; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with std​::​move(end).
constexpr sentinel(sentinel<!Const> other) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(other.end_).
constexpr sentinel_t<Base> base() const;
Effects: Equivalent to: return end_;
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ == y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_ - y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& x, const iterator<OtherConst>& y);
Effects: Equivalent to: return x.end_ - y.current_;

25.7.25 Zip view [range.zip]

25.7.25.1 Overview [range.zip.overview]

zip_view takes any number of views and produces a view of tuples of references to the corresponding elements of the constituent views.
The name views​::​zip denotes a customization point object ([customization.point.object]).
Given a pack of subexpressions Es..., the expression views​::​zip(Es...) is expression-equivalent to
  • auto(views​::​empty<tuple<>>) if Es is an empty pack,
  • otherwise, zip_view<views​::​all_t<decltype((Es))>...>(Es...).
[Example 1: vector v = {1, 2}; list l = {'a', 'b', 'c'}; auto z = views::zip(v, l); range_reference_t<decltype(z)> f = z.front(); // f is a tuple<int&, char&> // that refers to the first element of v and l for (auto&& [x, y] : z) { cout << '(' << x << ", " << y << ") "; // prints (1, a) (2, b) } — end example]

25.7.25.2 Class template zip_view [range.zip.view]

namespace std::ranges { template<class... Rs> concept zip-is-common = // exposition only (sizeof...(Rs) == 1 && (common_range<Rs> && ...)) || (!(bidirectional_range<Rs> && ...) && (common_range<Rs> && ...)) || ((random_access_range<Rs> && ...) && (sized_range<Rs> && ...)); template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) class zip_view : public view_interface<zip_view<Views...>> { tuple<Views...> views_; // exposition only // [range.zip.iterator], class template zip_view​::​iterator template<bool> class iterator; // exposition only // [range.zip.sentinel], class template zip_view​::​sentinel template<bool> class sentinel; // exposition only public: zip_view() = default; constexpr explicit zip_view(Views... views); constexpr auto begin() requires (!(simple-view<Views> && ...)) { return iterator<false>(tuple-transform(ranges::begin, views_)); } constexpr auto begin() const requires (range<const Views> && ...) { return iterator<true>(tuple-transform(ranges::begin, views_)); } constexpr auto end() requires (!(simple-view<Views> && ...)) { if constexpr (!zip-is-common<Views...>) { return sentinel<false>(tuple-transform(ranges::end, views_)); } else if constexpr ((random_access_range<Views> && ...)) { return begin() + iter_difference_t<iterator<false>>(size()); } else { return iterator<false>(tuple-transform(ranges::end, views_)); } } constexpr auto end() const requires (range<const Views> && ...) { if constexpr (!zip-is-common<const Views...>) { return sentinel<true>(tuple-transform(ranges::end, views_)); } else if constexpr ((random_access_range<const Views> && ...)) { return begin() + iter_difference_t<iterator<true>>(size()); } else { return iterator<true>(tuple-transform(ranges::end, views_)); } } constexpr auto size() requires (sized_range<Views> && ...); constexpr auto size() const requires (sized_range<const Views> && ...); }; template<class... Rs> zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>; }
Two zip_view objects have the same underlying sequence if and only if the corresponding elements of views_ are equal ([concepts.equality]) and have the same underlying sequence.
[Note 1: 
In particular, comparison of iterators obtained from zip_view objects that do not have the same underlying sequence is not required to produce meaningful results ([iterator.concept.forward]).
— end note]
constexpr explicit zip_view(Views... views);
Effects: Initializes views_ with std​::​move(views)....
constexpr auto size() requires (sized_range<Views> && ...); constexpr auto size() const requires (sized_range<const Views> && ...);
Effects: Equivalent to: return apply([](auto... sizes) { using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>; return ranges::min({CT(sizes)...}); }, tuple-transform(ranges::size, views_));

25.7.25.3 Class template zip_view​::​iterator [range.zip.iterator]

namespace std::ranges { template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) template<bool Const> class zip_view<Views...>::iterator { tuple<iterator_t<maybe-const<Const, Views>>...> current_; // exposition only constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...>); // exposition only public: using iterator_category = input_iterator_tag; // not always present using iterator_concept = see below; using value_type = tuple<range_value_t<maybe-const<Const, Views>>...>; using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...); constexpr auto operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires all-forward<Const, Views...>; constexpr iterator& operator--() requires all-bidirectional<Const, Views...>; constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>; constexpr iterator& operator+=(difference_type x) requires all-random-access<Const, Views...>; constexpr iterator& operator-=(difference_type x) requires all-random-access<Const, Views...>; constexpr auto operator[](difference_type n) const requires all-random-access<Const, Views...>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...); friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires all-random-access<Const, Views...>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires all-random-access<Const, Views...>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires all-random-access<Const, Views...>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...); friend constexpr auto iter_move(const iterator& i) noexcept(see below); friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...); }; }
iterator​::​iterator_concept is defined as follows:
  • If all-random-access<Const, Views...> is modeled, then iterator_concept denotes random_access_iterator_tag.
  • Otherwise, if all-bidirectional<Const, Views...> is modeled, then iterator_concept denotes bidirectional_iterator_tag.
  • Otherwise, if all-forward<Const, Views...> is modeled, then iterator_concept denotes forward_iterator_tag.
  • Otherwise, iterator_concept denotes input_iterator_tag.
iterator​::​iterator_category is present if and only if all-forward<Const, Views...> is modeled.
If the invocation of any non-const member function of iterator exits via an exception, the iterator acquires a singular value.
constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...> current);
Effects: Initializes current_ with std​::​move(current).
constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
Effects: Initializes current_ with std​::​move(i.current_).
constexpr auto operator*() const;
Effects: Equivalent to: return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
constexpr iterator& operator++();
Effects: Equivalent to: tuple-for-each([](auto& i) { ++i; }, current_); return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires all-forward<Const, Views...>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
Effects: Equivalent to: tuple-for-each([](auto& i) { --i; }, current_); return *this;
constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires all-random-access<Const, Views...>;
Effects: Equivalent to: tuple-for-each([&]<class I>(I& i) { i += iter_difference_t<I>(x); }, current_); return *this;
constexpr iterator& operator-=(difference_type x) requires all-random-access<Const, Views...>;
Effects: Equivalent to: tuple-for-each([&]<class I>(I& i) { i -= iter_difference_t<I>(x); }, current_); return *this;
constexpr auto operator[](difference_type n) const requires all-random-access<Const, Views...>;
Effects: Equivalent to: return tuple-transform([&]<class I>(I& i) -> decltype(auto) { return i[iter_difference_t<I>(n)]; }, current_);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
Returns:
  • x.current_ == y.current_ if all-bidirectional<Const, Views...> is true.
  • Otherwise, true if there exists an integer such that bool(std​::​​get<i>(x.current_) == std​::​get<i>(y.current_)) is true.
    [Note 1: 
    This allows zip_view to model common_range when all constituent views model common_range.
    — end note]
  • Otherwise, false.
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires all-random-access<Const, Views...>;
Returns: x.current_ <=> y.current_.
friend constexpr iterator operator+(const iterator& i, difference_type n) requires all-random-access<Const, Views...>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires all-random-access<Const, Views...>;
Effects: Equivalent to: auto r = i; r += n; return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires all-random-access<Const, Views...>;
Effects: Equivalent to: auto r = i; r -= n; return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...);
Let DIST(i) be difference_type(std​::​get<i>(x.current_) - std​::​get<i>(y.current_)).
Returns: The value with the smallest absolute value among DIST(n) for all integers .
friend constexpr auto iter_move(const iterator& i) noexcept(see below);
Effects: Equivalent to: return tuple-transform(ranges::iter_move, i.current_);
Remarks: The exception specification is equivalent to: (noexcept(ranges::iter_move(declval<const iterator_t<maybe-const<Const, Views>>&>())) && ...) && (is_nothrow_move_constructible_v<range_rvalue_reference_t<maybe-const<Const, Views>>> && ...)
friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
Effects: For every integer , performs: ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
Remarks: The exception specification is equivalent to the logical and of the following expressions: noexcept(ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))) for every integer .

25.7.25.4 Class template zip_view​::​sentinel [range.zip.sentinel]

namespace std::ranges { template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) template<bool Const> class zip_view<Views...>::sentinel { tuple<sentinel_t<maybe-const<Const, Views>>...> end_; // exposition only constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> i) requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...); template<bool OtherConst> requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...> operator-(const sentinel& y, const iterator<OtherConst>& x); }; }
constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> i) requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...);
Effects: Initializes end_ with std​::​move(i.end_).
template<bool OtherConst> requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Returns: true if there exists an integer such that bool(std​::​get<i>(x.current_) == std​::​get<i>(y.end_)) is true.
Otherwise, false.
template<bool OtherConst> requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...> operator-(const iterator<OtherConst>& x, const sentinel& y);
Let D be the return type.
Let DIST(i) be D(std​::​get<i>(x.current_) - std​::​get<i>(y.end_)).
Returns: The value with the smallest absolute value among DIST(n) for all integers .
template<bool OtherConst> requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<OtherConst, Views>>> && ...) friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...> operator-(const sentinel& y, const iterator<OtherConst>& x);
Effects: Equivalent to: return -(x - y);

25.7.26 Zip transform view [range.zip.transform]

25.7.26.1 Overview [range.zip.transform.overview]

zip_transform_view takes an invocable object and any number of views and produces a view whose element is the result of applying the invocable object to the elements of all views.
The name views​::​zip_transform denotes a customization point object ([customization.point.object]).
Let F be a subexpression, and let Es... be a pack of subexpressions.
  • If Es is an empty pack, let FD be decay_t<decltype((F))>.
    • If move_constructible<FD> && regular_invocable<FD&> is false, or if decay_t<invoke_result_t<FD&>> is not an object type, views​::​zip_transform(F, Es...) is ill-formed.
    • Otherwise, the expression views​::​zip_transform(F, Es...) is expression-equivalent to ((void)F, auto(views::empty<decay_t<invoke_result_t<FD&>>>))
  • Otherwise, the expression views​::​zip_transform(F, Es...) is expression-equivalent to zip_transform_view(F, Es...).
[Example 1: vector v1 = {1, 2}; vector v2 = {4, 5, 6}; for (auto i : views::zip_transform(plus(), v1, v2)) { cout << i << ' '; // prints 5 7 } — end example]

25.7.26.2 Class template zip_transform_view [range.zip.transform.view]

namespace std::ranges { template<move_constructible F, input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> && regular_invocable<F&, range_reference_t<Views>...> && can-reference<invoke_result_t<F&, range_reference_t<Views>...>> class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> { movable-box<F> fun_; // exposition only zip_view<Views...> zip_; // exposition only using InnerView = zip_view<Views...>; // exposition only template<bool Const> using ziperator = iterator_t<maybe-const<Const, InnerView>>; // exposition only template<bool Const> using zentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only // [range.zip.transform.iterator], class template zip_transform_view​::​iterator template<bool> class iterator; // exposition only // [range.zip.transform.sentinel], class template zip_transform_view​::​sentinel template<bool> class sentinel; // exposition only public: zip_transform_view() = default; constexpr explicit zip_transform_view(F fun, Views... views); constexpr auto begin() { return iterator<false>(*this, zip_.begin()); } constexpr auto begin() const requires range<const InnerView> && regular_invocable<const F&, range_reference_t<const Views>...> { return iterator<true>(*this, zip_.begin()); } constexpr auto end() { if constexpr (common_range<InnerView>) { return iterator<false>(*this, zip_.end()); } else { return sentinel<false>(zip_.end()); } } constexpr auto end() const requires range<const InnerView> && regular_invocable<const F&, range_reference_t<const Views>...> { if constexpr (common_range<const InnerView>) { return iterator<true>(*this, zip_.end()); } else { return sentinel<true>(zip_.end()); } } constexpr auto size() requires sized_range<InnerView> { return zip_.size(); } constexpr auto size() const requires sized_range<const InnerView> { return zip_.size(); } }; template<class F, class... Rs> zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>; }
constexpr explicit zip_transform_view(F fun, Views... views);
Effects: Initializes fun_ with std​::​move(fun) and zip_ with std​::​move(views)....

25.7.26.3 Class template zip_transform_view​::​iterator [range.zip.transform.iterator]

namespace std::ranges { template<move_constructible F, input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> && regular_invocable<F&, range_reference_t<Views>...> && can-reference<invoke_result_t<F&, range_reference_t<Views>...>> template<bool Const> class zip_transform_view<F, Views...>::iterator { using Parent = maybe-const<Const, zip_transform_view>; // exposition only using Base = maybe-const<Const, InnerView>; // exposition only Parent* parent_ = nullptr; // exposition only ziperator<Const> inner_; // exposition only constexpr iterator(Parent& parent, ziperator<Const> inner); // exposition only public: using iterator_category = see below; // not always present using iterator_concept = typename ziperator<Const>::iterator_concept; using value_type = remove_cvref_t<invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...>>; using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<ziperator<false>, ziperator<Const>>; constexpr decltype(auto) operator*() const noexcept(see below); constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<ziperator<Const>>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>; }; }
The member typedef-name iterator​::​iterator_category is defined if and only if Base models forward_range.
In that case, iterator​::​iterator_category is defined as follows:
  • If invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...> is not a reference, iterator_category denotes input_iterator_tag.
  • Otherwise, let Cs denote the pack of types iterator_traits<iterator_t<maybe-const<Const, Views>>>​::​iterator_category....
    • If (derived_from<Cs, random_access_iterator_tag> && ...) is true, iterator_category denotes random_access_iterator_tag.
    • Otherwise, if (derived_from<Cs, bidirectional_iterator_tag> && ...) is true, iterator_category denotes bidirectional_iterator_tag.
    • Otherwise, if (derived_from<Cs, forward_iterator_tag> && ...) is true, iterator_category denotes forward_iterator_tag.
    • Otherwise, iterator_category denotes input_iterator_tag.
constexpr iterator(Parent& parent, ziperator<Const> inner);
Effects: Initializes parent_ with addressof(parent) and inner_ with std​::​move(inner).
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
Effects: Initializes parent_ with i.parent_ and inner_ with std​::​move(i.inner_).
constexpr decltype(auto) operator*() const noexcept(see below);
Effects: Equivalent to: return apply([&](const auto&... iters) -> decltype(auto) { return invoke(*parent_->fun_, *iters...); }, inner_.current_);
Remarks: Let Is be the pack 0, 1, …, (sizeof...(Views)-1).
The exception specification is equivalent to: noexcept(invoke(*parent_->fun_, *std​::​get<Is>(inner_.current_)...)).
constexpr iterator& operator++();
Effects: Equivalent to: ++inner_; return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++*this.
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --inner_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: inner_ += x; return *this;
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: inner_ -= x; return *this;
constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base>;
Effects: Equivalent to: return apply([&]<class... Is>(const Is&... iters) -> decltype(auto) { return invoke(*parent_->fun_, iters[iter_difference_t<Is>(n)]...); }, inner_.current_);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<ziperator<Const>>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Let op be the operator.
Effects: Equivalent to: return x.inner_ op y.inner_;
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: return iterator(*i.parent_, i.inner_ + n);
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: return iterator(*i.parent_, i.inner_ - n);
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
Effects: Equivalent to: return x.inner_ - y.inner_;

25.7.26.4 Class template zip_transform_view​::​sentinel [range.zip.transform.sentinel]

namespace std::ranges { template<move_constructible F, input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> && regular_invocable<F&, range_reference_t<Views>...> && can-reference<invoke_result_t<F&, range_reference_t<Views>...>> template<bool Const> class zip_transform_view<F, Views...>::sentinel { zentinel<Const> inner_; // exposition only constexpr explicit sentinel(zentinel<Const> inner); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<zentinel<false>, zentinel<Const>>; template<bool OtherConst> requires sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const sentinel& x, const iterator<OtherConst>& y); }; }
constexpr explicit sentinel(zentinel<Const> inner);
Effects: Initializes inner_ with inner.
constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
Effects: Initializes inner_ with std​::​move(i.inner_).
template<bool OtherConst> requires sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.inner_ == y.inner_;
template<bool OtherConst> requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const sentinel& x, const iterator<OtherConst>& y);
Effects: Equivalent to: return x.inner_ - y.inner_;

25.7.27 Adjacent view [range.adjacent]

25.7.27.1 Overview [range.adjacent.overview]

adjacent_view takes a view and produces a view whose element is a tuple of references to the through elements of the original view.
If the original view has fewer than N elements, the resulting view is empty.
The name views​::​adjacent<N> denotes a range adaptor object ([range.adaptor.object]).
Given a subexpression E and a constant expression N, the expression views​::​adjacent<N>(E) is expression-equivalent to
  • ((void)E, auto(views​::​empty<tuple<>>)) if N is equal to 0 and decltype((E)) models forward_range,
  • otherwise, adjacent_view<views​::​all_t<decltype((E))>, N>(E).
[Example 1: vector v = {1, 2, 3, 4}; for (auto i : v | views::adjacent<2>) { cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4) } — end example]
Define REPEAT(T, N) as a pack of N types, each of which denotes the same type as T.

25.7.27.2 Class template adjacent_view [range.adjacent.view]

namespace std::ranges { template<forward_range V, size_t N> requires view<V> && (N > 0) class adjacent_view : public view_interface<adjacent_view<V, N>> { V base_ = V(); // exposition only // [range.adjacent.iterator], class template adjacent_view​::​iterator template<bool> class iterator; // exposition only // [range.adjacent.sentinel], class template adjacent_view​::​sentinel template<bool> class sentinel; // exposition only struct as-sentinel{}; // exposition only public: adjacent_view() requires default_initializable<V> = default; constexpr explicit adjacent_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(ranges::begin(base_), ranges::end(base_)); } constexpr auto begin() const requires range<const V> { return iterator<true>(ranges::begin(base_), ranges::end(base_)); } constexpr auto end() requires (!simple-view<V>) { if constexpr (common_range<V>) { return iterator<false>(as-sentinel{}, ranges::begin(base_), ranges::end(base_)); } else { return sentinel<false>(ranges::end(base_)); } } constexpr auto end() const requires range<const V> { if constexpr (common_range<const V>) { return iterator<true>(as-sentinel{}, ranges::begin(base_), ranges::end(base_)); } else { return sentinel<true>(ranges::end(base_)); } } constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; }
constexpr explicit adjacent_view(V base);
Effects: Initializes base_ with std​::​move(base).
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: using ST = decltype(ranges::size(base_)); using CT = common_type_t<ST, size_t>; auto sz = static_cast<CT>(ranges::size(base_)); sz -= std::min<CT>(sz, N - 1); return static_cast<ST>(sz);

25.7.27.3 Class template adjacent_view​::​iterator [range.adjacent.iterator]

namespace std::ranges { template<forward_range V, size_t N> requires view<V> && (N > 0) template<bool Const> class adjacent_view<V, N>::iterator { using Base = maybe-const<Const, V>; // exposition only array<iterator_t<Base>, N> current_ = array<iterator_t<Base>, N>(); // exposition only constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last); // exposition only constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last); // exposition only public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using value_type = tuple<REPEAT(range_value_t<Base>, N)...>; using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr auto operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr auto operator[](difference_type n) const requires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; friend constexpr auto iter_move(const iterator& i) noexcept(see below); friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires indirectly_swappable<iterator_t<Base>>; }; }
iterator​::​iterator_concept is defined as follows:
If the invocation of any non-const member function of iterator exits via an exception, the iterator acquires a singular value.
constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);
Postconditions: current_[0] == first is true, and for every integer , current_[i] == ranges​::​next(current_[i-1], 1, last) is true.
constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
Postconditions: If Base does not model bidirectional_range, each element of current_ is equal to last.
Otherwise, current_[N-1] == last is true, and for every integer , current_[i] == ranges​::​prev(current_[i+1], 1, first) is true.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes each element of current_ with the corresponding element of i.current_ as an xvalue.
constexpr auto operator*() const;
Effects: Equivalent to: return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
constexpr iterator& operator++();
Preconditions: current_.back() is incrementable.
Postconditions: Each element of current_ is equal to ranges​::​next(i), where i is the value of that element before the call.
Returns: *this.
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Preconditions: current_.front() is decrementable.
Postconditions: Each element of current_ is equal to ranges​::​prev(i), where i is the value of that element before the call.
Returns: *this.
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
Preconditions: current_.back() + x has well-defined behavior.
Postconditions: Each element of current_ is equal to i + x, where i is the value of that element before the call.
Returns: *this.
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Preconditions: current_.front() - x has well-defined behavior.
Postconditions: Each element of current_ is equal to i - x, where i is the value of that element before the call.
Returns: *this.
constexpr auto operator[](difference_type n) const requires random_access_range<Base>;
Effects: Equivalent to: return tuple-transform([&](auto& i) -> decltype(auto) { return i[n]; }, current_);
friend constexpr bool operator==(const iterator& x, const iterator& y);
Returns: x.current_.back() == y.current_.back().
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Returns: x.current_.back() < y.current_.back().
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Returns: x.current_.back() <=> y.current_.back().
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r += n; return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r -= n; return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return x.current_.back() - y.current_.back();
friend constexpr auto iter_move(const iterator& i) noexcept(see below);
Effects: Equivalent to: return tuple-transform(ranges​::​iter_move, i.current_);
Remarks: The exception specification is equivalent to: noexcept(ranges::iter_move(declval<const iterator_t<Base>&>())) && is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>
friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires indirectly_swappable<iterator_t<Base>>;
Preconditions: None of the iterators in l.current_ is equal to an iterator in r.current_.
Effects: For every integer , performs ranges​::​iter_swap(l.current_[i], r.current_[i]).
Remarks: The exception specification is equivalent to: noexcept(ranges::iter_swap(declval<iterator_t<Base>>(), declval<iterator_t<Base>>()))

25.7.27.4 Class template adjacent_view​::​sentinel [range.adjacent.sentinel]

namespace std::ranges { template<forward_range V, size_t N> requires view<V> && (N > 0) template<bool Const> class adjacent_view<V, N>::sentinel { using Base = maybe-const<Const, V>; // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only constexpr explicit sentinel(sentinel_t<Base> end); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& y, const iterator<OtherConst>& x); }; }
constexpr explicit sentinel(sentinel_t<Base> end);
Effects: Initializes end_ with end.
constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_ with std​::​move(i.end_).
template<bool OtherConst> requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_.back() == y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.current_.back() - y.end_;
template<bool OtherConst> requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> friend constexpr range_difference_t<maybe-const<OtherConst, V>> operator-(const sentinel& y, const iterator<OtherConst>& x);
Effects: Equivalent to: return y.end_ - x.current_.back();

25.7.28 Adjacent transform view [range.adjacent.transform]

25.7.28.1 Overview [range.adjacent.transform.overview]

adjacent_transform_view takes an invocable object and a view and produces a view whose element is the result of applying the invocable object to the through elements of the original view.
If the original view has fewer than N elements, the resulting view is empty.
The name views​::​adjacent_transform<N> denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F and a constant expression N:
  • If N is equal to 0 and decltype((E)) models forward_range, views​::​adjacent_transform<N>(E, F) is expression-equivalent to ((void)E, views​::​zip_transform(F)), except that the evaluations of E and F are indeterminately sequenced.
  • Otherwise, the expression views​::​adjacent_transform<N>(E, F) is expression-equivalent to adjacent_transform_view<views​::​all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F).
[Example 1: vector v = {1, 2, 3, 4}; for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { cout << i << ' '; // prints 2 6 12 } — end example]

25.7.28.2 Class template adjacent_transform_view [range.adjacent.transform.view]

namespace std::ranges { template<forward_range V, move_constructible F, size_t N> requires view<V> && (N > 0) && is_object_v<F> && regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> && can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>> class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> { movable-box<F> fun_; // exposition only adjacent_view<V, N> inner_; // exposition only using InnerView = adjacent_view<V, N>; // exposition only template<bool Const> using inner-iterator = iterator_t<maybe-const<Const, InnerView>>; // exposition only template<bool Const> using inner-sentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only // [range.adjacent.transform.iterator], class template adjacent_transform_view​::​iterator template<bool> class iterator; // exposition only // [range.adjacent.transform.sentinel], class template adjacent_transform_view​::​sentinel template<bool> class sentinel; // exposition only public: adjacent_transform_view() = default; constexpr explicit adjacent_transform_view(V base, F fun); constexpr V base() const & requires copy_constructible<V> { return inner_.base(); } constexpr V base() && { return std::move(inner_).base(); } constexpr auto begin() { return iterator<false>(*this, inner_.begin()); } constexpr auto begin() const requires range<const InnerView> && regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> { return iterator<true>(*this, inner_.begin()); } constexpr auto end() { if constexpr (common_range<InnerView>) { return iterator<false>(*this, inner_.end()); } else { return sentinel<false>(inner_.end()); } } constexpr auto end() const requires range<const InnerView> && regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> { if constexpr (common_range<const InnerView>) { return iterator<true>(*this, inner_.end()); } else { return sentinel<true>(inner_.end()); } } constexpr auto size() requires sized_range<InnerView> { return inner_.size(); } constexpr auto size() const requires sized_range<const InnerView> { return inner_.size(); } }; }
constexpr explicit adjacent_transform_view(V base, F fun);
Effects: Initializes fun_ with std​::​move(fun) and inner_ with std​::​move(base).

25.7.28.3 Class template adjacent_transform_view​::​iterator [range.adjacent.transform.iterator]

namespace std::ranges { template<forward_range V, move_constructible F, size_t N> requires view<V> && (N > 0) && is_object_v<F> && regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> && can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>> template<bool Const> class adjacent_transform_view<V, F, N>::iterator { using Parent = maybe-const<Const, adjacent_transform_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only Parent* parent_ = nullptr; // exposition only inner-iterator<Const> inner_; // exposition only constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only public: using iterator_category = see below; using iterator_concept = typename inner-iterator<Const>::iterator_concept; using value_type = remove_cvref_t<invoke_result_t<maybe-const<Const, F>&, REPEAT(range_reference_t<Base>, N)...>>; using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>; constexpr decltype(auto) operator*() const noexcept(see below); constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>; }; }
The member typedef-name iterator​::​iterator_category is defined as follows:
  • If invoke_result_t<maybe-const<Const, F>&, REPEAT(range_reference_t<Base>, N)...> is not a reference, iterator_category denotes input_iterator_tag.
  • Otherwise, let C denote the type iterator_traits<iterator_t<Base>>​::​iterator_category.
    • If derived_from<C, random_access_iterator_tag> is true, iterator_category denotes random_access_iterator_tag.
    • Otherwise, if derived_from<C, bidirectional_iterator_tag> is true, iterator_category denotes bidirectional_iterator_tag.
    • Otherwise, if derived_from<C, forward_iterator_tag> is true, iterator_category denotes forward_iterator_tag.
    • Otherwise, iterator_category denotes input_iterator_tag.
constexpr iterator(Parent& parent, inner-iterator<Const> inner);
Effects: Initializes parent_ with addressof(parent) and inner_ with std​::​move(inner).
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
Effects: Initializes parent_ with i.parent_ and inner_ with std​::​move(i.inner_).
constexpr decltype(auto) operator*() const noexcept(see below);
Effects: Equivalent to: return apply([&](const auto&... iters) -> decltype(auto) { return invoke(*parent_->fun_, *iters...); }, inner_.current_);
Remarks: Let Is be the pack 0, 1, …, (N-1).
The exception specification is equivalent to: noexcept(invoke(*parent_->fun_, *std::get<Is>(inner_.current_)...))
constexpr iterator& operator++();
Effects: Equivalent to: ++inner_; return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: --inner_; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: inner_ += x; return *this;
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: inner_ -= x; return *this;
constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base>;
Effects: Equivalent to: return apply([&](const auto&... iters) -> decltype(auto) { return invoke(*parent_->fun_, iters[n]...); }, inner_.current_);
friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
Let op be the operator.
Effects: Equivalent to: return x.inner_ op y.inner_;
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: return iterator(*i.parent_, i.inner_ + n);
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: return iterator(*i.parent_, i.inner_ - n);
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
Effects: Equivalent to: return x.inner_ - y.inner_;

25.7.28.4 Class template adjacent_transform_view​::​sentinel [range.adjacent.transform.sentinel]

namespace std::ranges { template<forward_range V, move_constructible F, size_t N> requires view<V> && (N > 0) && is_object_v<F> && regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> && can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>> template<bool Const> class adjacent_transform_view<V, F, N>::sentinel { inner-sentinel<Const> inner_; // exposition only constexpr explicit sentinel(inner-sentinel<Const> inner); // exposition only public: sentinel() = default; constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>; template<bool OtherConst> requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const sentinel& x, const iterator<OtherConst>& y); }; }
constexpr explicit sentinel(inner-sentinel<Const> inner);
Effects: Initializes inner_ with inner.
constexpr sentinel(sentinel<!Const> i) requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
Effects: Initializes inner_ with std​::​move(i.inner_).
template<bool OtherConst> requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
Effects: Equivalent to: return x.inner_ == y.inner_;
template<bool OtherConst> requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const iterator<OtherConst>& x, const sentinel& y); template<bool OtherConst> requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>> friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>> operator-(const sentinel& x, const iterator<OtherConst>& y);
Effects: Equivalent to: return x.inner_ - y.inner_;

25.7.29 Chunk view [range.chunk]

25.7.29.1 Overview [range.chunk.overview]

chunk_view takes a view and a number N and produces a range of views that are N-sized non-overlapping successive chunks of the elements of the original view, in order.
The last view in the range can have fewer than N elements.
The name views​::​chunk denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and N, the expression views​::​chunk(E, N) is expression-equivalent to chunk_view(E, N).
[Example 1: vector v = {1, 2, 3, 4, 5}; for (auto r : v | views::chunk(2)) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] "; } // The above prints [1, 2] [3, 4] [5] — end example]

25.7.29.2 Class template chunk_view for input ranges [range.chunk.view.input]

namespace std::ranges { template<class I> constexpr I div-ceil(I num, I denom) { // exposition only I r = num / denom; if (num % denom) ++r; return r; } template<view V> requires input_range<V> class chunk_view : public view_interface<chunk_view<V>> { V base_; // exposition only range_difference_t<V> n_; // exposition only range_difference_t<V> remainder_ = 0; // exposition only non-propagating-cache<iterator_t<V>> current_; // exposition only // [range.chunk.outer.iter], class chunk_view​::​outer-iterator class outer-iterator; // exposition only // [range.chunk.inner.iter], class chunk_view​::​inner-iterator class inner-iterator; // exposition only public: constexpr explicit chunk_view(V base, range_difference_t<V> n); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr outer-iterator begin(); constexpr default_sentinel_t end() const noexcept; constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; template<class R> chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>; }
constexpr explicit chunk_view(V base, range_difference_t<V> n);
Preconditions: n > 0 is true.
Effects: Initializes base_ with std​::​move(base) and n_ with n.
constexpr outer-iterator begin();
Effects: Equivalent to: current_ = ranges::begin(base_); remainder_ = n_; return outer-iterator(*this);
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: return to-unsigned-like(div-ceil(ranges::distance(base_), n_));

25.7.29.3 Class chunk_view​::​outer-iterator [range.chunk.outer.iter]

namespace std::ranges { template<view V> requires input_range<V> class chunk_view<V>::outer-iterator { chunk_view* parent_; // exposition only constexpr explicit outer-iterator(chunk_view& parent); // exposition only public: using iterator_concept = input_iterator_tag; using difference_type = range_difference_t<V>; // [range.chunk.outer.value], class chunk_view​::​outer-iterator​::​value_type struct value_type; outer-iterator(outer-iterator&&) = default; outer-iterator& operator=(outer-iterator&&) = default; constexpr value_type operator*() const; constexpr outer-iterator& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; }; }
constexpr explicit outer-iterator(chunk_view& parent);
Effects: Initializes parent_ with addressof(parent).
constexpr value_type operator*() const;
Preconditions: *this == default_sentinel is false.
Returns: value_type(*parent_).
constexpr outer-iterator& operator++();
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to: ranges::advance(*parent_->current_, parent_->remainder_, ranges::end(parent_->base_)); parent_->remainder_ = parent_->n_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
Effects: Equivalent to: return *x.parent_->current_ == ranges::end(x.parent_->base_) && x.parent_->remainder_ != 0;
friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: const auto dist = ranges::end(x.parent_->base_) - *x.parent_->current_; if (dist < x.parent_->remainder_) { return dist == 0 ? 0 : 1; } return div-ceil(dist - x.parent_->remainder_, x.parent_->n_) + 1;
friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return -(y - x);

25.7.29.4 Class chunk_view​::​outer-iterator​::​value_type [range.chunk.outer.value]

namespace std::ranges { template<view V> requires input_range<V> struct chunk_view<V>::outer-iterator::value_type : view_interface<value_type> { private: chunk_view* parent_; // exposition only constexpr explicit value_type(chunk_view& parent); // exposition only public: constexpr inner-iterator begin() const noexcept; constexpr default_sentinel_t end() const noexcept; constexpr auto size() const requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; }; }
constexpr explicit value_type(chunk_view& parent);
Effects: Initializes parent_ with addressof(parent).
constexpr inner-iterator begin() const noexcept;
Returns: inner-iterator(*parent_).
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr auto size() const requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return to-unsigned-like(ranges::min(parent_->remainder_, ranges::end(parent_->base_) - *parent_->current_));

25.7.29.5 Class chunk_view​::​inner-iterator [range.chunk.inner.iter]

namespace std::ranges { template<view V> requires input_range<V> class chunk_view<V>::inner-iterator { chunk_view* parent_; // exposition only constexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition only public: using iterator_concept = input_iterator_tag; using difference_type = range_difference_t<V>; using value_type = range_value_t<V>; inner-iterator(inner-iterator&&) = default; inner-iterator& operator=(inner-iterator&&) = default; constexpr const iterator_t<V>& base() const &; constexpr range_reference_t<V> operator*() const; constexpr inner-iterator& operator++(); constexpr void operator++(int); friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t); friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_))); friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires indirectly_swappable<iterator_t<V>>; }; }
constexpr explicit inner-iterator(chunk_view& parent) noexcept;
Effects: Initializes parent_ with addressof(parent).
constexpr const iterator_t<V>& base() const &;
Effects: Equivalent to: return *parent_->current_;
constexpr range_reference_t<V> operator*() const;
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to: return **parent_->current_;
constexpr inner-iterator& operator++();
Preconditions: *this == default_sentinel is false.
Effects: Equivalent to: ++*parent_->current_; if (*parent_->current_ == ranges::end(parent_->base_)) parent_->remainder_ = 0; else --parent_->remainder_; return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
Returns: x.parent_->remainder_ == 0.
friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return ranges::min(x.parent_->remainder_, ranges::end(x.parent_->base_) - *x.parent_->current_);
friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Effects: Equivalent to: return -(y - x);
friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i) noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
Effects: Equivalent to: return ranges​::​iter_move(*i.parent_->current_);
friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y) noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_))) requires indirectly_swappable<iterator_t<V>>;
Effects: Equivalent to: ranges​::​iter_swap(*x.parent_->current_, *y.parent_->current_);

25.7.29.6 Class template chunk_view for forward ranges [range.chunk.view.fwd]

namespace std::ranges { template<view V> requires forward_range<V> class chunk_view<V> : public view_interface<chunk_view<V>> { V base_; // exposition only range_difference_t<V> n_; // exposition only // [range.chunk.fwd.iter], class template chunk_view​::​iterator template<bool> class iterator; // exposition only public: constexpr explicit chunk_view(V base, range_difference_t<V> n); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(this, ranges::begin(base_)); } constexpr auto begin() const requires forward_range<const V> { return iterator<true>(this, ranges::begin(base_)); } constexpr auto end() requires (!simple-view<V>) { if constexpr (common_range<V> && sized_range<V>) { auto missing = (n_ - ranges::distance(base_) % n_) % n_; return iterator<false>(this, ranges::end(base_), missing); } else if constexpr (common_range<V> && !bidirectional_range<V>) { return iterator<false>(this, ranges::end(base_)); } else { return default_sentinel; } } constexpr auto end() const requires forward_range<const V> { if constexpr (common_range<const V> && sized_range<const V>) { auto missing = (n_ - ranges::distance(base_) % n_) % n_; return iterator<true>(this, ranges::end(base_), missing); } else if constexpr (common_range<const V> && !bidirectional_range<const V>) { return iterator<true>(this, ranges::end(base_)); } else { return default_sentinel; } } constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; }
constexpr explicit chunk_view(V base, range_difference_t<V> n);
Preconditions: n > 0 is true.
Effects: Initializes base_ with std​::​move(base) and n_ with n.
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: return to-unsigned-like(div-ceil(ranges::distance(base_), n_));

25.7.29.7 Class template chunk_view​::​iterator for forward ranges [range.chunk.fwd.iter]

namespace std::ranges { template<view V> requires forward_range<V> template<bool Const> class chunk_view<V>::iterator { using Parent = maybe-const<Const, chunk_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only range_difference_t<Base> n_ = 0; // exposition only range_difference_t<Base> missing_ = 0; // exposition only constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only range_difference_t<Base> missing = 0); public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using value_type = decltype(views::take(subrange(current_, end_), n_)); using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>> && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr iterator_t<Base> base() const; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr value_type operator[](difference_type n) const requires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator==(const iterator& x, default_sentinel_t); friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; }; }
iterator​::​iterator_concept is defined as follows:
constexpr iterator(Parent* parent, iterator_t<Base> current, range_difference_t<Base> missing = 0);
Effects: Initializes current_ with current, end_ with ranges​::​end(parent->base_), n_ with parent->n_, and missing_ with missing.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>> && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_), end_ with std​::​move(i.end_), n_ with i.n_, and missing_ with i.missing_.
constexpr iterator_t<Base> base() const;
Returns: current_.
constexpr value_type operator*() const;
Preconditions: current_ != end_ is true.
Returns: views​::​take(subrange(current_, end_), n_).
constexpr iterator& operator++();
Preconditions: current_ != end_ is true.
Effects: Equivalent to: missing_ = ranges::advance(current_, n_, end_); return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: ranges::advance(current_, missing_ - n_); missing_ = 0; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
Preconditions: If x is positive, ranges​::​distance(current_, end_) > n_ * (x - 1) is true.
[Note 1: 
If x is negative, the Effects paragraph implies a precondition.
— end note]
Effects: Equivalent to: if (x > 0) { ranges::advance(current_, n_ * (x - 1)); missing_ = ranges::advance(current_, n_, end_); } else if (x < 0) { ranges::advance(current_, n_ * x + missing_); missing_ = 0; } return *this;
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: return *this += -x;
constexpr value_type operator[](difference_type n) const requires random_access_range<Base>;
Returns: *(*this + n).
friend constexpr bool operator==(const iterator& x, const iterator& y);
Returns: x.current_ == y.current_.
friend constexpr bool operator==(const iterator& x, default_sentinel_t);
Returns: x.current_ == x.end_.
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Returns: x.current_ < y.current_.
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Returns: x.current_ <=> y.current_.
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r += n; return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r -= n; return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Returns: (x.current_ - y.current_ + x.missing_ - y.missing_) / x.n_.
friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
Returns: div-ceil(x.end_ - x.current_, x.n_).
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return -(y - x);

25.7.30 Slide view [range.slide]

25.7.30.1 Overview [range.slide.overview]

slide_view takes a view and a number N and produces a view whose element is a view over the through elements of the original view.
If the original view has fewer than N elements, the resulting view is empty.
The name views​::​slide denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and N, the expression views​::​slide(E, N) is expression-equivalent to slide_view(E, N).
[Example 1: vector v = {1, 2, 3, 4}; for (auto i : v | views::slide(2)) { cout << '[' << i[0] << ", " << i[1] << "] "; // prints [1, 2] [2, 3] [3, 4] } — end example]

25.7.30.2 Class template slide_view [range.slide.view]

namespace std::ranges { template<class V> concept slide-caches-nothing = random_access_range<V> && sized_range<V>; // exposition only template<class V> concept slide-caches-last = // exposition only !slide-caches-nothing<V> && bidirectional_range<V> && common_range<V>; template<class V> concept slide-caches-first = // exposition only !slide-caches-nothing<V> && !slide-caches-last<V>; template<forward_range V> requires view<V> class slide_view : public view_interface<slide_view<V>> { V base_; // exposition only range_difference_t<V> n_; // exposition only // [range.slide.iterator], class template slide_view​::​iterator template<bool> class iterator; // exposition only // [range.slide.sentinel], class slide_view​::​sentinel class sentinel; // exposition only public: constexpr explicit slide_view(V base, range_difference_t<V> n); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin() requires (!(simple-view<V> && slide-caches-nothing<const V>)); constexpr auto begin() const requires slide-caches-nothing<const V>; constexpr auto end() requires (!(simple-view<V> && slide-caches-nothing<const V>)); constexpr auto end() const requires slide-caches-nothing<const V>; constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; template<class R> slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>; }
constexpr explicit slide_view(V base, range_difference_t<V> n);
Preconditions: n > 0 is true.
Effects: Initializes base_ with std​::​move(base) and n_ with n.
constexpr auto begin() requires (!(simple-view<V> && slide-caches-nothing<const V>));
Returns:
  • If V models slide-caches-first, iterator<false>(ranges::begin(base_), ranges::next(ranges::begin(base_), n_ - 1, ranges::end(base_)), n_)
  • Otherwise, iterator<false>(ranges​::​begin(base_), n_).
Remarks: In order to provide the amortized constant-time complexity required by the range concept, this function caches the result within the slide_view for use on subsequent calls when V models slide-caches-first.
constexpr auto begin() const requires slide-caches-nothing<const V>;
Returns: iterator<true>(ranges​::​begin(base_), n_).
constexpr auto end() requires (!(simple-view<V> && slide-caches-nothing<const V>));
Returns:
  • If V models slide-caches-nothing, iterator<false>(ranges::begin(base_) + range_difference_t<V>(size()), n_)
  • Otherwise, if V models slide-caches-last, iterator<false>(ranges::prev(ranges::end(base_), n_ - 1, ranges::begin(base_)), n_)
  • Otherwise, if V models common_range, iterator<false>(ranges::end(base_), ranges::end(base_), n_)
  • Otherwise, sentinel(ranges​::​end(base_)).
Remarks: In order to provide the amortized constant-time complexity required by the range concept, this function caches the result within the slide_view for use on subsequent calls when V models slide-caches-last.
constexpr auto end() const requires slide-caches-nothing<const V>;
Returns: begin() + range_difference_t<const V>(size()).
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: auto sz = ranges::distance(base_) - n_ + 1; if (sz < 0) sz = 0; return to-unsigned-like(sz);

25.7.30.3 Class template slide_view​::​iterator [range.slide.iterator]

namespace std::ranges { template<forward_range V> requires view<V> template<bool Const> class slide_view<V>::iterator { using Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only iterator_t<Base> last_ele_ = iterator_t<Base>(); // exposition only, // present only if Base models slide-caches-first range_difference_t<Base> n_ = 0; // exposition only constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n) // exposition only requires (!slide-caches-first<Base>); constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele, // exposition only range_difference_t<Base> n) requires slide-caches-first<Base>; public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using value_type = decltype(views::counted(current_, n_)); using difference_type = range_difference_t<Base>; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>; constexpr auto operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>; constexpr auto operator[](difference_type n) const requires random_access_range<Base>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; }; }
iterator​::​iterator_concept is defined as follows:
If the invocation of any non-const member function of iterator exits via an exception, the iterator acquires a singular value.
constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n) requires (!slide-caches-first<Base>);
Effects: Initializes current_ with current and n_ with n.
constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele, range_difference_t<Base> n) requires slide-caches-first<Base>;
Effects: Initializes current_ with current, last_ele_ with last_ele, and n_ with n.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_) and n_ with i.n_.
[Note 1: 
iterator<true> can only be formed when Base models slide-caches-nothing, in which case last_ele_ is not present.
— end note]
constexpr auto operator*() const;
Returns: views​::​counted(current_, n_).
constexpr iterator& operator++();
Preconditions: current_ and last_ele_ (if present) are incrementable.
Postconditions: current_ and last_ele_ (if present) are each equal to ranges​::​next(i), where i is the value of that data member before the call.
Returns: *this.
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Preconditions: current_ and last_ele_ (if present) are decrementable.
Postconditions: current_ and last_ele_ (if present) are each equal to ranges​::​prev(i), where i is the value of that data member before the call.
Returns: *this.
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
Preconditions: current_ + x and last_ele_ + x (if last_ele_ is present) have well-defined behavior.
Postconditions: current_ and last_ele_ (if present) are each equal to i + x, where i is the value of that data member before the call.
Returns: *this.
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Preconditions: current_ - x and last_ele_ - x (if last_ele_ is present) have well-defined behavior.
Postconditions: current_ and last_ele_ (if present) are each equal to i - x, where i is the value of that data member before the call.
Returns: *this.
constexpr auto operator[](difference_type n) const requires random_access_range<Base>;
Effects: Equivalent to: return views​::​counted(current_ + n, n_);
friend constexpr bool operator==(const iterator& x, const iterator& y);
Returns: If last_ele_ is present, x.last_ele_ == y.last_ele_; otherwise, x.current_ == y.current_.
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Returns: x.current_ < y.current_.
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Returns: x.current_ <=> y.current_.
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r += n; return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r -= n; return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Returns: If last_ele_ is present, x.last_ele_ - y.last_ele_; otherwise, x.current_ - y.current_.

25.7.30.4 Class slide_view​::​sentinel [range.slide.sentinel]

namespace std::ranges { template<forward_range V> requires view<V> class slide_view<V>::sentinel { sentinel_t<V> end_ = sentinel_t<V>(); // exposition only constexpr explicit sentinel(sentinel_t<V> end); // exposition only public: sentinel() = default; friend constexpr bool operator==(const iterator<false>& x, const sentinel& y); friend constexpr range_difference_t<V> operator-(const iterator<false>& x, const sentinel& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr range_difference_t<V> operator-(const sentinel& y, const iterator<false>& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; }; }
[Note 1: 
sentinel is used only when slide-caches-first<V> is true.
— end note]
constexpr explicit sentinel(sentinel_t<V> end);
Effects: Initializes end_ with end.
friend constexpr bool operator==(const iterator<false>& x, const sentinel& y);
Returns: x.last_ele_ == y.end_.
friend constexpr range_difference_t<V> operator-(const iterator<false>& x, const sentinel& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Returns: x.last_ele_ - y.end_.
friend constexpr range_difference_t<V> operator-(const sentinel& y, const iterator<false>& x) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Returns: y.end_ - x.last_ele_.

25.7.31 Chunk by view [range.chunk.by]

25.7.31.1 Overview [range.chunk.by.overview]

chunk_by_view takes a view and a predicate, and splits the view into subranges between each pair of adjacent elements for which the predicate returns false.
The name views​::​chunk_by denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and F, the expression views​::​chunk_by(E, F) is expression-equivalent to chunk_by_view(E, F).
[Example 1: vector v = {1, 2, 2, 3, 0, 4, 5, 2}; for (auto r : v | views::chunk_by(ranges::less_equal{})) { cout << '['; auto sep = ""; for (auto i : r) { cout << sep << i; sep = ", "; } cout << "] "; } // The above prints [1, 2, 2, 3] [0, 4, 5] [2] — end example]

25.7.31.2 Class template chunk_by_view [range.chunk.by.view]

namespace std::ranges { template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> { V base_ = V(); // exposition only movable-box<Pred> pred_; // exposition only // [range.chunk.by.iter], class chunk_by_view​::​iterator class iterator; // exposition only public: chunk_by_view() requires default_initializable<V> && default_initializable<Pred> = default; constexpr explicit chunk_by_view(V base, Pred pred); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const; constexpr iterator begin(); constexpr auto end(); constexpr iterator_t<V> find-next(iterator_t<V>); // exposition only constexpr iterator_t<V> find-prev(iterator_t<V>) // exposition only requires bidirectional_range<V>; }; template<class R, class Pred> chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>; }
constexpr explicit chunk_by_view(V base, Pred pred);
Effects: Initializes base_ with std​::​move(base) and pred_ with std​::​move(pred).
constexpr const Pred& pred() const;
Effects: Equivalent to: return *pred_;
constexpr iterator begin();
Preconditions: pred_.has_value() is true.
Returns: iterator(*this, ranges​::​begin(base_), find-next(ranges​::​begin(base_))).
Remarks: In order to provide the amortized constant-time complexity required by the range concept, this function caches the result within the chunk_by_view for use on subsequent calls.
constexpr auto end();
Effects: Equivalent to: if constexpr (common_range<V>) { return iterator(*this, ranges::end(base_), ranges::end(base_)); } else { return default_sentinel; }
constexpr iterator_t<V> find-next(iterator_t<V> current);
Preconditions: pred_.has_value() is true.
Returns: ranges::next(ranges::adjacent_find(current, ranges::end(base_), not_fn(ref(*pred_))), 1, ranges::end(base_))
constexpr iterator_t<V> find-prev(iterator_t<V> current) requires bidirectional_range<V>;
Preconditions:
  • current is not equal to ranges​::​begin(base_).
  • pred_.has_value() is true.
Returns: An iterator i in the range [ranges​::​begin(base_), current) such that:
  • ranges​::​adjacent_find(i, current, not_fn(ref(*pred_))) is equal to current; and
  • if i is not equal to ranges​::​begin(base_), then bool(invoke(*pred_, *ranges​::​prev(i), *i)) is false.

25.7.31.3 Class chunk_by_view​::​iterator [range.chunk.by.iter]

namespace std::ranges { template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class chunk_by_view<V, Pred>::iterator { chunk_by_view* parent_ = nullptr; // exposition only iterator_t<V> current_ = iterator_t<V>(); // exposition only iterator_t<V> next_ = iterator_t<V>(); // exposition only constexpr iterator(chunk_by_view& parent, iterator_t<V> current, // exposition only iterator_t<V> next); public: using value_type = subrange<iterator_t<V>>; using difference_type = range_difference_t<V>; using iterator_category = input_iterator_tag; using iterator_concept = see below; iterator() = default; constexpr value_type operator*() const; constexpr iterator& operator++(); constexpr iterator operator++(int); constexpr iterator& operator--() requires bidirectional_range<V>; constexpr iterator operator--(int) requires bidirectional_range<V>; friend constexpr bool operator==(const iterator& x, const iterator& y); friend constexpr bool operator==(const iterator& x, default_sentinel_t); }; }
iterator​::​iterator_concept is defined as follows:
  • If V models bidirectional_range, then iterator_concept denotes bidirectional_iterator_tag.
  • Otherwise, iterator_concept denotes forward_iterator_tag.
constexpr iterator(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next);
Effects: Initializes parent_ with addressof(parent), current_ with current, and next_ with next.
constexpr value_type operator*() const;
Preconditions: current_ is not equal to next_.
Returns: subrange(current_, next_).
constexpr iterator& operator++();
Preconditions: current_ is not equal to next_.
Effects: Equivalent to: current_ = next_; next_ = parent_->find-next(current_); return *this;
constexpr iterator operator++(int);
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<V>;
Effects: Equivalent to: next_ = current_; current_ = parent_->find-prev(next_); return *this;
constexpr iterator operator--(int) requires bidirectional_range<V>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y);
Returns: x.current_ == y.current_.
friend constexpr bool operator==(const iterator& x, default_sentinel_t);
Returns: x.current_ == x.next_.

25.7.32 Stride view [range.stride]

25.7.32.1 Overview [range.stride.overview]

stride_view presents a view of an underlying sequence, advancing over n elements at a time, as opposed to the usual single-step succession.
The name views​::​stride denotes a range adaptor object ([range.adaptor.object]).
Given subexpressions E and N, the expression views​::​stride(E, N) is expression-equivalent to stride_view(E, N).
[Example 1: auto input = views::iota(0, 12) | views::stride(3); ranges::copy(input, ostream_iterator<int>(cout, " ")); // prints 0 3 6 9 ranges::copy(input | views::reverse, ostream_iterator<int>(cout, " ")); // prints 9 6 3 0 — end example]

25.7.32.2 Class template stride_view [range.stride.view]

namespace std::ranges { template<input_range V> requires view<V> class stride_view : public view_interface<stride_view<V>> { V base_; // exposition only range_difference_t<V> stride_; // exposition only // [range.stride.iterator], class template stride_view​::​iterator template<bool> class iterator; // exposition only public: constexpr explicit stride_view(V base, range_difference_t<V> stride); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr range_difference_t<V> stride() const noexcept; constexpr auto begin() requires (!simple-view<V>) { return iterator<false>(this, ranges::begin(base_)); } constexpr auto begin() const requires range<const V> { return iterator<true>(this, ranges::begin(base_)); } constexpr auto end() requires (!simple-view<V>) { if constexpr (common_range<V> && sized_range<V> && forward_range<V>) { auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_; return iterator<false>(this, ranges::end(base_), missing); } else if constexpr (common_range<V> && !bidirectional_range<V>) { return iterator<false>(this, ranges::end(base_)); } else { return default_sentinel; } } constexpr auto end() const requires range<const V> { if constexpr (common_range<const V> && sized_range<const V> && forward_range<const V>) { auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_; return iterator<true>(this, ranges::end(base_), missing); } else if constexpr (common_range<const V> && !bidirectional_range<const V>) { return iterator<true>(this, ranges::end(base_)); } else { return default_sentinel; } } constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; template<class R> stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>; }
constexpr stride_view(V base, range_difference_t<V> stride);
Preconditions: stride > 0 is true.
Effects: Initializes base_ with std​::​move(base) and stride_ with stride.
constexpr range_difference_t<V> stride() const noexcept;
Returns: stride_.
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));

25.7.32.3 Class template stride_view​::​iterator [range.stride.iterator]

namespace std::ranges { template<input_range V> requires view<V> template<bool Const> class stride_view<V>::iterator { using Parent = maybe-const<Const, stride_view>; // exposition only using Base = maybe-const<Const, V>; // exposition only iterator_t<Base> current_ = iterator_t<Base>(); // exposition only sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only range_difference_t<Base> stride_ = 0; // exposition only range_difference_t<Base> missing_ = 0; // exposition only constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only range_difference_t<Base> missing = 0); public: using difference_type = range_difference_t<Base>; using value_type = range_value_t<Base>; using iterator_concept = see below; using iterator_category = see below; // not always present iterator() requires default_initializable<iterator_t<Base>> = default; constexpr iterator(iterator<!Const> other) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>> && convertible_to<sentinel_t<V>, sentinel_t<Base>>; constexpr iterator_t<Base> base() &&; constexpr const iterator_t<Base>& base() const & noexcept; constexpr decltype(auto) operator*() const { return *current_; } constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<Base>; constexpr iterator& operator--() requires bidirectional_range<Base>; constexpr iterator operator--(int) requires bidirectional_range<Base>; constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>; constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>; constexpr decltype(auto) operator[](difference_type n) const requires random_access_range<Base> { return *(*this + n); } friend constexpr bool operator==(const iterator& x, default_sentinel_t); friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<Base>>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>; friend constexpr iterator operator+(const iterator& x, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& x) requires random_access_range<Base>; friend constexpr iterator operator-(const iterator& x, difference_type n) requires random_access_range<Base>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>; friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<Base>>; }; }
iterator​::​iterator_concept is defined as follows:
The member typedef-name iterator_category is defined if and only if Base models forward_range.
In that case, iterator​::​iterator_category is defined as follows:
  • Let C denote the type iterator_traits<iterator_t<Base>>​::​iterator_category.
  • If C models derived_from<random_access_iterator_tag>, then iterator_category denotes random_access_iterator_tag.
  • Otherwise, iterator_category denotes C.
constexpr iterator(Parent* parent, iterator_t<Base> current, range_difference_t<Base> missing = 0);
Effects: Initializes current_ with std​::​move(current), end_ with ranges​::​end(parent->base_), stride_ with parent->stride_, and missing_ with missing.
constexpr iterator(iterator<!Const> i) requires Const && convertible_to<iterator_t<V>, iterator_t<Base>> && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes current_ with std​::​move(i.current_), end_ with std​::​move(i.end_), stride_ with i.stride_, and missing_ with i.missing_.
constexpr iterator_t<Base> base() &&;
Returns: std​::​move(current_).
constexpr const iterator_t<Base>& base() const & noexcept;
Returns: current_.
constexpr iterator& operator++();
Preconditions: current_ != end_ is true.
Effects: Equivalent to: missing_ = ranges::advance(current_, stride_, end_); return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this;
constexpr iterator operator++(int) requires forward_range<Base>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires bidirectional_range<Base>;
Effects: Equivalent to: ranges::advance(current_, missing_ - stride_); missing_ = 0; return *this;
constexpr iterator operator--(int) requires bidirectional_range<Base>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
Preconditions: If n is positive, ranges​::​distance(current_, end_) > stride_ * (n - 1) is true.
[Note 1: 
If n is negative, the Effects paragraph implies a precondition.
— end note]
Effects: Equivalent to: if (n > 0) { ranges::advance(current_, stride_ * (n - 1)); missing_ = ranges::advance(current_, stride_, end_); } else if (n < 0) { ranges::advance(current_, stride_ * n + missing_); missing_ = 0; } return *this;
constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
Effects: Equivalent to: return *this += -x;
friend constexpr bool operator==(const iterator& x, default_sentinel_t);
Returns: x.current_ == x.end_.
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<Base>>;
Returns: x.current_ == y.current_.
friend constexpr bool operator<(const iterator& x, const iterator& y) requires random_access_range<Base>;
Returns: x.current_ < y.current_.
friend constexpr bool operator>(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return y < x;
friend constexpr bool operator<=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(y < x);
friend constexpr bool operator>=(const iterator& x, const iterator& y) requires random_access_range<Base>;
Effects: Equivalent to: return !(x < y);
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
Returns: x.current_ <=> y.current_.
friend constexpr iterator operator+(const iterator& i, difference_type n) requires random_access_range<Base>; friend constexpr iterator operator+(difference_type n, const iterator& i) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r += n; return r;
friend constexpr iterator operator-(const iterator& i, difference_type n) requires random_access_range<Base>;
Effects: Equivalent to: auto r = i; r -= n; return r;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
Returns: Let N be (x.current_ - y.current_).
  • If Base models forward_range, (N + x.missing_ - y.missing_) / x.stride_.
  • Otherwise, if N is negative, -div-ceil(-N, x.stride_).
  • Otherwise, div-ceil(N, x.stride_).
friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
Returns: div-ceil(x.end_ - x.current_, x.stride_).
friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y) requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
Effects: Equivalent to: return -(y - x);
friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)));
Effects: Equivalent to: return ranges​::​iter_move(i.current_);
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<Base>>;
Effects: Equivalent to: ranges​::​iter_swap(x.current_, y.current_);

25.7.33 Cartesian product view [range.cartesian]

25.7.33.1 Overview [range.cartesian.overview]

cartesian_product_view takes any non-zero number of ranges n and produces a view of tuples calculated by the n-ary cartesian product of the provided ranges.
The name views​::​cartesian_product denotes a customization point object ([customization.point.object]).
Given a pack of subexpressions Es, the expression views​::​cartesian_product(Es...) is expression-equivalent to
  • views​::​single(tuple()) if Es is an empty pack,
  • otherwise, cartesian_product_view<views​::​all_t<decltype((Es))>...>(Es...).
[Example 1: vector<int> v { 0, 1, 2 }; for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) { cout << a << ' ' << b << ' ' << c << '\n'; } // The above prints // 0 0 0 // 0 0 1 // 0 0 2 // 0 1 0 // 0 1 1 // ... — end example]

25.7.33.2 Class template cartesian_product_view [range.cartesian.view]

namespace std::ranges { template<bool Const, class First, class... Vs> concept cartesian-product-is-random-access = // exposition only (random_access_range<maybe-const<Const, First>> && ... && (random_access_range<maybe-const<Const, Vs>> && sized_range<maybe-const<Const, Vs>>)); template<class R> concept cartesian-product-common-arg = // exposition only common_range<R> || (sized_range<R> && random_access_range<R>); template<bool Const, class First, class... Vs> concept cartesian-product-is-bidirectional = // exposition only (bidirectional_range<maybe-const<Const, First>> && ... && (bidirectional_range<maybe-const<Const, Vs>> && cartesian-product-common-arg<maybe-const<Const, Vs>>)); template<class First, class...> concept cartesian-product-is-common = // exposition only cartesian-product-common-arg<First>; template<class... Vs> concept cartesian-product-is-sized = // exposition only (sized_range<Vs> && ...); template<bool Const, template<class> class FirstSent, class First, class... Vs> concept cartesian-is-sized-sentinel = // exposition only (sized_sentinel_for<FirstSent<maybe-const<Const, First>>, iterator_t<maybe-const<Const, First>>> && ... && (sized_range<maybe-const<Const, Vs>> && sized_sentinel_for<iterator_t<maybe-const<Const, Vs>>, iterator_t<maybe-const<Const, Vs>>>)); template<cartesian-product-common-arg R> constexpr auto cartesian-common-arg-end(R& r) { // exposition only if constexpr (common_range<R>) { return ranges::end(r); } else { return ranges::begin(r) + ranges::distance(r); } } template<input_range First, forward_range... Vs> requires (view<First> && ... && view<Vs>) class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> { private: tuple<First, Vs...> bases_; // exposition only // [range.cartesian.iterator], class template cartesian_product_view​::​iterator template<bool Const> class iterator; // exposition only public: constexpr cartesian_product_view() = default; constexpr explicit cartesian_product_view(First first_base, Vs... bases); constexpr iterator<false> begin() requires (!simple-view<First> || ... || !simple-view<Vs>); constexpr iterator<true> begin() const requires (range<const First> && ... && range<const Vs>); constexpr iterator<false> end() requires ((!simple-view<First> || ... || !simple-view<Vs>) && cartesian-product-is-common<First, Vs...>); constexpr iterator<true> end() const requires cartesian-product-is-common<const First, const Vs...>; constexpr default_sentinel_t end() const noexcept; constexpr see below size() requires cartesian-product-is-sized<First, Vs...>; constexpr see below size() const requires cartesian-product-is-sized<const First, const Vs...>; }; template<class... Vs> cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>; }
constexpr explicit cartesian_product_view(First first_base, Vs... bases);
Effects: Initializes bases_ with std​::​move(first_base), std​::​move(bases)....
constexpr iterator<false> begin() requires (!simple-view<First> || ... || !simple-view<Vs>);
Effects: Equivalent to: return iterator<false>(*this, tuple-transform(ranges::begin, bases_));
constexpr iterator<true> begin() const requires (range<const First> && ... && range<const Vs>);
Effects: Equivalent to: return iterator<true>(*this, tuple-transform(ranges::begin, bases_));
constexpr iterator<false> end() requires ((!simple-view<First> || ... || !simple-view<Vs>) && cartesian-product-is-common<First, Vs...>); constexpr iterator<true> end() const requires cartesian-product-is-common<const First, const Vs...>;
Let:
  • is-const be true for the const-qualified overload, and false otherwise;
  • is-empty be true if the expression ranges​::​empty(rng) is true for any rng among the underlying ranges except the first one and false otherwise; and
  • begin-or-first-end(rng) be expression-equivalent to is-empty ? ranges​::​begin(rng) :cartesian-common-arg-end(rng) if rng is the first underlying range and ranges​::​begin(rng) otherwise.
Effects: Equivalent to: iterator<is-const> it(*this, tuple-transform( [](auto& rng){ return begin-or-first-end(rng); }, bases_)); return it;
constexpr default_sentinel_t end() const noexcept;
Returns: default_sentinel.
constexpr see below size() requires cartesian-product-is-sized<First, Vs...>; constexpr see below size() const requires cartesian-product-is-sized<const First, const Vs...>;
The return type is an implementation-defined unsigned-integer-like type.
Recommended practice: The return type should be the smallest unsigned-integer-like type that is sufficiently wide to store the product of the maximum sizes of all the underlying ranges, if such a type exists.
Let p be the product of the sizes of all the ranges in bases_.
Preconditions: p can be represented by the return type.
Returns: p.

25.7.33.3 Class template cartesian_product_view​::​iterator [range.cartesian.iterator]

namespace std::ranges { template<input_range First, forward_range... Vs> requires (view<First> && ... && view<Vs>) template<bool Const> class cartesian_product_view<First, Vs...>::iterator { public: using iterator_category = input_iterator_tag; using iterator_concept = see below; using value_type = tuple<range_value_t<maybe-const<Const, First>>, range_value_t<maybe-const<Const, Vs>>...>; using reference = tuple<range_reference_t<maybe-const<Const, First>>, range_reference_t<maybe-const<Const, Vs>>...>; using difference_type = see below; iterator() = default; constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<First>, iterator_t<const First>> && ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>); constexpr auto operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>; constexpr iterator& operator--() requires cartesian-product-is-bidirectional<Const, First, Vs...>; constexpr iterator operator--(int) requires cartesian-product-is-bidirectional<Const, First, Vs...>; constexpr iterator& operator+=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>; constexpr iterator& operator-=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>; constexpr reference operator[](difference_type n) const requires cartesian-product-is-random-access<Const, First, Vs...>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<maybe-const<Const, First>>>; friend constexpr bool operator==(const iterator& x, default_sentinel_t); friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires all-random-access<Const, First, Vs...>; friend constexpr iterator operator+(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>; friend constexpr iterator operator+(difference_type x, const iterator& y) requires cartesian-product-is-random-access<Const, First, Vs...>; friend constexpr iterator operator-(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>; friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>; friend constexpr difference_type operator-(const iterator& i, default_sentinel_t) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>; friend constexpr difference_type operator-(default_sentinel_t, const iterator& i) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>; friend constexpr auto iter_move(const iterator& i) noexcept(see below); friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... && indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>); private: using Parent = maybe-const<Const, cartesian_product_view>; // exposition only Parent* parent_ = nullptr; // exposition only tuple<iterator_t<maybe-const<Const, First>>, iterator_t<maybe-const<Const, Vs>>...> current_; // exposition only template<size_t N = sizeof...(Vs)> constexpr void next(); // exposition only template<size_t N = sizeof...(Vs)> constexpr void prev(); // exposition only template<class Tuple> constexpr difference_type distance-from(const Tuple& t) const; // exposition only constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>, iterator_t<maybe-const<Const, Vs>>...> current); // exposition only }; }
iterator​::​iterator_concept is defined as follows:
iterator​::​difference_type is an implementation-defined signed-integer-like type.
Recommended practice: iterator​::​difference_type should be the smallest signed-integer-like type that is sufficiently wide to store the product of the maximum sizes of all underlying ranges if such a type exists.
template<size_t N = sizeof...(Vs)> constexpr void next();
Effects: Equivalent to: auto& it = std::get<N>(current_); ++it; if constexpr (N > 0) { if (it == ranges::end(std::get<N>(parent_->bases_))) { it = ranges::begin(std::get<N>(parent_->bases_)); next<N - 1>(); } }
template<size_t N = sizeof...(Vs)> constexpr void prev();
Effects: Equivalent to: auto& it = std::get<N>(current_); if constexpr (N > 0) { if (it == ranges::begin(std::get<N>(parent_->bases_))) { it = cartesian-common-arg-end(std::get<N>(parent_->bases_)); prev<N - 1>(); } } --it;
template<class Tuple> constexpr difference_type distance-from(const Tuple& t) const;
Let:
  • scaled-size(N) be the product of static_cast<difference_type>(ranges​::​size(std​::​get<N>(parent_->bases_))) and if N  ≤ sizeof...(Vs), otherwise static_cast<difference_type>(1);
  • scaled-distance(N) be the product of static_cast<difference_type>(std​::​get<N>(current_) - std​::​get<N>(t)) and ; and
  • scaled-sum be the sum of scaled-distance(N) for every integer 0  ≤ N  ≤ sizeof...(Vs).
Preconditions: scaled-sum can be represented by difference_type.
Returns: scaled-sum.
constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>, iterator_t<maybe-const<Const, Vs>>...> current);
Effects: Initializes parent_ with addressof(parent) and current_ with std​::​move(current).
constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<First>, iterator_t<const First>> && ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);
Effects: Initializes parent_ with i.parent_ and current_ with std​::​move(i.current_).
constexpr auto operator*() const;
Effects: Equivalent to: return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
constexpr iterator& operator++();
Effects: Equivalent to: next(); return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>;
Effects: Equivalent to: auto tmp = *this; ++*this; return tmp;
constexpr iterator& operator--() requires cartesian-product-is-bidirectional<Const, First, Vs...>;
Effects: Equivalent to: prev(); return *this;
constexpr iterator operator--(int) requires cartesian-product-is-bidirectional<Const, First, Vs...>;
Effects: Equivalent to: auto tmp = *this; --*this; return tmp;
constexpr iterator& operator+=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>;
Let orig be the value of *this before the call.
Let ret be:
  • If x > 0, the value of *this had next been called x times.
  • Otherwise, if x < 0, the value of *this had prev been called -x times.
  • Otherwise, orig.
Preconditions: x is in the range [ranges​::​distance(*this, ranges​::​begin(*parent_)),
ranges​::​distance(*this, ranges​::​end(*parent_))].
Effects: Sets the value of *this to ret.
Returns: *this.
Complexity: Constant.
constexpr iterator& operator-=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>;
Effects: Equivalent to: *this += -x; return *this;
constexpr reference operator[](difference_type n) const requires cartesian-product-is-random-access<Const, First, Vs...>;
Effects: Equivalent to: return *((*this) + n);
friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<maybe-const<Const, First>>>;
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr bool operator==(const iterator& x, default_sentinel_t);
Returns: true if std​::​get<i>(x.current_) == ranges​::​end(std​::​get<i>(x.parent_->bases_)) is true for any integer 0  ≤ i  ≤ sizeof...(Vs); otherwise, false.
friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires all-random-access<Const, First, Vs...>;
Effects: Equivalent to: return x.current_ <=> y.current_;
friend constexpr iterator operator+(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>;
Effects: Equivalent to: return iterator(x) += y;
friend constexpr iterator operator+(difference_type x, const iterator& y) requires cartesian-product-is-random-access<Const, First, Vs...>;
Effects: Equivalent to: return y + x;
friend constexpr iterator operator-(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>;
Effects: Equivalent to: return iterator(x) -= y;
friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
Effects: Equivalent to: return x.distance-from(y.current_);
friend constexpr difference_type operator-(const iterator& i, default_sentinel_t) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
Let end-tuple be an object of a type that is a specialization of tuple, such that:
  • std​::​get<0>(end-tuple) has the same value as ranges​::​end(std​::​get<0>(i.parent_->bases_));
  • std​::​get<N>(end-tuple) has the same value as ranges​::​begin(std​::​get<N>(i.parent_->bases_)) for every integer 1  ≤ N  ≤ sizeof...(Vs).
Effects: Equivalent to: return i.distance-from(end-tuple);
friend constexpr difference_type operator-(default_sentinel_t s, const iterator& i) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
Effects: Equivalent to: return -(i - s);
friend constexpr auto iter_move(const iterator& i) noexcept(see below);
Effects: Equivalent to: return tuple-transform(ranges​::​iter_move, i.current_);
Remarks: The exception specification is equivalent to the logical and of the following expressions:
  • noexcept(ranges​::​iter_move(std​::​get<N>(i.current_))) for every integer
    0  ≤ N  ≤ sizeof...(Vs),
  • is_nothrow_move_constructible_v<range_rvalue_reference_t<maybe-const<Const, T>>>
    for every type T in First, Vs....
friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... && indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>);
Effects: For every integer 0  ≤ i  ≤ sizeof...(Vs), performs: ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
Remarks: The exception specification is equivalent to the logical and of the following expressions:
  • noexcept(ranges​::​iter_swap(std​::​get<i>(l.current_), std​::​get<i>(r.current_))) for
    every integer 0  ≤ i  ≤ sizeof...(Vs).

25.7.34 Cache latest view [range.cache.latest]

25.7.34.1 Overview [range.cache.latest.overview]

cache_latest_view caches the last-accessed element of its underlying sequence so that the element does not have to be recomputed on repeated access.
[Note 1: 
This is useful if computation of the element to produce is expensive.
— end note]
The name views​::​cache_latest denotes a range adaptor object ([range.adaptor.object]).
Let E be an expression.
The expression views​::​cache_latest(E) is expression-equivalent to cache_latest_view(E).

25.7.34.2 Class template cache_latest_view [range.cache.latest.view]

namespace std::ranges { template<input_range V> requires view<V> class cache_latest_view : public view_interface<cache_latest_view<V>> { V base_ = V(); // exposition only using cache-t = conditional_t<is_reference_v<range_reference_t<V>>, // exposition only add_pointer_t<range_reference_t<V>>, range_reference_t<V>>; non-propagating-cache<cache-t> cache_; // exposition only class iterator; // exposition only class sentinel; // exposition only public: cache_latest_view() requires default_initializable<V> = default; constexpr explicit cache_latest_view(V base); constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr auto begin(); constexpr auto end(); constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>; }; template<class R> cache_latest_view(R&&) -> cache_latest_view<views::all_t<R>>; }
constexpr explicit cache_latest_view(V base);
Effects: Initializes base_ with std​::​move(base).
constexpr auto begin();
Effects: Equivalent to: return iterator(*this);
constexpr auto end();
Effects: Equivalent to: return sentinel(*this);
constexpr auto size() requires sized_range<V>; constexpr auto size() const requires sized_range<const V>;
Effects: Equivalent to: return ranges​::​size(base_);

25.7.34.3 Class cache_latest_view​::​iterator [range.cache.latest.iterator]

namespace std::ranges { template<input_range V> requires view<V> class cache_latest_view<V>::iterator { cache_latest_view* parent_; // exposition only iterator_t<V> current_; // exposition only constexpr explicit iterator(cache_latest_view& parent); // exposition only public: using difference_type = range_difference_t<V>; using value_type = range_value_t<V>; using iterator_concept = input_iterator_tag; iterator(iterator&&) = default; iterator& operator=(iterator&&) = default; constexpr iterator_t<V> base() &&; constexpr const iterator_t<V>& base() const & noexcept; constexpr range_reference_t<V>& operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<V>>; }; }
constexpr explicit iterator(cache_latest_view& parent);
Effects: Initializes current_ with ranges​::​begin(parent.base_) and parent_ with addressof(parent).
constexpr iterator_t<V> base() &&;
Returns: std​::​move(current_).
constexpr const iterator_t<V>& base() const & noexcept;
Returns: current_.
constexpr iterator& operator++();
Effects: Equivalent to: parent_->cache_.reset(); ++current_; return *this;
constexpr void operator++(int);
Effects: Equivalent to: ++*this.
constexpr range_reference_t<V>& operator*() const;
Effects: Equivalent to: if constexpr (is_reference_v<range_reference_t<V>>) { if (!parent_->cache_) { parent_->cache_ = addressof(as-lvalue(*current_)); } return **parent_->cache_; } else { if (!parent_->cache_) { parent_->cache_.emplace-deref(current_); } return *parent_->cache_; }
[Note 1: 
Evaluations of operator* on the same iterator object can conflict ([intro.races]).
— end note]
friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)));
Effects: Equivalent to: return ranges​::​iter_move(i.current_);
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires indirectly_swappable<iterator_t<V>>;
Effects: Equivalent to ranges​::​iter_swap(x.current_, y.current_).

25.7.34.4 Class cache_latest_view​::​sentinel [range.cache.latest.sentinel]

namespace std::ranges { template<input_range V> requires view<V> class cache_latest_view<V>::sentinel { sentinel_t<V> end_ = sentinel_t<V>(); // exposition only constexpr explicit sentinel(cache_latest_view& parent); // exposition only public: sentinel() = default; constexpr sentinel_t<V> base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); friend constexpr range_difference_t<V> operator-(const iterator& x, const sentinel& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; friend constexpr range_difference_t<V> operator-(const sentinel& x, const iterator& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>; }; }
constexpr explicit sentinel(cache_latest_view& parent);
Effects: Initializes end_ with ranges​::​end(parent.base_).
constexpr sentinel_t<V> base() const;
Returns: end_.
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Returns: x.current_ == y.end_.
friend constexpr range_difference_t<V> operator-(const iterator& x, const sentinel& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Returns: x.current_ - y.end_.
friend constexpr range_difference_t<V> operator-(const sentinel& x, const iterator& y) requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
Returns: x.end_ - y.current_.

25.8 Range generators [coro.generator]

25.8.1 Overview [coroutine.generator.overview]

Class template generator presents a view of the elements yielded by the evaluation of a coroutine.
A generator generates a sequence of elements by repeatedly resuming the coroutine from which it was returned.
Elements of the sequence are produced by the coroutine each time a co_yield statement is evaluated.
When the co_yield statement is of the form co_yield elements_of(r), each element of the range r is successively produced as an element of the sequence.
[Example 1: generator<int> ints(int start = 0) { while (true) co_yield start++; } void f() { for (auto i : ints() | views::take(3)) cout << i << ' '; // prints 0 1 2 } — end example]

25.8.2 Header <generator> synopsis [generator.syn]

namespace std { // [coro.generator.class], class template generator template<class Ref, class Val = void, class Allocator = void> class generator; namespace pmr { template<class Ref, class Val = void> using generator = std::generator<Ref, Val, polymorphic_allocator<>>; } }

25.8.3 Class template generator [coro.generator.class]

namespace std { template<class Ref, class Val = void, class Allocator = void> class generator : public ranges::view_interface<generator<Ref, Val, Allocator>> { private: using value = conditional_t<is_void_v<Val>, remove_cvref_t<Ref>, Val>; // exposition only using reference = conditional_t<is_void_v<Val>, Ref&&, Ref>; // exposition only // [coro.generator.iterator], class generator​::​iterator class iterator; // exposition only public: using yielded = conditional_t<is_reference_v<reference>, reference, const reference&>; // [coro.generator.promise], class generator​::​promise_type class promise_type; generator(const generator&) = delete; generator(generator&& other) noexcept; ~generator(); generator& operator=(generator other) noexcept; iterator begin(); default_sentinel_t end() const noexcept; private: coroutine_handle<promise_type> coroutine_ = nullptr; // exposition only unique_ptr<stack<coroutine_handle<>>> active_; // exposition only }; }
Mandates:
If Allocator is not void, it shall meet the Cpp17Allocator requirements.
Specializations of generator model view and input_range.
The behavior of a program that adds a specialization for generator is undefined.

25.8.4 Members [coro.generator.members]

generator(generator&& other) noexcept;
Effects: Initializes coroutine_ with exchange(other.coroutine_, {}) and active_ with exchange(​other.active_, nullptr).
[Note 1: 
Iterators previously obtained from other are not invalidated; they become iterators into *this.
— end note]
~generator();
Effects: Equivalent to: if (coroutine_) { coroutine_.destroy(); }
[Note 2: 
Ownership of recursively yielded generators is held in awaitable objects in the coroutine frame of the yielding generator, so destroying the root generator effectively destroys the entire stack of yielded generators.
— end note]
generator& operator=(generator other) noexcept;
Effects: Equivalent to: swap(coroutine_, other.coroutine_); swap(active_, other.active_);
Returns: *this.
[Note 3: 
Iterators previously obtained from other are not invalidated; they become iterators into *this.
— end note]
iterator begin();
Preconditions: coroutine_ refers to a coroutine suspended at its initial suspend point ([dcl.fct.def.coroutine]).
Effects: Pushes coroutine_ into *active_, then evaluates coroutine_.resume().
Returns: An iterator object whose member coroutine_ refers to the same coroutine as does coroutine_.
[Note 4: 
A program that calls begin more than once on the same generator has undefined behavior.
— end note]
default_sentinel_t end() const noexcept;
Returns: default_sentinel.

25.8.5 Class generator​::​promise_type [coro.generator.promise]

namespace std { template<class Ref, class Val, class Allocator> class generator<Ref, Val, Allocator>::promise_type { public: generator get_return_object() noexcept; suspend_always initial_suspend() const noexcept { return {}; } auto final_suspend() noexcept; suspend_always yield_value(yielded val) noexcept; auto yield_value(const remove_reference_t<yielded>& lval) requires is_rvalue_reference_v<yielded> && constructible_from<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>; template<class R2, class V2, class Alloc2, class Unused> requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded> auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept; template<class R2, class V2, class Alloc2, class Unused> requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded> auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&, Unused> g) noexcept; template<ranges::input_range R, class Alloc> requires convertible_to<ranges::range_reference_t<R>, yielded> auto yield_value(ranges::elements_of<R, Alloc> r); void await_transform() = delete; void return_void() const noexcept {} void unhandled_exception(); void* operator new(size_t size) requires same_as<Allocator, void> || default_initializable<Allocator>; template<class Alloc, class... Args> void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template<class This, class Alloc, class... Args> void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, const Args&...); void operator delete(void* pointer, size_t size) noexcept; private: add_pointer_t<yielded> value_ = nullptr; // exposition only exception_ptr except_; // exposition only }; }
generator get_return_object() noexcept;
Returns: A generator object whose member coroutine_ is coroutine_handle<promise_type>​::​​from_promise(*this), and whose member active_ points to an empty stack.
auto final_suspend() noexcept;
Preconditions: A handle referring to the coroutine whose promise object is *this is at the top of *active_ of some generator object x.
This function is called by that coroutine upon reaching its final suspend point ([dcl.fct.def.coroutine]).
Returns: An awaitable object of unspecified type ([expr.await]) whose member functions arrange for the calling coroutine to be suspended, pop the coroutine handle from the top of *x.active_, and resume execution of the coroutine referred to by x.active_->top() if *x.active_ is not empty.
If it is empty, control flow returns to the current coroutine caller or resumer ([dcl.fct.def.coroutine]).
suspend_always yield_value(yielded val) noexcept;
Effects: Equivalent to value_ = addressof(val).
Returns: {}.
auto yield_value(const remove_reference_t<yielded>& lval) requires is_rvalue_reference_v<yielded> && constructible_from<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>;
Preconditions: A handle referring to the coroutine whose promise object is *this is at the top of *active_ of some generator object.
Returns: An awaitable object of an unspecified type ([expr.await]) that stores an object of type remove_cvref_t<yielded> direct-non-list-initialized with lval, whose member functions arrange for value_ to point to that stored object and then suspend the coroutine.
Throws: Any exception thrown by the initialization of the stored object.
Remarks: A yield-expression that calls this function has type void ([expr.yield]).
template<class R2, class V2, class Alloc2, class Unused> requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded> auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept; template<class R2, class V2, class Alloc2, class Unused> requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded> auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&, Unused> g) noexcept;
Preconditions: A handle referring to the coroutine whose promise object is *this is at the top of *active_ of some generator object x.
The coroutine referred to by g.range.coroutine_ is suspended at its initial suspend point.
Returns: An awaitable object of an unspecified type ([expr.await]) into which g.range is moved, whose member await_ready returns false, whose member await_suspend pushes g.range.coroutine_ into *x.active_ and resumes execution of the coroutine referred to by g.range.coroutine_, and whose member await_resume evaluates rethrow_exception(except_) if bool(except_) is true.
If bool(except_) is false, the await_resume member has no effects.
Remarks: A yield-expression that calls one of these functions has type void ([expr.yield]).
template<ranges::input_range R, class Alloc> requires convertible_to<ranges::range_reference_t<R>, yielded> auto yield_value(ranges::elements_of<R, Alloc> r);
Effects: Equivalent to: auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t<R> i, ranges::sentinel_t<R> s) -> generator<yielded, void, Alloc> { for (; i != s; ++i) { co_yield static_cast<yielded>(*i); } }; return yield_value(ranges::elements_of(nested( allocator_arg, r.allocator, ranges::begin(r.range), ranges::end(r.range))));
[Note 1: 
A yield-expression that calls this function has type void ([expr.yield]).
— end note]
void unhandled_exception();
Preconditions: A handle referring to the coroutine whose promise object is *this is at the top of *active_ of some generator object x.
Effects: If the handle referring to the coroutine whose promise object is *this is the sole element of *x.active_, equivalent to throw, otherwise, assigns current_exception() to except_.
void* operator new(size_t size) requires same_as<Allocator, void> || default_initializable<Allocator>; template<class Alloc, class... Args> void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...); template<class This, class Alloc, class... Args> void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc, const Args&...);
Let A be
  • Allocator, if it is not void,
  • Alloc for the overloads with a template parameter Alloc, or
  • allocator<void> otherwise.
Let B be allocator_traits<A>​::​template rebind_alloc<U> where U is an unspecified type whose size and alignment are both __STDCPP_DEFAULT_NEW_ALIGNMENT__.
Mandates: allocator_traits<B>​::​pointer is a pointer type.
For the overloads with a template parameter Alloc, same_as<Allocator, void> || convertible_to<const Alloc&, Allocator> is modeled.
Effects: Initializes an allocator b of type B with A(alloc), for the overloads with a function parameter alloc, and with A() otherwise.
Uses b to allocate storage for the smallest array of U sufficient to provide storage for a coroutine state of size size, and unspecified additional state necessary to ensure that operator delete can later deallocate this memory block with an allocator equal to b.
Returns: A pointer to the allocated storage.
void operator delete(void* pointer, size_t size) noexcept;
Preconditions: pointer was returned from an invocation of one of the above overloads of operator new with a size argument equal to size.
Effects: Deallocates the storage pointed to by pointer using an allocator equivalent to that used to allocate it.

25.8.6 Class generator​::​iterator [coro.generator.iterator]

namespace std { template<class Ref, class Val, class Allocator> class generator<Ref, Val, Allocator>::iterator { public: using value_type = value; using difference_type = ptrdiff_t; iterator(iterator&& other) noexcept; iterator& operator=(iterator&& other) noexcept; reference operator*() const noexcept(is_nothrow_copy_constructible_v<reference>); iterator& operator++(); void operator++(int); friend bool operator==(const iterator& i, default_sentinel_t); private: coroutine_handle<promise_type> coroutine_; // exposition only }; }
iterator(iterator&& other) noexcept;
Effects: Initializes coroutine_ with exchange(other.coroutine_, {}).
iterator& operator=(iterator&& other) noexcept;
Effects: Equivalent to coroutine_ = exchange(other.coroutine_, {}).
Returns: *this.
reference operator*() const noexcept(is_nothrow_copy_constructible_v<reference>);
Preconditions: For some generator object x, coroutine_ is in *x.active_ and x.active_->top() refers to a suspended coroutine with promise object p.
Effects: Equivalent to: return static_cast<reference>(*p.value_);
iterator& operator++();
Preconditions: For some generator object x, coroutine_ is in *x.active_.
Effects: Equivalent to x.active_->top().resume().
Returns: *this.
void operator++(int);
Effects: Equivalent to ++*this.
friend bool operator==(const iterator& i, default_sentinel_t);
Effects: Equivalent to: return i.coroutine_.done();

26 Algorithms library [algorithms]

26.1 General [algorithms.general]

This Clause describes components that C++ programs may use to perform algorithmic operations on containers and other sequences.
The following subclauses describe components for non-modifying sequence operations, mutating sequence operations, sorting and related operations, and algorithms from the C library, as summarized in Table 80.
Table 80 — Algorithms library summary [tab:algorithms.summary]
Subclause
Header
Algorithms requirements
Parallel algorithms
<execution>
Algorithm result types
<algorithm>
Non-modifying sequence operations
Mutating sequence operations
Sorting and related operations
Generalized numeric operations
<numeric>
Specialized <memory> algorithms
<memory>
Specialized <random> algorithms
<random>
C library algorithms
<cstdlib>

26.2 Algorithms requirements [algorithms.requirements]

All of the algorithms are separated from the particular implementations of data structures and are parameterized by iterator types.
Because of this, they can work with program-defined data structures, as long as these data structures have iterator types satisfying the assumptions on the algorithms.
The entities defined in the std​::​ranges namespace in this Clause and specified as function templates are algorithm function objects ([alg.func.obj]).
For purposes of determining the existence of data races, algorithms shall not modify objects referenced through an iterator argument unless the specification requires such modification.
Throughout this Clause, where the template parameters are not constrained, the names of template parameters are used to express type requirements.
[Note 1: 
These requirements do not affect iterator arguments that are constrained, for which iterator category and mutability requirements are expressed explicitly.
— end note]
Both in-place and copying versions are provided for certain algorithms.203
When such a version is provided for algorithm it is called algorithm_copy.
Algorithms that take predicates end with the suffix _if (which follows the suffix _copy).
When not otherwise constrained, the Predicate parameter is used whenever an algorithm expects a function object ([function.objects]) that, when applied to the result of dereferencing the corresponding iterator, returns a value testable as true.
If an algorithm takes Predicate pred as its argument and first as its iterator argument with value type T, the expression pred(*first) shall be well-formed and the type decltype(pred(*first)) shall model boolean-testable ([concept.booleantestable]).
The function object pred shall not apply any non-constant function through its argument.
Given a glvalue u of type (possibly const) T that designates the same object as *first, pred(u) shall be a valid expression that is equal to pred(*first).
When not otherwise constrained, the BinaryPredicate parameter is used whenever an algorithm expects a function object that, when applied to the result of dereferencing two corresponding iterators or to dereferencing an iterator and type T when T is part of the signature, returns a value testable as true.
If an algorithm takes BinaryPredicate binary_pred as its argument and first1 and first2 as its iterator arguments with respective value types T1 and T2, the expression binary_pred(*first1, *first2) shall be well-formed and the type decltype(binary_pred(*first1, *first2)) shall model boolean-testable.
Unless otherwise specified, BinaryPredicate always takes the first iterator's value_type as its first argument, that is, in those cases when T value is part of the signature, the expression binary_pred(*first1, value) shall be well-formed and the type decltype(binary_pred(*first1, value)) shall model boolean-testable.
binary_pred shall not apply any non-constant function through any of its arguments.
Given a glvalue u of type (possibly const) T1 that designates the same object as *first1, and a glvalue v of type (possibly const) T2 that designates the same object as *first2, binary_pred(u, *first2), binary_pred(*first1, v), and binary_pred(u, v) shall each be a valid expression that is equal to binary_pred(*first1, *first2), and binary_pred(u, value) shall be a valid expression that is equal to binary_pred(*first1, value).
The parameters UnaryOperation, BinaryOperation, BinaryOperation1, and BinaryOperation2 are used whenever an algorithm expects a function object ([function.objects]).
[Note 2: 
Unless otherwise specified, algorithms that take function objects as arguments can copy those function objects freely.
If object identity is important, a wrapper class that points to a non-copied implementation object such as reference_wrapper<T> ([refwrap]), or some equivalent solution, can be used.
— end note]
When the description of an algorithm gives an expression such as *first == value for a condition, the expression shall evaluate to either true or false in boolean contexts.
In the description of the algorithms, operator + is used for some of the iterator categories for which it does not have to be defined.
In these cases the semantics of a + n are the same as those of auto tmp = a; for (; n < 0; ++n) --tmp; for (; n > 0; --n) ++tmp; return tmp;
Similarly, operator - is used for some combinations of iterators and sentinel types for which it does not have to be defined.
If [a, b) denotes a range, the semantics of b - a in these cases are the same as those of iter_difference_t<decltype(a)> n = 0; for (auto tmp = a; tmp != b; ++tmp) ++n; return n; and if [b, a) denotes a range, the same as those of iter_difference_t<decltype(b)> n = 0; for (auto tmp = b; tmp != a; ++tmp) --n; return n;
In the description of the algorithms, given an iterator a whose difference type is D, and an expression n of integer-like type other than cv D, the semantics of a + n and a - n are, respectively, those of a + D(n) and a - D(n).
In the description of algorithm return values, a sentinel value s denoting the end of a range [i, s) is sometimes returned where an iterator is expected.
In these cases, the semantics are as if the sentinel is converted into an iterator using ranges​::​next(i, s).
Overloads of algorithms that take range arguments ([range.range]) behave as if they are implemented by calling ranges​::​begin and ranges​::​end on the range(s) and dispatching to the overload in namespace ranges that takes separate iterator and sentinel arguments.
The well-formedness and behavior of a call to an algorithm with an explicitly-specified template argument list is unspecified, except where explicitly stated otherwise.
[Note 3: 
Consequently, an implementation can declare an algorithm with different template parameters than those presented.
— end note]
203)203)
The decision whether to include a copying version was usually based on complexity considerations.
When the cost of doing the operation dominates the cost of copy, the copying version is not included.
For example, sort_copy is not included because the cost of sorting is much more significant, and users can invoke copy followed by sort.

26.3 Parallel algorithms [algorithms.parallel]

26.3.1 Preamble [algorithms.parallel.defns]

Subclause [algorithms.parallel] describes components that C++ programs may use to perform operations on containers and other sequences in parallel.
A parallel algorithm is a function template listed in this document with a template parameter named ExecutionPolicy.
Parallel algorithms access objects indirectly accessible via their arguments by invoking the following functions:
  • All operations of the categories of the iterators or mdspan types that the algorithm is instantiated with.
  • Operations on those sequence elements that are required by its specification.
  • User-provided function objects to be applied during the execution of the algorithm, if required by the specification.
  • Operations on those function objects required by the specification.
    [Note 1:  — end note]
These functions are herein called element access functions.
[Example 1: 
The sort function may invoke the following element access functions:
  • Operations of the random-access iterator of the actual template argument (as per [random.access.iterators]), as implied by the name of the template parameter RandomAccessIterator.
  • The swap function on the elements of the sequence (as per the preconditions specified in [sort]).
  • The user-provided Compare function object.
— end example]
A standard library function is vectorization-unsafe if it is specified to synchronize with another function invocation, or another function invocation is specified to synchronize with it, and if it is not a memory allocation or deallocation function.
[Note 2: 
Implementations must ensure that internal synchronization inside standard library functions does not prevent forward progress when those functions are executed by threads of execution with weakly parallel forward progress guarantees.
— end note]
[Example 2: int x = 0; std::mutex m; void f() { int a[] = {1,2}; std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); // incorrect: lock_guard constructor calls m.lock() ++x; }); }
The above program may result in two consecutive calls to m.lock() on the same thread of execution (which may deadlock), because the applications of the function object are not guaranteed to run on different threads of execution.
— end example]

26.3.2 Requirements on user-provided function objects [algorithms.parallel.user]

Unless otherwise specified, function objects passed into parallel algorithms as objects of type Predicate, BinaryPredicate, Compare, UnaryOperation, BinaryOperation, BinaryOperation1, BinaryOperation2, BinaryDivideOp, and the operators used by the analogous overloads to these parallel algorithms that are formed by an invocation with the specified default predicate or operation (where applicable) shall not directly or indirectly modify objects via their arguments, nor shall they rely on the identity of the provided objects.

26.3.3 Effect of execution policies on algorithm execution [algorithms.parallel.exec]

Parallel algorithms have template parameters named ExecutionPolicy ([execpol]) which describe the manner in which the execution of these algorithms may be parallelized and the manner in which they apply the element access functions.
If an object is modified by an element access function, the algorithm will perform no other unsynchronized accesses to that object.
The modifying element access functions are those which are specified as modifying the object.
[Note 1: 
For example, swap, ++, --, @=, and assignments modify the object.
For the assignment and @= operators, only the left argument is modified.
— end note]
Unless otherwise stated, implementations may make arbitrary copies of elements (with type T) from sequences where is_trivially_copy_constructible_v<T> and is_trivially_destructible_v<T> are true.
[Note 2: 
This implies that user-supplied function objects cannot rely on object identity of arguments for such input sequences.
If object identity of the arguments to these function objects is important, a wrapping iterator that returns a non-copied implementation object such as reference_wrapper<T> ([refwrap]), or some equivalent solution, can be used.
— end note]
The invocations of element access functions in parallel algorithms invoked with an execution policy object of type execution​::​sequenced_policy all occur in the calling thread of execution.
[Note 3: 
The invocations are not interleaved; see [intro.execution].
— end note]
The invocations of element access functions in parallel algorithms invoked with an execution policy object of type execution​::​unsequenced_policy are permitted to execute in an unordered fashion in the calling thread of execution, unsequenced with respect to one another in the calling thread of execution.
[Note 4: 
This means that multiple function object invocations can be interleaved on a single thread of execution, which overrides the usual guarantee from [intro.execution] that function executions do not overlap with one another.
— end note]
The behavior of a program is undefined if it invokes a vectorization-unsafe standard library function from user code called from an execution​::​unsequenced_policy algorithm.
[Note 5: 
Because execution​::​unsequenced_policy allows the execution of element access functions to be interleaved on a single thread of execution, blocking synchronization, including the use of mutexes, risks deadlock.
— end note]
The invocations of element access functions in parallel algorithms invoked with an execution policy object of type execution​::​parallel_policy are permitted to execute either in the invoking thread of execution or in a thread of execution implicitly created by the library to support parallel algorithm execution.
If the threads of execution created by thread ([thread.thread.class]) or jthread ([thread.jthread.class]) provide concurrent forward progress guarantees ([intro.progress]), then a thread of execution implicitly created by the library will provide parallel forward progress guarantees; otherwise, the provided forward progress guarantee is implementation-defined.
Any such invocations executing in the same thread of execution are indeterminately sequenced with respect to each other.
[Note 6: 
It is the caller's responsibility to ensure that the invocation does not introduce data races or deadlocks.
— end note]
[Example 1: int a[] = {0,1}; std::vector<int> v; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) { v.push_back(i*2+1); // incorrect: data race });
The program above has a data race because of the unsynchronized access to the container v.
— end example]
[Example 2: std::atomic<int> x{0}; int a[] = {1,2}; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { x.fetch_add(1, std::memory_order::relaxed); // spin wait for another iteration to change the value of x while (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order });
The above example depends on the order of execution of the iterations, and will not terminate if both iterations are executed sequentially on the same thread of execution.
— end example]
[Example 3: int x = 0; std::mutex m; int a[] = {1,2}; std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); ++x; });
The above example synchronizes access to object x ensuring that it is incremented correctly.
— end example]
The invocations of element access functions in parallel algorithms invoked with an execution policy object of type execution​::​parallel_unsequenced_policy are permitted to execute in an unordered fashion in unspecified threads of execution, and unsequenced with respect to one another within each thread of execution.
These threads of execution are either the invoking thread of execution or threads of execution implicitly created by the library; the latter will provide weakly parallel forward progress guarantees.
[Note 7: 
This means that multiple function object invocations can be interleaved on a single thread of execution, which overrides the usual guarantee from [intro.execution] that function executions do not overlap with one another.
— end note]
The behavior of a program is undefined if it invokes a vectorization-unsafe standard library function from user code called from an execution​::​parallel_unsequenced_policy algorithm.
[Note 8: 
Because execution​::​parallel_unsequenced_policy allows the execution of element access functions to be interleaved on a single thread of execution, blocking synchronization, including the use of mutexes, risks deadlock.
— end note]
[Note 9: 
The semantics of invocation with execution​::​unsequenced_policy, execution​::​parallel_policy, or execution​::​parallel_unsequenced_policy allow the implementation to fall back to sequential execution if the system cannot parallelize an algorithm invocation, e.g., due to lack of resources.
— end note]
If an invocation of a parallel algorithm uses threads of execution implicitly created by the library, then the invoking thread of execution will either
  • temporarily block with forward progress guarantee delegation ([intro.progress]) on the completion of these library-managed threads of execution, or
  • eventually execute an element access function;
the thread of execution will continue to do so until the algorithm is finished.
[Note 10: 
In blocking with forward progress guarantee delegation in this context, a thread of execution created by the library is considered to have finished execution as soon as it has finished the execution of the particular element access function that the invoking thread of execution logically depends on.
— end note]
The semantics of parallel algorithms invoked with an execution policy object of implementation-defined type are implementation-defined.

26.3.4 Parallel algorithm exceptions [algorithms.parallel.exceptions]

During the execution of a parallel algorithm, if temporary memory resources are required for parallelization and none are available, the algorithm throws a bad_alloc exception.
During the execution of a parallel algorithm, if the invocation of an element access function exits via an uncaught exception, the behavior is determined by the ExecutionPolicy.

26.3.5 ExecutionPolicy algorithm overloads [algorithms.parallel.overloads]

Parallel algorithms are algorithm overloads.
Each parallel algorithm overload has an additional template type parameter named ExecutionPolicy, which is the first template parameter.
Additionally, each parallel algorithm overload has an additional function parameter of type ExecutionPolicy&&, which is the first function parameter.
[Note 1: 
Not all algorithms have parallel algorithm overloads.
— end note]
Unless otherwise specified, the semantics of ExecutionPolicy algorithm overloads are identical to their overloads without.
Unless otherwise specified, the complexity requirements of ExecutionPolicy algorithm overloads are relaxed from the complexity requirements of the overloads without as follows: when the guarantee says “at most expr” or “exactly expr” and does not specify the number of assignments or swaps, and expr is not already expressed with notation, the complexity of the algorithm shall be .
Parallel algorithms shall not participate in overload resolution unless is_execution_policy_v<remove_cvref_t<ExecutionPolicy>> is true.

26.3.6 Execution policies [execpol]

26.3.6.1 General [execpol.general]

Subclause [execpol] describes classes that are execution policy types.
An object of an execution policy type indicates the kinds of parallelism allowed in the execution of an algorithm and expresses the consequent requirements on the element access functions.
Execution policy types are declared in header <execution>.
[Example 1: using namespace std; vector<int> v = /* ... */; // standard sequential sort sort(v.begin(), v.end()); // explicitly sequential sort sort(execution::seq, v.begin(), v.end()); // permitting parallel execution sort(execution::par, v.begin(), v.end()); // permitting vectorization as well sort(execution::par_unseq, v.begin(), v.end()); — end example]
[Note 1: 
Implementations can provide additional execution policies to those described in this document as extensions to address parallel architectures that require idiosyncratic parameters for efficient execution.
— end note]

26.3.6.2 Execution policy type trait [execpol.type]

template<class T> struct is_execution_policy { see below };
is_execution_policy can be used to detect execution policies for the purpose of excluding function signatures from otherwise ambiguous overload resolution participation.
is_execution_policy<T> is a Cpp17UnaryTypeTrait with a base characteristic of true_type if T is the type of a standard or implementation-defined execution policy, otherwise false_type.
[Note 1: 
This provision reserves the privilege of creating non-standard execution policies to the library implementation.
— end note]
The behavior of a program that adds specializations for is_execution_policy is undefined.

26.3.6.3 Sequenced execution policy [execpol.seq]

class execution::sequenced_policy { unspecified };
The class execution​::​sequenced_policy is an execution policy type used as a unique type to disambiguate parallel algorithm overloading and require that a parallel algorithm's execution may not be parallelized.
During the execution of a parallel algorithm with the execution​::​sequenced_policy policy, if the invocation of an element access function exits via an exception, terminate is invoked ([except.terminate]).

26.3.6.4 Parallel execution policy [execpol.par]

class execution::parallel_policy { unspecified };
The class execution​::​parallel_policy is an execution policy type used as a unique type to disambiguate parallel algorithm overloading and indicate that a parallel algorithm's execution may be parallelized.
During the execution of a parallel algorithm with the execution​::​parallel_policy policy, if the invocation of an element access function exits via an exception, terminate is invoked ([except.terminate]).

26.3.6.5 Parallel and unsequenced execution policy [execpol.parunseq]

class execution::parallel_unsequenced_policy { unspecified };
The class execution​::​parallel_unsequenced_policy is an execution policy type used as a unique type to disambiguate parallel algorithm overloading and indicate that a parallel algorithm's execution may be parallelized and vectorized.
During the execution of a parallel algorithm with the execution​::​parallel_unsequenced_policy policy, if the invocation of an element access function exits via an exception, terminate is invoked ([except.terminate]).

26.3.6.6 Unsequenced execution policy [execpol.unseq]

class execution::unsequenced_policy { unspecified };
The class unsequenced_policy is an execution policy type used as a unique type to disambiguate parallel algorithm overloading and indicate that a parallel algorithm's execution may be vectorized, e.g., executed on a single thread using instructions that operate on multiple data items.
During the execution of a parallel algorithm with the execution​::​unsequenced_policy policy, if the invocation of an element access function exits via an exception, terminate is invoked ([except.terminate]).

26.3.6.7 Execution policy objects [execpol.objects]

inline constexpr execution::sequenced_policy execution::seq{ unspecified }; inline constexpr execution::parallel_policy execution::par{ unspecified }; inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ unspecified }; inline constexpr execution::unsequenced_policy execution::unseq{ unspecified };
The header <execution> declares global objects associated with each type of execution policy.

26.4 Header <algorithm> synopsis [algorithm.syn]

#include <initializer_list> // see [initializer.list.syn] namespace std { namespace ranges { // [algorithms.results], algorithm result types template<class I, class F> struct in_fun_result; template<class I1, class I2> struct in_in_result; template<class I, class O> struct in_out_result; template<class I1, class I2, class O> struct in_in_out_result; template<class I, class O1, class O2> struct in_out_out_result; template<class T> struct min_max_result; template<class I> struct in_found_result; template<class I, class T> struct in_value_result; template<class O, class T> struct out_value_result; } // [alg.nonmodifying], non-modifying sequence operations // [alg.all.of], all of template<class InputIterator, class Predicate> constexpr bool all_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool all_of(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool all_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool all_of(R&& r, Pred pred, Proj proj = {}); } // [alg.any.of], any of template<class InputIterator, class Predicate> constexpr bool any_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool any_of(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool any_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool any_of(R&& r, Pred pred, Proj proj = {}); } // [alg.none.of], none of template<class InputIterator, class Predicate> constexpr bool none_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool none_of(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool none_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool none_of(R&& r, Pred pred, Proj proj = {}); } // [alg.contains], contains namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr bool contains(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr bool contains(R&& r, const T& value, Proj proj = {}); template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool contains_subrange(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool contains_subrange(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.foreach], for each template<class InputIterator, class Function> constexpr Function for_each(InputIterator first, InputIterator last, Function f); template<class ExecutionPolicy, class ForwardIterator, class Function> void for_each(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Function f); namespace ranges { template<class I, class F> using for_each_result = in_fun_result<I, F>; template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirectly_unary_invocable<projected<I, Proj>> Fun> constexpr for_each_result<I, Fun> for_each(I first, S last, Fun f, Proj proj = {}); template<input_range R, class Proj = identity, indirectly_unary_invocable<projected<iterator_t<R>, Proj>> Fun> constexpr for_each_result<borrowed_iterator_t<R>, Fun> for_each(R&& r, Fun f, Proj proj = {}); } template<class InputIterator, class Size, class Function> constexpr InputIterator for_each_n(InputIterator first, Size n, Function f); template<class ExecutionPolicy, class ForwardIterator, class Size, class Function> ForwardIterator for_each_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, Function f); namespace ranges { template<class I, class F> using for_each_n_result = in_fun_result<I, F>; template<input_iterator I, class Proj = identity, indirectly_unary_invocable<projected<I, Proj>> Fun> constexpr for_each_n_result<I, Fun> for_each_n(I first, iter_difference_t<I> n, Fun f, Proj proj = {}); } // [alg.find], find template<class InputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator find(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& value); template<class InputIterator, class Predicate> constexpr InputIterator find_if(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator find_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); template<class InputIterator, class Predicate> constexpr InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator find_if_not(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr I find(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_iterator_t<R> find(R&& r, const T& value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I find_if(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> find_if(R&& r, Pred pred, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I find_if_not(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> find_if_not(R&& r, Pred pred, Proj proj = {}); } // [alg.find.last], find last namespace ranges { template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr subrange<I> find_last(I first, S last, const T& value, Proj proj = {}); template<forward_range R, class T, class Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_subrange_t<R> find_last(R&& r, const T& value, Proj proj = {}); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> find_last_if(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_subrange_t<R> find_last_if(R&& r, Pred pred, Proj proj = {}); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> find_last_if_not(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_subrange_t<R> find_last_if_not(R&& r, Pred pred, Proj proj = {}); } // [alg.find.end], find end template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 find_end(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 find_end(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr subrange<I1> find_end(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_subrange_t<R1> find_end(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.find.first.of], find first template<class InputIterator, class ForwardIterator> constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2); template<class InputIterator, class ForwardIterator, class BinaryPredicate> constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 find_first_of(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 find_first_of(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr I1 find_first_of(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_iterator_t<R1> find_first_of(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.adjacent.find], adjacent find template<class ForwardIterator> constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class BinaryPredicate> constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator adjacent_find(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> ForwardIterator adjacent_find(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, BinaryPredicate pred); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_binary_predicate<projected<I, Proj>, projected<I, Proj>> Pred = ranges::equal_to> constexpr I adjacent_find(I first, S last, Pred pred = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_binary_predicate<projected<iterator_t<R>, Proj>, projected<iterator_t<R>, Proj>> Pred = ranges::equal_to> constexpr borrowed_iterator_t<R> adjacent_find(R&& r, Pred pred = {}, Proj proj = {}); } // [alg.count], count template<class InputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr typename iterator_traits<InputIterator>::difference_type count(InputIterator first, InputIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<InputIterator>::value_type> typename iterator_traits<ForwardIterator>::difference_type count(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& value); template<class InputIterator, class Predicate> constexpr typename iterator_traits<InputIterator>::difference_type count_if(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> typename iterator_traits<ForwardIterator>::difference_type count_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr iter_difference_t<I> count(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr range_difference_t<R> count(R&& r, const T& value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr iter_difference_t<I> count_if(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr range_difference_t<R> count_if(R&& r, Pred pred, Proj proj = {}); } // [alg.mismatch], mismatch template<class InputIterator1, class InputIterator2> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template<class InputIterator1, class InputIterator2> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<class I1, class I2> using mismatch_result = in_in_result<I1, I2>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr mismatch_result<I1, I2> mismatch(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.equal], equal template<class InputIterator1, class InputIterator2> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template<class InputIterator1, class InputIterator2> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool equal(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> bool equal(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool equal(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> bool equal(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool equal(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool equal(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.is.permutation], is permutation template<class ForwardIterator1, class ForwardIterator2> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class ForwardIterator1, class ForwardIterator2> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<I1, Proj1>, projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool is_permutation(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool is_permutation(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.search], search template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); namespace ranges { template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr subrange<I1> search(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_subrange_t<R1> search(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); template<class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator search_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Size count, const T& value); template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_comparable<I, const T*, Pred, Proj> constexpr subrange<I> search_n(I first, S last, iter_difference_t<I> count, const T& value, Pred pred = {}, Proj proj = {}); template<forward_range R, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_comparable<iterator_t<R>, const T*, Pred, Proj> constexpr borrowed_subrange_t<R> search_n(R&& r, range_difference_t<R> count, const T& value, Pred pred = {}, Proj proj = {}); } template<class ForwardIterator, class Searcher> constexpr ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher& searcher); namespace ranges { // [alg.starts.with], starts with template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool starts_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool starts_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // [alg.ends.with], ends with template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires (forward_iterator<I1> || sized_sentinel_for<S1, I1>) && (forward_iterator<I2> || sized_sentinel_for<S2, I2>) && indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ends_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires (forward_range<R1> || sized_range<R1>) && (forward_range<R2> || sized_range<R2>) && indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ends_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // [alg.fold], fold template<class F> class flipped { // exposition only F f; // exposition only public: template<class T, class U> requires invocable<F&, U, T> invoke_result_t<F&, U, T> operator()(T&&, U&&); }; template<class F, class T, class I, class U> concept indirectly-binary-left-foldable-impl = // exposition only movable<T> && movable<U> && convertible_to<T, U> && invocable<F&, U, iter_reference_t<I>> && assignable_from<U&, invoke_result_t<F&, U, iter_reference_t<I>>>; template<class F, class T, class I> concept indirectly-binary-left-foldable = // exposition only copy_constructible<F> && indirectly_readable<I> && invocable<F&, T, iter_reference_t<I>> && convertible_to<invoke_result_t<F&, T, iter_reference_t<I>>, decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>> && indirectly-binary-left-foldable-impl<F, T, I, decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>; template<class F, class T, class I> concept indirectly-binary-right-foldable = // exposition only indirectly-binary-left-foldable<flipped<F>, T, I>; template<input_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-left-foldable<T, I> F> constexpr auto fold_left(I first, S last, T init, F f); template<input_range R, class T = range_value_t<R>, indirectly-binary-left-foldable<T, iterator_t<R>> F> constexpr auto fold_left(R&& r, T init, F f); template<input_iterator I, sentinel_for<I> S, indirectly-binary-left-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr auto fold_left_first(I first, S last, F f); template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr auto fold_left_first(R&& r, F f); template<bidirectional_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-right-foldable<T, I> F> constexpr auto fold_right(I first, S last, T init, F f); template<bidirectional_range R, class T = range_value_t<R>, indirectly-binary-right-foldable<T, iterator_t<R>> F> constexpr auto fold_right(R&& r, T init, F f); template<bidirectional_iterator I, sentinel_for<I> S, indirectly-binary-right-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr auto fold_right_last(I first, S last, F f); template<bidirectional_range R, indirectly-binary-right-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr auto fold_right_last(R&& r, F f); template<class I, class T> using fold_left_with_iter_result = in_value_result<I, T>; template<class I, class T> using fold_left_first_with_iter_result = in_value_result<I, T>; template<input_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-left-foldable<T, I> F> constexpr see below fold_left_with_iter(I first, S last, T init, F f); template<input_range R, class T = range_value_t<R>, indirectly-binary-left-foldable<T, iterator_t<R>> F> constexpr see below fold_left_with_iter(R&& r, T init, F f); template<input_iterator I, sentinel_for<I> S, indirectly-binary-left-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr see below fold_left_first_with_iter(I first, S last, F f); template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr see below fold_left_first_with_iter(R&& r, F f); } // [alg.modifying.operations], mutating sequence operations // [alg.copy], copy template<class InputIterator, class OutputIterator> constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template<class I, class O> using copy_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr copy_result<I, O> copy(I first, S last, O result); template<input_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr copy_result<borrowed_iterator_t<R>, O> copy(R&& r, O result); } template<class InputIterator, class Size, class OutputIterator> constexpr OutputIterator copy_n(InputIterator first, Size n, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class Size, class ForwardIterator2> ForwardIterator2 copy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, Size n, ForwardIterator2 result); namespace ranges { template<class I, class O> using copy_n_result = in_out_result<I, O>; template<input_iterator I, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr copy_n_result<I, O> copy_n(I first, iter_difference_t<I> n, O result); } template<class InputIterator, class OutputIterator, class Predicate> constexpr OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate> ForwardIterator2 copy_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); namespace ranges { template<class I, class O> using copy_if_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr copy_if_result<I, O> copy_if(I first, S last, O result, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr copy_if_result<borrowed_iterator_t<R>, O> copy_if(R&& r, O result, Pred pred, Proj proj = {}); } template<class BidirectionalIterator1, class BidirectionalIterator2> constexpr BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); namespace ranges { template<class I1, class I2> using copy_backward_result = in_out_result<I1, I2>; template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> requires indirectly_copyable<I1, I2> constexpr copy_backward_result<I1, I2> copy_backward(I1 first, S1 last, I2 result); template<bidirectional_range R, bidirectional_iterator I> requires indirectly_copyable<iterator_t<R>, I> constexpr copy_backward_result<borrowed_iterator_t<R>, I> copy_backward(R&& r, I result); } // [alg.move], move template<class InputIterator, class OutputIterator> constexpr OutputIterator move(InputIterator first, InputIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 move(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template<class I, class O> using move_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_movable<I, O> constexpr move_result<I, O> move(I first, S last, O result); template<input_range R, weakly_incrementable O> requires indirectly_movable<iterator_t<R>, O> constexpr move_result<borrowed_iterator_t<R>, O> move(R&& r, O result); } template<class BidirectionalIterator1, class BidirectionalIterator2> constexpr BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); namespace ranges { template<class I1, class I2> using move_backward_result = in_out_result<I1, I2>; template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> requires indirectly_movable<I1, I2> constexpr move_backward_result<I1, I2> move_backward(I1 first, S1 last, I2 result); template<bidirectional_range R, bidirectional_iterator I> requires indirectly_movable<iterator_t<R>, I> constexpr move_backward_result<borrowed_iterator_t<R>, I> move_backward(R&& r, I result); } // [alg.swap], swap template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); namespace ranges { template<class I1, class I2> using swap_ranges_result = in_in_result<I1, I2>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2> requires indirectly_swappable<I1, I2> constexpr swap_ranges_result<I1, I2> swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2); template<input_range R1, input_range R2> requires indirectly_swappable<iterator_t<R1>, iterator_t<R2>> constexpr swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> swap_ranges(R1&& r1, R2&& r2); } template<class ForwardIterator1, class ForwardIterator2> constexpr void iter_swap(ForwardIterator1 a, ForwardIterator2 b); // [alg.transform], transform template<class InputIterator, class OutputIterator, class UnaryOperation> constexpr OutputIterator transform(InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op); template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation> constexpr OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class UnaryOperation> ForwardIterator2 transform(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 result, UnaryOperation op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class BinaryOperation> ForwardIterator transform(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation binary_op); namespace ranges { template<class I, class O> using unary_transform_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<I, Proj>>> constexpr unary_transform_result<I, O> transform(I first1, S last1, O result, F op, Proj proj = {}); template<input_range R, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<iterator_t<R>, Proj>>> constexpr unary_transform_result<borrowed_iterator_t<R>, O> transform(R&& r, O result, F op, Proj proj = {}); template<class I1, class I2, class O> using binary_transform_result = in_in_out_result<I1, I2, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, class Proj2 = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<I1, Proj1>, projected<I2, Proj2>>> constexpr binary_transform_result<I1, I2, O> transform(I1 first1, S1 last1, I2 first2, S2 last2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, class Proj2 = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>> constexpr binary_transform_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> transform(R1&& r1, R2&& r2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.replace], replace template<class ForwardIterator, class T> constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> void replace(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template<class ForwardIterator, class Predicate, class T = iterator_traits<ForwardIterator>::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); template<class ExecutionPolicy, class ForwardIterator, class Predicate, class T = iterator_traits<ForwardIterator>::value_type> void replace_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T1 = projected_value_t<I, Proj>, class T2 = T1> requires indirectly_writable<I, const T2&> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*> constexpr I replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_range R, class Proj = identity, class T1 = projected_value_t<iterator_t<R>, Proj>, class T2 = T1> requires indirectly_writable<iterator_t<R>, const T2&> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T1*> constexpr borrowed_iterator_t<R> replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_writable<I, const T&> constexpr I replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_writable<iterator_t<R>, const T&> constexpr borrowed_iterator_t<R> replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); } template<class InputIterator, class OutputIterator, class T> constexpr OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> ForwardIterator2 replace_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value); template<class InputIterator, class OutputIterator, class Predicate, class T = iterator_traits<OutputIterator>::value_type> constexpr OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate, class T = iterator_traits<ForwardIterator2>::value_type> ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred, const T& new_value); namespace ranges { template<class I, class O> using replace_copy_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, class O, class Proj = identity, class T1 = projected_value_t<I, Proj>, class T2 = iter_value_t<O>> requires indirectly_copyable<I, O> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*> && output_iterator<O, const T2&> constexpr replace_copy_result<I, O> replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_range R, class O, class Proj = identity, class T1 = projected_value_t<iterator_t<R>, Proj>, class T2 = iter_value_t<O>> requires indirectly_copyable<iterator_t<R>, O> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T1*> && output_iterator<O, const T2&> constexpr replace_copy_result<borrowed_iterator_t<R>, O> replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); template<class I, class O> using replace_copy_if_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, class O, class T = iter_value_t<O> class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> && output_iterator<O, const T&> constexpr replace_copy_if_result<I, O> replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); template<input_range R, class O, class T = iter_value_t<O>, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> && output_iterator<O, const T&> constexpr replace_copy_if_result<borrowed_iterator_t<R>, O> replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {}); } // [alg.fill], fill template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> void fill(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& value); template<class OutputIterator, class Size, class T = iterator_traits<OutputIterator>::value_type> constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); // freestanding template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, const T& value); namespace ranges { template<class O, sentinel_for<O> S, class T = iter_value_t<O>> requires output_iterator<O, const T&> constexpr O fill(O first, S last, const T& value); template<class R, class T = range_value_t<R>> requires output_range<R, const T&> constexpr borrowed_iterator_t<R> fill(R&& r, const T& value); template<class O, class T = iter_value_t<O>> requires output_iterator<O, const T&> constexpr O fill_n(O first, iter_difference_t<O> n, const T& value); } // [alg.generate], generate template<class ForwardIterator, class Generator> constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Generator> void generate(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Generator gen); template<class OutputIterator, class Size, class Generator> constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Size, class Generator> ForwardIterator generate_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, Generator gen); namespace ranges { template<input_or_output_iterator O, sentinel_for<O> S, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> constexpr O generate(O first, S last, F gen); template<class R, copy_constructible F> requires invocable<F&> && output_range<R, invoke_result_t<F&>> constexpr borrowed_iterator_t<R> generate(R&& r, F gen); template<input_or_output_iterator O, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> constexpr O generate_n(O first, iter_difference_t<O> n, F gen); } // [alg.remove], remove template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator remove(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class Predicate> constexpr ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator remove_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<permutable I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr subrange<I> remove(I first, S last, const T& value, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires permutable<iterator_t<R>> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_subrange_t<R> remove(R&& r, const T& value, Proj proj = {}); template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> remove_if(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> remove_if(R&& r, Pred pred, Proj proj = {}); } template<class InputIterator, class OutputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T = iterator_traits<ForwardIterator1>::value_type> ForwardIterator2 remove_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value); template<class InputIterator, class OutputIterator, class Predicate> constexpr OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate> ForwardIterator2 remove_copy_if(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); namespace ranges { template<class I, class O> using remove_copy_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_copyable<I, O> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr remove_copy_result<I, O> remove_copy(I first, S last, O result, const T& value, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirectly_copyable<iterator_t<R>, O> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr remove_copy_result<borrowed_iterator_t<R>, O> remove_copy(R&& r, O result, const T& value, Proj proj = {}); template<class I, class O> using remove_copy_if_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr remove_copy_if_result<I, O> remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr remove_copy_if_result<borrowed_iterator_t<R>, O> remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); } // [alg.unique], unique template<class ForwardIterator> constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class BinaryPredicate> constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator unique(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> ForwardIterator unique(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, BinaryPredicate pred); namespace ranges { template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> constexpr subrange<I> unique(I first, S last, C comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> unique(R&& r, C comp = {}, Proj proj = {}); } template<class InputIterator, class OutputIterator> constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); template<class InputIterator, class OutputIterator, class BinaryPredicate> constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 unique_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator2 unique_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred); namespace ranges { template<class I, class O> using unique_copy_result = in_out_result<I, O>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> requires indirectly_copyable<I, O> && (forward_iterator<I> || (input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>) || indirectly_copyable_storable<I, O>) constexpr unique_copy_result<I, O> unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires indirectly_copyable<iterator_t<R>, O> && (forward_iterator<iterator_t<R>> || (input_iterator<O> && same_as<range_value_t<R>, iter_value_t<O>>) || indirectly_copyable_storable<iterator_t<R>, O>) constexpr unique_copy_result<borrowed_iterator_t<R>, O> unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); } // [alg.reverse], reverse template<class BidirectionalIterator> constexpr void reverse(BidirectionalIterator first, BidirectionalIterator last); template<class ExecutionPolicy, class BidirectionalIterator> void reverse(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] BidirectionalIterator first, BidirectionalIterator last); namespace ranges { template<bidirectional_iterator I, sentinel_for<I> S> requires permutable<I> constexpr I reverse(I first, S last); template<bidirectional_range R> requires permutable<iterator_t<R>> constexpr borrowed_iterator_t<R> reverse(R&& r); } template<class BidirectionalIterator, class OutputIterator> constexpr OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result); template<class ExecutionPolicy, class BidirectionalIterator, class ForwardIterator> ForwardIterator reverse_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] BidirectionalIterator first, BidirectionalIterator last, ForwardIterator result); namespace ranges { template<class I, class O> using reverse_copy_result = in_out_result<I, O>; template<bidirectional_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr reverse_copy_result<I, O> reverse_copy(I first, S last, O result); template<bidirectional_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr reverse_copy_result<borrowed_iterator_t<R>, O> reverse_copy(R&& r, O result); } // [alg.rotate], rotate template<class ForwardIterator> constexpr ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator rotate(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator middle, ForwardIterator last); namespace ranges { template<permutable I, sentinel_for<I> S> constexpr subrange<I> rotate(I first, I middle, S last); template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> rotate(R&& r, iterator_t<R> middle); } template<class ForwardIterator, class OutputIterator> constexpr OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 rotate_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result); namespace ranges { template<class I, class O> using rotate_copy_result = in_out_result<I, O>; template<forward_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr rotate_copy_result<I, O> rotate_copy(I first, I middle, S last, O result); template<forward_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr rotate_copy_result<borrowed_iterator_t<R>, O> rotate_copy(R&& r, iterator_t<R> middle, O result); } // [alg.random.sample], sample template<class PopulationIterator, class SampleIterator, class Distance, class UniformRandomBitGenerator> SampleIterator sample(PopulationIterator first, PopulationIterator last, SampleIterator out, Distance n, UniformRandomBitGenerator&& g); namespace ranges { template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Gen> requires (forward_iterator<I> || random_access_iterator<O>) && indirectly_copyable<I, O> && uniform_random_bit_generator<remove_reference_t<Gen>> O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); template<input_range R, weakly_incrementable O, class Gen> requires (forward_range<R> || random_access_iterator<O>) && indirectly_copyable<iterator_t<R>, O> && uniform_random_bit_generator<remove_reference_t<Gen>> O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); } // [alg.random.shuffle], shuffle template<class RandomAccessIterator, class UniformRandomBitGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomBitGenerator&& g); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Gen> requires permutable<I> && uniform_random_bit_generator<remove_reference_t<Gen>> I shuffle(I first, S last, Gen&& g); template<random_access_range R, class Gen> requires permutable<iterator_t<R>> && uniform_random_bit_generator<remove_reference_t<Gen>> borrowed_iterator_t<R> shuffle(R&& r, Gen&& g); } // [alg.shift], shift template<class ForwardIterator> constexpr ForwardIterator shift_left(ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator shift_left(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); namespace ranges { template<permutable I, sentinel_for<I> S> constexpr subrange<I> shift_left(I first, S last, iter_difference_t<I> n); template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> shift_left(R&& r, range_difference_t<R> n); } template<class ForwardIterator> constexpr ForwardIterator shift_right(ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator shift_right(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); namespace ranges { template<permutable I, sentinel_for<I> S> constexpr subrange<I> shift_right(I first, S last, iter_difference_t<I> n); template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> shift_right(R&& r, range_difference_t<R> n); } // [alg.sorting], sorting and related operations // [alg.sort], sorting template<class RandomAccessIterator> constexpr void sort(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> void sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I sort(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> sort(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> void stable_sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void stable_sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> stable_sort(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> void partial_sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void partial_sort(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I partial_sort(I first, I middle, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> partial_sort(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {}); } template<class InputIterator, class RandomAccessIterator> constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template<class InputIterator, class RandomAccessIterator, class Compare> constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class RandomAccessIterator> RandomAccessIterator partial_sort_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template<class ExecutionPolicy, class ForwardIterator, class RandomAccessIterator, class Compare> RandomAccessIterator partial_sort_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); namespace ranges { template<class I, class O> using partial_sort_copy_result = in_out_result<I, O>; template<input_iterator I1, sentinel_for<I1> S1, random_access_iterator I2, sentinel_for<I2> S2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires indirectly_copyable<I1, I2> && sortable<I2, Comp, Proj2> && indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>> constexpr partial_sort_copy_result<I1, I2> partial_sort_copy(I1 first, S1 last, I2 result_first, S2 result_last, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, random_access_range R2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires indirectly_copyable<iterator_t<R1>, iterator_t<R2>> && sortable<iterator_t<R2>, Comp, Proj2> && indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> constexpr partial_sort_copy_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class ForwardIterator> constexpr bool is_sorted(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator> bool is_sorted(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class Compare> bool is_sorted(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr bool is_sorted(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool is_sorted(R&& r, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator> constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator is_sorted_until(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator is_sorted_until(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I is_sorted_until(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> is_sorted_until(R&& r, Comp comp = {}, Proj proj = {}); } // [alg.nth.element], Nth element template<class RandomAccessIterator> constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> void nth_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void nth_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> nth_element(R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {}); } // [alg.binary.search], binary search template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr I lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj> indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr subrange<I> equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t<R> equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr bool binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr bool binary_search(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool binary_search(R&& r, const T& value, Comp comp = {}, Proj proj = {}); } // [alg.partitions], partitions template<class InputIterator, class Predicate> constexpr bool is_partitioned(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool is_partitioned(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool is_partitioned(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool is_partitioned(R&& r, Pred pred, Proj proj = {}); } template<class ForwardIterator, class Predicate> constexpr ForwardIterator partition(ForwardIterator first, ForwardIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator partition(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> partition(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> partition(R&& r, Pred pred, Proj proj = {}); } template<class BidirectionalIterator, class Predicate> constexpr BidirectionalIterator stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); template<class ExecutionPolicy, class BidirectionalIterator, class Predicate> BidirectionalIterator stable_partition(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] BidirectionalIterator first, BidirectionalIterator last, Predicate pred); namespace ranges { template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires permutable<I> constexpr subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); template<bidirectional_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); } template<class InputIterator, class OutputIterator1, class OutputIterator2, class Predicate> constexpr pair<OutputIterator1, OutputIterator2> partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class ForwardIterator1, class ForwardIterator2, class Predicate> pair<ForwardIterator1, ForwardIterator2> partition_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, Predicate pred); namespace ranges { template<class I, class O1, class O2> using partition_copy_result = in_out_out_result<I, O1, O2>; template<input_iterator I, sentinel_for<I> S, weakly_incrementable O1, weakly_incrementable O2, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O1> && indirectly_copyable<I, O2> constexpr partition_copy_result<I, O1, O2> partition_copy(I first, S last, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O1, weakly_incrementable O2, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O1> && indirectly_copyable<iterator_t<R>, O2> constexpr partition_copy_result<borrowed_iterator_t<R>, O1, O2> partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); } template<class ForwardIterator, class Predicate> constexpr ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, Predicate pred); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I partition_point(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> partition_point(R&& r, Pred pred, Proj proj = {}); } // [alg.merge], merge template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator merge(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator merge(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template<class I1, class I2, class O> using merge_result = in_in_out_result<I1, I2, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr merge_result<I1, I2, O> merge(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr merge_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> merge(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class BidirectionalIterator> constexpr void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template<class ExecutionPolicy, class BidirectionalIterator> void inplace_merge(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template<class ExecutionPolicy, class BidirectionalIterator, class Compare> void inplace_merge(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); namespace ranges { template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {}); } // [alg.set.operations], set operations template<class InputIterator1, class InputIterator2> constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class InputIterator1, class InputIterator2, class Compare> constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool includes(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> bool includes(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); namespace ranges { template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = ranges::less> constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_union(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_union(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template<class I1, class I2, class O> using set_union_result = in_in_out_result<I1, I2, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr set_union_result<I1, I2, O> set_union(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr set_union_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> set_union(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_intersection(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_intersection(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template<class I1, class I2, class O> using set_intersection_result = in_in_out_result<I1, I2, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr set_intersection_result<I1, I2, O> set_intersection(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr set_intersection_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> set_intersection(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template<class I, class O> using set_difference_result = in_out_result<I, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr set_difference_result<I1, O> set_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr set_difference_result<borrowed_iterator_t<R1>, O> set_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_symmetric_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_symmetric_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); namespace ranges { template<class I1, class I2, class O> using set_symmetric_difference_result = in_in_out_result<I1, I2, O>; template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr set_symmetric_difference_result<I1, I2, O> set_symmetric_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr set_symmetric_difference_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> set_symmetric_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.heap.operations], heap operations template<class RandomAccessIterator> constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I push_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> push_heap(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I pop_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> pop_heap(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I make_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> make_heap(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I sort_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> sort_heap(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> bool is_heap(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> bool is_heap(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr bool is_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool is_heap(R&& r, Comp comp = {}, Proj proj = {}); } template<class RandomAccessIterator> constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator> RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] RandomAccessIterator first, RandomAccessIterator last, Compare comp); namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I is_heap_until(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> is_heap_until(R&& r, Comp comp = {}, Proj proj = {}); } // [alg.min.max], minimum and maximum template<class T> constexpr const T& min(const T& a, const T& b); template<class T, class Compare> constexpr const T& min(const T& a, const T& b, Compare comp); template<class T> constexpr T min(initializer_list<T> t); template<class T, class Compare> constexpr T min(initializer_list<T> t, Compare comp); namespace ranges { template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr T min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> min(R&& r, Comp comp = {}, Proj proj = {}); } template<class T> constexpr const T& max(const T& a, const T& b); template<class T, class Compare> constexpr const T& max(const T& a, const T& b, Compare comp); template<class T> constexpr T max(initializer_list<T> t); template<class T, class Compare> constexpr T max(initializer_list<T> t, Compare comp); namespace ranges { template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& max(const T& a, const T& b, Comp comp = {}, Proj proj = {}); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr T max(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> max(R&& r, Comp comp = {}, Proj proj = {}); } template<class T> constexpr pair<const T&, const T&> minmax(const T& a, const T& b); template<class T, class Compare> constexpr pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp); template<class T> constexpr pair<T, T> minmax(initializer_list<T> t); template<class T, class Compare> constexpr pair<T, T> minmax(initializer_list<T> t, Compare comp); namespace ranges { template<class T> using minmax_result = min_max_result<T>; template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr minmax_result<const T&> minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr minmax_result<T> minmax(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr minmax_result<range_value_t<R>> minmax(R&& r, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator min_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator min_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I min_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> min_element(R&& r, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator max_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator max_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I max_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> max_element(R&& r, Comp comp = {}, Proj proj = {}); } template<class ForwardIterator> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator> pair<ForwardIterator, ForwardIterator> minmax_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class Compare> pair<ForwardIterator, ForwardIterator> minmax_element(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, Compare comp); namespace ranges { template<class I> using minmax_element_result = min_max_result<I>; template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr minmax_element_result<I> minmax_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr minmax_element_result<borrowed_iterator_t<R>> minmax_element(R&& r, Comp comp = {}, Proj proj = {}); } // [alg.clamp], bounded value template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi); template<class T, class Compare> constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp); namespace ranges { template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& clamp(const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {}); } // [alg.lex.comparison], lexicographical comparison template<class InputIterator1, class InputIterator2> constexpr bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class InputIterator1, class InputIterator2, class Compare> constexpr bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool lexicographical_compare(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> bool lexicographical_compare(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); namespace ranges { template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = ranges::less> constexpr bool lexicographical_compare(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool lexicographical_compare(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); } // [alg.three.way], three-way comparison algorithms template<class InputIterator1, class InputIterator2, class Cmp> constexpr auto lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, Cmp comp) -> decltype(comp(*b1, *b2)); template<class InputIterator1, class InputIterator2> constexpr auto lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2); // [alg.permutation.generators], permutations template<class BidirectionalIterator> constexpr bool next_permutation(BidirectionalIterator first, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp); namespace ranges { template<class I> using next_permutation_result = in_found_result<I>; template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr next_permutation_result<I> next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr next_permutation_result<borrowed_iterator_t<R>> next_permutation(R&& r, Comp comp = {}, Proj proj = {}); } template<class BidirectionalIterator> constexpr bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp); namespace ranges { template<class I> using prev_permutation_result = in_found_result<I>; template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr prev_permutation_result<I> prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr prev_permutation_result<borrowed_iterator_t<R>> prev_permutation(R&& r, Comp comp = {}, Proj proj = {}); } }

26.5 Algorithm result types [algorithms.results]

Each of the class templates specified in this subclause has the template parameters, data members, and special members specified below, and has no base classes or members other than those specified.
namespace std::ranges { template<class I, class F> struct in_fun_result { [[no_unique_address]] I in; [[no_unique_address]] F fun; template<class I2, class F2> requires convertible_to<const I&, I2> && convertible_to<const F&, F2> constexpr operator in_fun_result<I2, F2>() const & { return {in, fun}; } template<class I2, class F2> requires convertible_to<I, I2> && convertible_to<F, F2> constexpr operator in_fun_result<I2, F2>() && { return {std::move(in), std::move(fun)}; } }; template<class I1, class I2> struct in_in_result { [[no_unique_address]] I1 in1; [[no_unique_address]] I2 in2; template<class II1, class II2> requires convertible_to<const I1&, II1> && convertible_to<const I2&, II2> constexpr operator in_in_result<II1, II2>() const & { return {in1, in2}; } template<class II1, class II2> requires convertible_to<I1, II1> && convertible_to<I2, II2> constexpr operator in_in_result<II1, II2>() && { return {std::move(in1), std::move(in2)}; } }; template<class I, class O> struct in_out_result { [[no_unique_address]] I in; [[no_unique_address]] O out; template<class I2, class O2> requires convertible_to<const I&, I2> && convertible_to<const O&, O2> constexpr operator in_out_result<I2, O2>() const & { return {in, out}; } template<class I2, class O2> requires convertible_to<I, I2> && convertible_to<O, O2> constexpr operator in_out_result<I2, O2>() && { return {std::move(in), std::move(out)}; } }; template<class I1, class I2, class O> struct in_in_out_result { [[no_unique_address]] I1 in1; [[no_unique_address]] I2 in2; [[no_unique_address]] O out; template<class II1, class II2, class OO> requires convertible_to<const I1&, II1> && convertible_to<const I2&, II2> && convertible_to<const O&, OO> constexpr operator in_in_out_result<II1, II2, OO>() const & { return {in1, in2, out}; } template<class II1, class II2, class OO> requires convertible_to<I1, II1> && convertible_to<I2, II2> && convertible_to<O, OO> constexpr operator in_in_out_result<II1, II2, OO>() && { return {std::move(in1), std::move(in2), std::move(out)}; } }; template<class I, class O1, class O2> struct in_out_out_result { [[no_unique_address]] I in; [[no_unique_address]] O1 out1; [[no_unique_address]] O2 out2; template<class II, class OO1, class OO2> requires convertible_to<const I&, II> && convertible_to<const O1&, OO1> && convertible_to<const O2&, OO2> constexpr operator in_out_out_result<II, OO1, OO2>() const & { return {in, out1, out2}; } template<class II, class OO1, class OO2> requires convertible_to<I, II> && convertible_to<O1, OO1> && convertible_to<O2, OO2> constexpr operator in_out_out_result<II, OO1, OO2>() && { return {std::move(in), std::move(out1), std::move(out2)}; } }; template<class T> struct min_max_result { [[no_unique_address]] T min; [[no_unique_address]] T max; template<class T2> requires convertible_to<const T&, T2> constexpr operator min_max_result<T2>() const & { return {min, max}; } template<class T2> requires convertible_to<T, T2> constexpr operator min_max_result<T2>() && { return {std::move(min), std::move(max)}; } }; template<class I> struct in_found_result { [[no_unique_address]] I in; bool found; template<class I2> requires convertible_to<const I&, I2> constexpr operator in_found_result<I2>() const & { return {in, found}; } template<class I2> requires convertible_to<I, I2> constexpr operator in_found_result<I2>() && { return {std::move(in), found}; } }; template<class I, class T> struct in_value_result { [[no_unique_address]] I in; [[no_unique_address]] T value; template<class I2, class T2> requires convertible_to<const I&, I2> && convertible_to<const T&, T2> constexpr operator in_value_result<I2, T2>() const & { return {in, value}; } template<class I2, class T2> requires convertible_to<I, I2> && convertible_to<T, T2> constexpr operator in_value_result<I2, T2>() && { return {std::move(in), std::move(value)}; } }; template<class O, class T> struct out_value_result { [[no_unique_address]] O out; [[no_unique_address]] T value; template<class O2, class T2> requires convertible_to<const O&, O2> && convertible_to<const T&, T2> constexpr operator out_value_result<O2, T2>() const & { return {out, value}; } template<class O2, class T2> requires convertible_to<O, O2> && convertible_to<T, T2> constexpr operator out_value_result<O2, T2>() && { return {std::move(out), std::move(value)}; } }; }

26.6 Non-modifying sequence operations [alg.nonmodifying]

26.6.1 All of [alg.all.of]

template<class InputIterator, class Predicate> constexpr bool all_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool all_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool ranges::all_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool ranges::all_of(R&& r, Pred pred, Proj proj = {});
Let E be:
  • pred(*i) for the overloads in namespace std;
  • invoke(pred, invoke(proj, *i)) for the overloads in namespace ranges.
Returns: false if E is false for some iterator i in the range [first, last), and true otherwise.
Complexity: At most last - first applications of the predicate and any projection.

26.6.2 Any of [alg.any.of]

template<class InputIterator, class Predicate> constexpr bool any_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool any_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool ranges::any_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool ranges::any_of(R&& r, Pred pred, Proj proj = {});
Let E be:
  • pred(*i) for the overloads in namespace std;
  • invoke(pred, invoke(proj, *i)) for the overloads in namespace ranges.
Returns: true if E is true for some iterator i in the range [first, last), and false otherwise.
Complexity: At most last - first applications of the predicate and any projection.

26.6.3 None of [alg.none.of]

template<class InputIterator, class Predicate> constexpr bool none_of(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool none_of(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool ranges::none_of(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {});
Let E be:
  • pred(*i) for the overloads in namespace std;
  • invoke(pred, invoke(proj, *i)) for the overloads in namespace ranges.
Returns: false if E is true for some iterator i in the range [first, last), and true otherwise.
Complexity: At most last - first applications of the predicate and any projection.

26.6.4 Contains [alg.contains]

template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr bool ranges::contains(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr bool ranges::contains(R&& r, const T& value, Proj proj = {});
Returns: ranges​::​find(std​::​move(first), last, value, proj) != last.
template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ranges::contains_subrange(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ranges::contains_subrange(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Returns: first2 == last2 || !ranges​::​search(first1, last1, first2, last2, pred, proj1, proj2).empty().

26.6.5 For each [alg.foreach]

template<class InputIterator, class Function> constexpr Function for_each(InputIterator first, InputIterator last, Function f);
Preconditions: Function meets the Cpp17MoveConstructible requirements (Table 31).
[Note 1: 
Function need not meet the requirements of Cpp17CopyConstructible (Table 32).
— end note]
Effects: Applies f to the result of dereferencing every iterator in the range [first, last), starting from first and proceeding to last - 1.
[Note 2: 
If the type of first meets the requirements of a mutable iterator, f can apply non-constant functions through the dereferenced iterator.
— end note]
Returns: f.
Complexity: Applies f exactly last - first times.
Remarks: If f returns a result, the result is ignored.
template<class ExecutionPolicy, class ForwardIterator, class Function> void for_each(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Function f);
Preconditions: Function meets the Cpp17CopyConstructible requirements.
Effects: Applies f to the result of dereferencing every iterator in the range [first, last).
[Note 3: 
If the type of first meets the requirements of a mutable iterator, f can apply non-constant functions through the dereferenced iterator.
— end note]
Complexity: Applies f exactly last - first times.
Remarks: If f returns a result, the result is ignored.
Implementations do not have the freedom granted under [algorithms.parallel.exec] to make arbitrary copies of elements from the input sequence.
[Note 4: 
Does not return a copy of its Function parameter, since parallelization often does not permit efficient state accumulation.
— end note]
template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirectly_unary_invocable<projected<I, Proj>> Fun> constexpr ranges::for_each_result<I, Fun> ranges::for_each(I first, S last, Fun f, Proj proj = {}); template<input_range R, class Proj = identity, indirectly_unary_invocable<projected<iterator_t<R>, Proj>> Fun> constexpr ranges::for_each_result<borrowed_iterator_t<R>, Fun> ranges::for_each(R&& r, Fun f, Proj proj = {});
Effects: Calls invoke(f, invoke(proj, *i)) for every iterator i in the range [first, last), starting from first and proceeding to last - 1.
[Note 5: 
If the result of invoke(proj, *i) is a mutable reference, f can apply non-constant functions.
— end note]
Returns: {last, std​::​move(f)}.
Complexity: Applies f and proj exactly last - first times.
Remarks: If f returns a result, the result is ignored.
[Note 6: 
The overloads in namespace ranges require Fun to model copy_constructible.
— end note]
template<class InputIterator, class Size, class Function> constexpr InputIterator for_each_n(InputIterator first, Size n, Function f);
Mandates: The type Size is convertible to an integral type ([conv.integral], [class.conv]).
Preconditions: n >= 0 is true.
Function meets the Cpp17MoveConstructible requirements.
[Note 7: 
Function need not meet the requirements of Cpp17CopyConstructible.
— end note]
Effects: Applies f to the result of dereferencing every iterator in the range [first, first + n) in order.
[Note 8: 
If the type of first meets the requirements of a mutable iterator, f can apply non-constant functions through the dereferenced iterator.
— end note]
Returns: first + n.
Remarks: If f returns a result, the result is ignored.
template<class ExecutionPolicy, class ForwardIterator, class Size, class Function> ForwardIterator for_each_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Function f);
Mandates: The type Size is convertible to an integral type ([conv.integral], [class.conv]).
Preconditions: n >= 0 is true.
Function meets the Cpp17CopyConstructible requirements.
Effects: Applies f to the result of dereferencing every iterator in the range [first, first + n).
[Note 9: 
If the type of first meets the requirements of a mutable iterator, f can apply non-constant functions through the dereferenced iterator.
— end note]
Returns: first + n.
Remarks: If f returns a result, the result is ignored.
Implementations do not have the freedom granted under [algorithms.parallel.exec] to make arbitrary copies of elements from the input sequence.
template<input_iterator I, class Proj = identity, indirectly_unary_invocable<projected<I, Proj>> Fun> constexpr ranges::for_each_n_result<I, Fun> ranges::for_each_n(I first, iter_difference_t<I> n, Fun f, Proj proj = {});
Preconditions: n >= 0 is true.
Effects: Calls invoke(f, invoke(proj, *i)) for every iterator i in the range [first, first + n) in order.
[Note 10: 
If the result of invoke(proj, *i) is a mutable reference, f can apply non-constant functions.
— end note]
Returns: {first + n, std​::​move(f)}.
Remarks: If f returns a result, the result is ignored.
[Note 11: 
The overload in namespace ranges requires Fun to model copy_constructible.
— end note]

26.6.6 Find [alg.find]

template<class InputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr InputIterator find(InputIterator first, InputIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); template<class InputIterator, class Predicate> constexpr InputIterator find_if(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator find_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<class InputIterator, class Predicate> constexpr InputIterator find_if_not(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator find_if_not(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr I ranges::find(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_iterator_t<R> ranges::find(R&& r, const T& value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I ranges::find_if(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> ranges::find_if(R&& r, Pred pred, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I ranges::find_if_not(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> ranges::find_if_not(R&& r, Pred pred, Proj proj = {});
Let E be:
  • *i == value for find;
  • pred(*i) != false for find_if;
  • pred(*i) == false for find_if_not;
  • bool(invoke(proj, *i) == value) for ranges​::​find;
  • bool(invoke(pred, invoke(proj, *i))) for ranges​::​find_if;
  • bool(!invoke(pred, invoke(proj, *i))) for ranges​::​find_if_not.
Returns: The first iterator i in the range [first, last) for which E is true.
Returns last if no such iterator is found.
Complexity: At most last - first applications of the corresponding predicate and any projection.

26.6.7 Find last [alg.find.last]

template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr subrange<I> ranges::find_last(I first, S last, const T& value, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_subrange_t<R> ranges::find_last(R&& r, const T& value, Proj proj = {}); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> ranges::find_last_if(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_subrange_t<R> ranges::find_last_if(R&& r, Pred pred, Proj proj = {}); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> ranges::find_last_if_not(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_subrange_t<R> ranges::find_last_if_not(R&& r, Pred pred, Proj proj = {});
Let E be:
  • bool(invoke(proj, *i) == value) for ranges​::​find_last;
  • bool(invoke(pred, invoke(proj, *i))) for ranges​::​find_last_if;
  • bool(!invoke(pred, invoke(proj, *i))) for ranges​::​find_last_if_not.
Returns: Let i be the last iterator in the range [first, last) for which E is true.
Returns {i, last}, or {last, last} if no such iterator is found.
Complexity: At most last - first applications of the corresponding predicate and projection.

26.6.8 Find end [alg.find.end]

template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 find_end(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr ForwardIterator1 find_end(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 find_end(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr subrange<I1> ranges::find_end(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_subrange_t<R1> ranges::find_end(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let:
  • pred be equal_to{} for the overloads with no parameter pred;
  • E be:
    • pred(*(i + n), *(first2 + n)) for the overloads in namespace std;
    • invoke(pred, invoke(proj1, *(i + n)), invoke(proj2, *(first2 + n))) for the overloads in namespace ranges;
  • i be last1 if [first2, last2) is empty, or if (last2 - first2) > (last1 - first1) is true, or if there is no iterator in the range [first1, last1 - (last2 - first2)) such that for every non-negative integer n < (last2 - first2), E is true.
    Otherwise i is the last such iterator in [first1, last1 - (last2 - first2)).
Returns:
  • i for the overloads in namespace std.
  • {i, i + (i == last1 ? 0 : last2 - first2)} for the overloads in namespace ranges.
Complexity: At most (last2 - first2) * (last1 - first1 - (last2 - first2) + 1) applications of the corresponding predicate and any projections.

26.6.9 Find first [alg.find.first.of]

template<class InputIterator, class ForwardIterator> constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class InputIterator, class ForwardIterator, class BinaryPredicate> constexpr InputIterator find_first_of(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 find_first_of(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr I1 ranges::find_first_of(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_iterator_t<R1> ranges::find_first_of(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let E be:
  • *i == *j for the overloads with no parameter pred;
  • pred(*i, *j) != false for the overloads with a parameter pred and no parameter proj1;
  • bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j))) for the overloads with parameters pred and proj1.
Effects: Finds an element that matches one of a set of values.
Returns: The first iterator i in the range [first1, last1) such that for some iterator j in the range [first2, last2) E holds.
Returns last1 if [first2, last2) is empty or if no such iterator is found.
Complexity: At most (last1-first1) * (last2-first2) applications of the corresponding predicate and any projections.

26.6.10 Adjacent find [alg.adjacent.find]

template<class ForwardIterator> constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class BinaryPredicate> constexpr ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> ForwardIterator adjacent_find(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_binary_predicate<projected<I, Proj>, projected<I, Proj>> Pred = ranges::equal_to> constexpr I ranges::adjacent_find(I first, S last, Pred pred = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_binary_predicate<projected<iterator_t<R>, Proj>, projected<iterator_t<R>, Proj>> Pred = ranges::equal_to> constexpr borrowed_iterator_t<R> ranges::adjacent_find(R&& r, Pred pred = {}, Proj proj = {});
Let E be:
  • *i == *(i + 1) for the overloads with no parameter pred;
  • pred(*i, *(i + 1)) != false for the overloads with a parameter pred and no parameter proj;
  • bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1)))) for the overloads with both parameters pred and proj.
Returns: The first iterator i such that both i and i + 1 are in the range [first, last) for which E holds.
Returns last if no such iterator is found.
Complexity: For the overloads with no ExecutionPolicy, exactly min((i - first) + 1,  (last - first) - 1) applications of the corresponding predicate, where i is adjacent_find's return value.
For the overloads with an ExecutionPolicy, applications of the corresponding predicate, and no more than twice as many applications of any projection.

26.6.11 Count [alg.count]

template<class InputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr typename iterator_traits<InputIterator>::difference_type count(InputIterator first, InputIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> typename iterator_traits<ForwardIterator>::difference_type count(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); template<class InputIterator, class Predicate> constexpr typename iterator_traits<InputIterator>::difference_type count_if(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> typename iterator_traits<ForwardIterator>::difference_type count_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr iter_difference_t<I> ranges::count(I first, S last, const T& value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr range_difference_t<R> ranges::count(R&& r, const T& value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr iter_difference_t<I> ranges::count_if(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr range_difference_t<R> ranges::count_if(R&& r, Pred pred, Proj proj = {});
Let E be:
  • *i == value for the overloads with no parameter pred or proj;
  • pred(*i) != false for the overloads with a parameter pred but no parameter proj;
  • invoke(proj, *i) == value for the overloads with a parameter proj but no parameter pred;
  • bool(invoke(pred, invoke(proj, *i))) for the overloads with both parameters proj and pred.
Effects: Returns the number of iterators i in the range [first, last) for which E holds.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.

26.6.12 Mismatch [alg.mismatch]

template<class InputIterator1, class InputIterator2> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class InputIterator1, class InputIterator2> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr pair<InputIterator1, InputIterator2> mismatch(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> pair<ForwardIterator1, ForwardIterator2> mismatch(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr ranges::mismatch_result<I1, I2> ranges::mismatch(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr ranges::mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> ranges::mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let last2 be first2 + (last1 - first1) for the overloads with no parameter last2 or r2.
Let E be:
  • !(*(first1 + n) == *(first2 + n)) for the overloads with no parameter pred;
  • pred(*(first1 + n), *(first2 + n)) == false for the overloads with a parameter pred and no parameter proj1;
  • !invoke(pred, invoke(proj1, *(first1 + n)), invoke(proj2, *(first2 + n))) for the overloads with both parameters pred and proj1.
Let N be min(last1 - first1,  last2 - first2).
Returns: { first1 + n, first2 + n }, where n is the smallest integer in [0, N) such that E holds, or N if no such integer exists.
Complexity: At most N applications of the corresponding predicate and any projections.

26.6.13 Equal [alg.equal]

template<class InputIterator1, class InputIterator2> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> bool equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class InputIterator1, class InputIterator2> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class InputIterator1, class InputIterator2, class BinaryPredicate> constexpr bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> bool equal(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ranges::equal(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ranges::equal(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let:
  • last2 be first2 + (last1 - first1) for the overloads with no parameter last2 or r2;
  • pred be equal_to{} for the overloads with no parameter pred;
  • E be:
    • pred(*i, *(first2 + (i - first1))) for the overloads with no parameter proj1;
    • invoke(pred, invoke(proj1, *i), invoke(proj2, *(first2 + (i - first1)))) for the overloads with parameter proj1.
Returns: If last1 - first1 != last2 - first2, return false.
Otherwise return true if E holds for every iterator i in the range [first1, last1).
Otherwise, returns false.
Complexity: If then no applications of the corresponding predicate and each projection; otherwise,
  • For the overloads with no ExecutionPolicy, at most min(last1 - first1,  last2 - first2) applications of the corresponding predicate and any projections.
  • For the overloads with an ExecutionPolicy, applications of the corresponding predicate.

26.6.14 Is permutation [alg.is.permutation]

template<class ForwardIterator1, class ForwardIterator2> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, BinaryPredicate pred); template<class ForwardIterator1, class ForwardIterator2> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);
Let last2 be first2 + (last1 - first1) for the overloads with no parameter named last2, and let pred be equal_to{} for the overloads with no parameter pred.
Mandates: ForwardIterator1 and ForwardIterator2 have the same value type.
Preconditions: The comparison function is an equivalence relation.
Returns: If last1 - first1 != last2 - first2, return false.
Otherwise return true if there exists a permutation of the elements in the range [first2, last2), beginning with ForwardIterator2 begin, such that equal(first1, last1, begin, pred) returns true; otherwise, returns false.
Complexity: No applications of the corresponding predicate if ForwardIterator1 and ForwardIterator2 meet the requirements of random access iterators and last1 - first1 != last2 - first2.
Otherwise, exactly last1 - first1 applications of the corresponding predicate if equal(first1, last1, first2, last2, pred) would return true; otherwise, at worst , where N has the value last1 - first1.
template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<I1, Proj1>, projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Returns: If last1 - first1 != last2 - first2, return false.
Otherwise return true if there exists a permutation of the elements in the range [first2, last2), bounded by [pfirst, plast), such that ranges​::​equal(first1, last1, pfirst, plast, pred, proj1, proj2) returns true; otherwise, returns false.
Complexity: No applications of the corresponding predicate and projections if
Otherwise, exactly last1 - first1 applications of the corresponding predicate and projections if ranges​::​equal(​first1, last1, first2, last2, pred, proj1, proj2) would return true; otherwise, at worst , where N has the value last1 - first1.

26.6.15 Search [alg.search]

template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);
Returns: The first iterator i in the range [first1, last1 - (last2-first2)) such that for every non-negative integer n less than last2 - first2 the following corresponding conditions hold: *(i + n) == *(first2 + n), pred(*(i + n), *(first2 + n)) != false.
Returns first1 if [first2, last2) is empty, otherwise returns last1 if no such iterator is found.
Complexity: At most (last1 - first1) * (last2 - first2) applications of the corresponding predicate.
template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr subrange<I1> ranges::search(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_subrange_t<R1> ranges::search(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Returns:
  • {i, i + (last2 - first2)}, where i is the first iterator in the range [first1, last1 - (last2 - first2)) such that for every non-negative integer n less than last2 - first2 the condition bool(invoke(pred, invoke(proj1, *(i + n)), invoke(proj2, *(first2 + n)))) is true.
  • Returns {last1, last1} if no such iterator exists.
Complexity: At most (last1 - first1) * (last2 - first2) applications of the corresponding predicate and projections.
template<class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value); template<class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type, class BinaryPredicate> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred);
Mandates: The type Size is convertible to an integral type ([conv.integral], [class.conv]).
Let E be pred(*(i + n), value) != false for the overloads with a parameter pred, and *(i + n) == value otherwise.
Returns: The first iterator i in the range [first, last-count) such that for every non-negative integer n less than count the condition E is true.
Returns last if no such iterator is found.
Complexity: At most last - first applications of the corresponding predicate.
template<forward_iterator I, sentinel_for<I> S, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_comparable<I, const T*, Pred, Proj> constexpr subrange<I> ranges::search_n(I first, S last, iter_difference_t<I> count, const T& value, Pred pred = {}, Proj proj = {}); template<forward_range R, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirectly_comparable<iterator_t<R>, const T*, Pred, Proj> constexpr borrowed_subrange_t<R> ranges::search_n(R&& r, range_difference_t<R> count, const T& value, Pred pred = {}, Proj proj = {});
Returns: {i, i + count} where i is the first iterator in the range [first, last - count) such that for every non-negative integer n less than count, the following condition holds: invoke(pred, invoke(proj, *(i + n)), value).
Returns {last, last} if no such iterator is found.
Complexity: At most last - first applications of the corresponding predicate and projection.
template<class ForwardIterator, class Searcher> constexpr ForwardIterator search(ForwardIterator first, ForwardIterator last, const Searcher& searcher);
Effects: Equivalent to: return searcher(first, last).first;
Remarks: Searcher need not meet the Cpp17CopyConstructible requirements.

26.6.16 Starts with [alg.starts.with]

template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ranges::starts_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ranges::starts_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Returns: ranges::mismatch(std::move(first1), last1, std::move(first2), last2, pred, proj1, proj2).in2 == last2

26.6.17 Ends with [alg.ends.with]

template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires (forward_iterator<I1> || sized_sentinel_for<S1, I1>) && (forward_iterator<I2> || sized_sentinel_for<S2, I2>) && indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr bool ranges::ends_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let N1 be last1 - first1 and N2 be last2 - first2.
Returns: false if N1 < N2, otherwise ranges::equal(std::move(first1) + (N1 - N2), last1, std::move(first2), last2, pred, proj1, proj2)
template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires (forward_range<R1> || sized_range<R1>) && (forward_range<R2> || sized_range<R2>) && indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr bool ranges::ends_with(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let N1 be ranges​::​distance(r1) and N2 be ranges​::​distance(r2).
Returns: false if N1 < N2, otherwise ranges::equal(views::drop(ranges::ref_view(r1), N1 - static_cast<decltype(N1)>(N2)), r2, pred, proj1, proj2)

26.6.18 Fold [alg.fold]

template<input_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-left-foldable<T, I> F> constexpr auto ranges::fold_left(I first, S last, T init, F f); template<input_range R, class T = range_value_t<R>, indirectly-binary-left-foldable<T, iterator_t<R>> F> constexpr auto ranges::fold_left(R&& r, T init, F f);
Returns: ranges::fold_left_with_iter(std::move(first), last, std::move(init), f).value
template<input_iterator I, sentinel_for<I> S, indirectly-binary-left-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr auto ranges::fold_left_first(I first, S last, F f); template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr auto ranges::fold_left_first(R&& r, F f);
Returns: ranges::fold_left_first_with_iter(std::move(first), last, f).value
template<bidirectional_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-right-foldable<T, I> F> constexpr auto ranges::fold_right(I first, S last, T init, F f); template<bidirectional_range R, class T = range_value_t<R>, indirectly-binary-right-foldable<T, iterator_t<R>> F> constexpr auto ranges::fold_right(R&& r, T init, F f);
Effects: Equivalent to: using U = decay_t<invoke_result_t<F&, iter_reference_t<I>, T>>; if (first == last) return U(std::move(init)); I tail = ranges::next(first, last); U accum = invoke(f, *--tail, std::move(init)); while (first != tail) accum = invoke(f, *--tail, std::move(accum)); return accum;
template<bidirectional_iterator I, sentinel_for<I> S, indirectly-binary-right-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr auto ranges::fold_right_last(I first, S last, F f); template<bidirectional_range R, indirectly-binary-right-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr auto ranges::fold_right_last(R&& r, F f);
Let U be decltype(ranges​::​fold_right(first, last, iter_value_t<I>(*first), f)).
Effects: Equivalent to: if (first == last) return optional<U>(); I tail = ranges::prev(ranges::next(first, std::move(last))); return optional<U>(in_place, ranges::fold_right(std::move(first), tail, iter_value_t<I>(*tail), std::move(f)));
template<input_iterator I, sentinel_for<I> S, class T = iter_value_t<I>, indirectly-binary-left-foldable<T, I> F> constexpr see below ranges::fold_left_with_iter(I first, S last, T init, F f); template<input_range R, class T = range_value_t<R>, indirectly-binary-left-foldable<T, iterator_t<R>> F> constexpr see below ranges::fold_left_with_iter(R&& r, T init, F f);
Let U be decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>.
Effects: Equivalent to: if (first == last) return {std::move(first), U(std::move(init))}; U accum = invoke(f, std::move(init), *first); for (++first; first != last; ++first) accum = invoke(f, std::move(accum), *first); return {std::move(first), std::move(accum)};
Remarks: The return type is fold_left_with_iter_result<I, U> for the first overload and fold_left_with_iter_result<borrowed_iterator_t<R>, U> for the second overload.
template<input_iterator I, sentinel_for<I> S, indirectly-binary-left-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr see below ranges::fold_left_first_with_iter(I first, S last, F f); template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr see below ranges::fold_left_first_with_iter(R&& r, F f);
Let U be decltype(ranges::fold_left(std::move(first), last, iter_value_t<I>(*first), f))
Effects: Equivalent to: if (first == last) return {std::move(first), optional<U>()}; optional<U> init(in_place, *first); for (++first; first != last; ++first) *init = invoke(f, std::move(*init), *first); return {std::move(first), std::move(init)};
Remarks: The return type is fold_left_first_with_iter_result<I, optional<U>> for the first overload and fold_left_first_with_iter_result<borrowed_iterator_t<R>, optional<U>> for the second overload.

26.7 Mutating sequence operations [alg.modifying.operations]

26.7.1 Copy [alg.copy]

template<class InputIterator, class OutputIterator> constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr ranges::copy_result<I, O> ranges::copy(I first, S last, O result); template<input_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::copy_result<borrowed_iterator_t<R>, O> ranges::copy(R&& r, O result);
Let N be last - first.
Preconditions: result is not in the range [first, last).
Effects: Copies elements in the range [first, last) into the range [result, result + N) starting from first and proceeding to last.
For each non-negative integer , performs *(result + n) = *(first + n).
Returns:
  • result + N for the overload in namespace std.
  • {last, result + N} for the overloads in namespace ranges.
Complexity: Exactly N assignments.
template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 copy(ExecutionPolicy&& policy, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);
Preconditions: The ranges [first, last) and [result, result + (last - first)) do not overlap.
Effects: Copies elements in the range [first, last) into the range [result, result + (last - first)).
For each non-negative integer n < (last - first), performs *(result + n) = *(first + n).
Returns: result + (last - first).
Complexity: Exactly last - first assignments.
template<class InputIterator, class Size, class OutputIterator> constexpr OutputIterator copy_n(InputIterator first, Size n, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class Size, class ForwardIterator2> ForwardIterator2 copy_n(ExecutionPolicy&& exec, ForwardIterator1 first, Size n, ForwardIterator2 result); template<input_iterator I, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr ranges::copy_n_result<I, O> ranges::copy_n(I first, iter_difference_t<I> n, O result);
Let N be max(0, n).
Mandates: The type Size is convertible to an integral type ([conv.integral], [class.conv]).
Effects: For each non-negative integer , performs *(result + i) = *(first + i).
Returns:
  • result + N for the overloads in namespace std.
  • {first + N, result + N} for the overload in namespace ranges.
Complexity: Exactly N assignments.
template<class InputIterator, class OutputIterator, class Predicate> constexpr OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate> ForwardIterator2 copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr ranges::copy_if_result<I, O> ranges::copy_if(I first, S last, O result, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::copy_if_result<borrowed_iterator_t<R>, O> ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {});
Let E be:
  • bool(pred(*i)) for the overloads in namespace std;
  • bool(invoke(pred, invoke(proj, *i))) for the overloads in namespace ranges,
and N be the number of iterators i in the range [first, last) for which the condition E holds.
Preconditions: The ranges [first, last) and [result, result + (last - first)) do not overlap.
[Note 1: 
For the overload with an ExecutionPolicy, there might be a performance cost if iterator_traits<ForwardIterator1>​::​value_type is not Cpp17MoveConstructible (Table 31).
— end note]
Effects: Copies all of the elements referred to by the iterator i in the range [first, last) for which E is true.
Returns:
  • result + N for the overloads in namespace std.
  • {last, result + N} for the overloads in namespace ranges.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.
Remarks: Stable ([algorithm.stable]).
template<class BidirectionalIterator1, class BidirectionalIterator2> constexpr BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> requires indirectly_copyable<I1, I2> constexpr ranges::copy_backward_result<I1, I2> ranges::copy_backward(I1 first, S1 last, I2 result); template<bidirectional_range R, bidirectional_iterator I> requires indirectly_copyable<iterator_t<R>, I> constexpr ranges::copy_backward_result<borrowed_iterator_t<R>, I> ranges::copy_backward(R&& r, I result);
Let N be last - first.
Preconditions: result is not in the range (first, last].
Effects: Copies elements in the range [first, last) into the range [result - N, result) starting from last - 1 and proceeding to first.204
For each positive integer n  ≤ N, performs *(result - n) = *(last - n).
Returns:
  • result - N for the overload in namespace std.
  • {last, result - N} for the overloads in namespace ranges.
Complexity: Exactly N assignments.
204)204)
copy_backward can be used instead of copy when last is in the range [result - N, result).

26.7.2 Move [alg.move]

template<class InputIterator, class OutputIterator> constexpr OutputIterator move(InputIterator first, InputIterator last, OutputIterator result); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_movable<I, O> constexpr ranges::move_result<I, O> ranges::move(I first, S last, O result); template<input_range R, weakly_incrementable O> requires indirectly_movable<iterator_t<R>, O> constexpr ranges::move_result<borrowed_iterator_t<R>, O> ranges::move(R&& r, O result);
Let E be
  • std​::​move(*(first + n)) for the overload in namespace std;
  • ranges​::​iter_move(first + n) for the overloads in namespace ranges.
Let N be last - first.
Preconditions: result is not in the range [first, last).
Effects: Moves elements in the range [first, last) into the range [result, result + N) starting from first and proceeding to last.
For each non-negative integer , performs *(result + n) = E.
Returns:
  • result + N for the overload in namespace std.
  • {last, result + N} for the overloads in namespace ranges.
Complexity: Exactly N assignments.
template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 move(ExecutionPolicy&& policy, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);
Let N be last - first.
Preconditions: The ranges [first, last) and [result, result + N) do not overlap.
Effects: Moves elements in the range [first, last) into the range [result, result + N).
For each non-negative integer , performs *(result + n) = std​::​​move(*(first + n)).
Returns: result + N.
Complexity: Exactly N assignments.
template<class BidirectionalIterator1, class BidirectionalIterator2> constexpr BidirectionalIterator2 move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> requires indirectly_movable<I1, I2> constexpr ranges::move_backward_result<I1, I2> ranges::move_backward(I1 first, S1 last, I2 result); template<bidirectional_range R, bidirectional_iterator I> requires indirectly_movable<iterator_t<R>, I> constexpr ranges::move_backward_result<borrowed_iterator_t<R>, I> ranges::move_backward(R&& r, I result);
Let E be
  • std​::​move(*(last - n)) for the overload in namespace std;
  • ranges​::​iter_move(last - n) for the overloads in namespace ranges.
Let N be last - first.
Preconditions: result is not in the range (first, last].
Effects: Moves elements in the range [first, last) into the range [result - N, result) starting from last - 1 and proceeding to first.205
For each positive integer n  ≤ N, performs *(result - n) = E.
Returns:
  • result - N for the overload in namespace std.
  • {last, result - N} for the overloads in namespace ranges.
Complexity: Exactly N assignments.
205)205)
move_backward can be used instead of move when last is in the range [result - N, result).

26.7.3 Swap [alg.swap]

template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); // freestanding template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2> requires indirectly_swappable<I1, I2> constexpr ranges::swap_ranges_result<I1, I2> ranges::swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2); template<input_range R1, input_range R2> requires indirectly_swappable<iterator_t<R1>, iterator_t<R2>> constexpr ranges::swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> ranges::swap_ranges(R1&& r1, R2&& r2);
Let:
  • last2 be first2 + (last1 - first1) for the overloads with no parameter named last2;
  • M be min(last1 - first1,  last2 - first2).
Preconditions: The two ranges [first1, last1) and [first2, last2) do not overlap.
For the overloads in namespace std, *(first1 + n) is swappable with ([swappable.requirements]) *(first2 + n).
Effects: For each non-negative integer performs:
  • swap(*(first1 + n), *(first2 + n)) for the overloads in namespace std;
  • ranges​::​iter_swap(first1 + n, first2 + n) for the overloads in namespace ranges.
Returns:
  • last2 for the overloads in namespace std.
  • {first1 + M, first2 + M} for the overloads in namespace ranges.
Complexity: Exactly M swaps.
template<class ForwardIterator1, class ForwardIterator2> constexpr void iter_swap(ForwardIterator1 a, ForwardIterator2 b);
Preconditions: a and b are dereferenceable.
*a is swappable with ([swappable.requirements]) *b.
Effects: As if by swap(*a, *b).

26.7.4 Transform [alg.transform]

template<class InputIterator, class OutputIterator, class UnaryOperation> constexpr OutputIterator transform(InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class UnaryOperation> ForwardIterator2 transform(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 result, UnaryOperation op); template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryOperation> constexpr OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class BinaryOperation> ForwardIterator transform(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator result, BinaryOperation binary_op); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<I, Proj>>> constexpr ranges::unary_transform_result<I, O> ranges::transform(I first1, S last1, O result, F op, Proj proj = {}); template<input_range R, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<iterator_t<R>, Proj>>> constexpr ranges::unary_transform_result<borrowed_iterator_t<R>, O> ranges::transform(R&& r, O result, F op, Proj proj = {}); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, class Proj2 = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<I1, Proj1>, projected<I2, Proj2>>> constexpr ranges::binary_transform_result<I1, I2, O> ranges::transform(I1 first1, S1 last1, I2 first2, S2 last2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, class Proj2 = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>> constexpr ranges::binary_transform_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> ranges::transform(R1&& r1, R2&& r2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {});
Let:
  • last2 be first2 + (last1 - first1) for the overloads with parameter first2 but no parameter last2;
  • N be last1 - first1 for unary transforms, or min(last1 - first1,  last2 - first2) for binary transforms;
  • E be
    • op(*(first1 + (i - result))) for unary transforms defined in namespace std;
    • binary_op(*(first1 + (i - result)), *(first2 + (i - result))) for binary transforms defined in namespace std;
    • invoke(op, invoke(proj, *(first1 + (i - result)))) for unary transforms defined in namespace ranges;
    • invoke(binary_op, invoke(proj1, *(first1 + (i - result))), invoke(proj2, *(first2 + (i - result)))) for binary transforms defined in namespace ranges.
Preconditions: op and binary_op do not invalidate iterators or subranges, nor modify elements in the ranges
Effects: Assigns through every iterator i in the range [result, result + N) a new corresponding value equal to E.
Returns:
  • result + N for the overloads defined in namespace std.
  • {first1 + N, result + N} for unary transforms defined in namespace ranges.
  • {first1 + N, first2 + N, result + N} for binary transforms defined in namespace ranges.
Complexity: Exactly N applications of op or binary_op, and any projections.
This requirement also applies to the overload with an ExecutionPolicy.
Remarks: result may be equal to first1 or first2.
206)206)
The use of fully closed ranges is intentional.

26.7.5 Replace [alg.replace]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> void replace(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value); template<class ForwardIterator, class Predicate, class T = iterator_traits<ForwardIterator>::value_type> constexpr void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); template<class ExecutionPolicy, class ForwardIterator, class Predicate, class T = iterator_traits<ForwardIterator>::value_type> void replace_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value); template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T1 = projected_value_t<I, Proj>, class T2 = T1> requires indirectly_writable<I, const T2&> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*> constexpr I ranges::replace(I first, S last, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_range R, class Proj = identity, class T1 = projected_value_t<iterator_t<R>, Proj>, class T2 = T1> requires indirectly_writable<iterator_t<R>, const T2&> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T1*> constexpr borrowed_iterator_t<R> ranges::replace(R&& r, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_writable<I, const T&> constexpr I ranges::replace_if(I first, S last, Pred pred, const T& new_value, Proj proj = {}); template<input_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_writable<iterator_t<R>, const T&> constexpr borrowed_iterator_t<R> ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {});
Let E be
  • bool(*i == old_value) for replace;
  • bool(pred(*i)) for replace_if;
  • bool(invoke(proj, *i) == old_value) for ranges​::​replace;
  • bool(invoke(pred, invoke(proj, *i))) for ranges​::​replace_if.
Mandates: new_value is writable ([iterator.requirements.general]) to first.
Effects: Substitutes elements referred by the iterator i in the range [first, last) with new_value, when E is true.
Returns: last for the overloads in namespace ranges.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.
template<class InputIterator, class OutputIterator, class T> constexpr OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> ForwardIterator2 replace_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& old_value, const T& new_value); template<class InputIterator, class OutputIterator, class Predicate, class T> constexpr OutputIterator replace_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred, const T& new_value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate, class T> ForwardIterator2 replace_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred, const T& new_value); template<input_iterator I, sentinel_for<I> S, class O, class Proj = identity, class T1 = projected_value_t<I, Proj>, class T2 = iter_value_t<O>> requires indirectly_copyable<I, O> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*> && output_iterator<O, const T2&> constexpr ranges::replace_copy_result<I, O> ranges::replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_range R, class O, class Proj = identity, class T1 = projected_value_t<iterator_t<R>, Proj>, class T2 = iter_value_t<O>> requires indirectly_copyable<iterator_t<R>, O> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T1*> && output_iterator<O, const T2&> constexpr ranges::replace_copy_result<borrowed_iterator_t<R>, O> ranges::replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S,class O, class T = iter_value_t<O>, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> && output_iterator<O, const T&> constexpr ranges::replace_copy_if_result<I, O> ranges::replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, Proj proj = {}); template<input_range R, class O, class T = iter_value_t<O>, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> && output_iterator<O, const T&> constexpr ranges::replace_copy_if_result<borrowed_iterator_t<R>, O> ranges::replace_copy_if(R&& r, O result, Pred pred, const T& new_value, Proj proj = {});
Let E be
  • bool(*(first + (i - result)) == old_value) for replace_copy;
  • bool(pred(*(first + (i - result)))) for replace_copy_if;
  • bool(invoke(proj, *(first + (i - result))) == old_value) for ranges​::​replace_copy;
  • bool(invoke(pred, invoke(proj, *(first + (i - result))))) for ranges​::​replace_copy_if.
Mandates: The results of the expressions *first and new_value are writable ([iterator.requirements.general]) to result.
Preconditions: The ranges [first, last) and [result, result + (last - first)) do not overlap.
Effects: Assigns through every iterator i in the range [result, result + (last - first)) a new corresponding value
  • new_value if E is true or
  • *(first + (i - result)) otherwise.
Returns:
  • result + (last - first) for the overloads in namespace std.
  • {last, result + (last - first)} for the overloads in namespace ranges.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.

26.7.6 Fill [alg.fill]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> void fill(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); template<class OutputIterator, class Size, class T = iterator_traits<OutputIterator>::value_type> constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator fill_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, const T& value); template<class O, sentinel_for<O> S, class T = iter_value_t<O>> requires output_iterator<O, const T&> constexpr O ranges::fill(O first, S last, const T& value); template<class R, class T = range_value_t<R>> requires output_range<R, const T&> constexpr borrowed_iterator_t<R> ranges::fill(R&& r, const T& value); template<class O, class T = iter_value_t<O>> requires output_iterator<O, const T&> constexpr O ranges::fill_n(O first, iter_difference_t<O> n, const T& value);
Let N be max(0, n) for the fill_n algorithms, and last - first for the fill algorithms.
Mandates: The expression value is writable ([iterator.requirements.general]) to the output iterator.
The type Size is convertible to an integral type ([conv.integral], [class.conv]).
Effects: Assigns value through all the iterators in the range [first, first + N).
Returns: first + N.
Complexity: Exactly N assignments.

26.7.7 Generate [alg.generate]

template<class ForwardIterator, class Generator> constexpr void generate(ForwardIterator first, ForwardIterator last, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Generator> void generate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Generator gen); template<class OutputIterator, class Size, class Generator> constexpr OutputIterator generate_n(OutputIterator first, Size n, Generator gen); template<class ExecutionPolicy, class ForwardIterator, class Size, class Generator> ForwardIterator generate_n(ExecutionPolicy&& exec, ForwardIterator first, Size n, Generator gen); template<input_or_output_iterator O, sentinel_for<O> S, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> constexpr O ranges::generate(O first, S last, F gen); template<class R, copy_constructible F> requires invocable<F&> && output_range<R, invoke_result_t<F&>> constexpr borrowed_iterator_t<R> ranges::generate(R&& r, F gen); template<input_or_output_iterator O, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> constexpr O ranges::generate_n(O first, iter_difference_t<O> n, F gen);
Let N be max(0, n) for the generate_n algorithms, and last - first for the generate algorithms.
Mandates: Size is convertible to an integral type ([conv.integral], [class.conv]).
Effects: Assigns the result of successive evaluations of gen() through each iterator in the range [first, first + N).
Returns: first + N.
Complexity: Exactly N evaluations of gen() and assignments.

26.7.8 Remove [alg.remove]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value); template<class ExecutionPolicy, class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> ForwardIterator remove(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class Predicate> constexpr ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator remove_if(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<permutable I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr subrange<I> ranges::remove(I first, S last, const T& value, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires permutable<iterator_t<R>> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_subrange_t<R> ranges::remove(R&& r, const T& value, Proj proj = {}); template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> ranges::remove_if(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::remove_if(R&& r, Pred pred, Proj proj = {});
Let E be
  • bool(*i == value) for remove;
  • bool(pred(*i)) for remove_if;
  • bool(invoke(proj, *i) == value) for ranges​::​remove;
  • bool(invoke(pred, invoke(proj, *i))) for ranges​::​remove_if.
Preconditions: For the algorithms in namespace std, the type of *first meets the Cpp17MoveAssignable requirements (Table 33).
Effects: Eliminates all the elements referred to by iterator i in the range [first, last) for which E holds.
Returns: Let j be the end of the resulting range.
Returns:
  • j for the overloads in namespace std.
  • {j, last} for the overloads in namespace ranges.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.
Remarks: Stable ([algorithm.stable]).
[Note 1: 
Each element in the range [ret, last), where ret is the returned value, has a valid but unspecified state, because the algorithms can eliminate elements by moving from elements that were originally in that range.
— end note]
template<class InputIterator, class OutputIterator, class T = iterator_traits<InputIterator>::value_type> constexpr OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T = iterator_traits<ForwardIterator1>::value_type> ForwardIterator2 remove_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, const T& value); template<class InputIterator, class OutputIterator, class Predicate> constexpr OutputIterator remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Predicate> ForwardIterator2 remove_copy_if(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, Predicate pred); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_copyable<I, O> && indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr ranges::remove_copy_result<I, O> ranges::remove_copy(I first, S last, O result, const T& value, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirectly_copyable<iterator_t<R>, O> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr ranges::remove_copy_result<borrowed_iterator_t<R>, O> ranges::remove_copy(R&& r, O result, const T& value, Proj proj = {}); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr ranges::remove_copy_if_result<I, O> ranges::remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::remove_copy_if_result<borrowed_iterator_t<R>, O> ranges::remove_copy_if(R&& r, O result, Pred pred, Proj proj = {});
Let E be
  • bool(*i == value) for remove_copy;
  • bool(pred(*i)) for remove_copy_if;
  • bool(invoke(proj, *i) == value) for ranges​::​remove_copy;
  • bool(invoke(pred, invoke(proj, *i))) for ranges​::​remove_copy_if.
Let N be the number of elements in [first, last) for which E is false.
Mandates: *first is writable ([iterator.requirements.general]) to result.
Preconditions: The ranges [first, last) and [result, result + (last - first)) do not overlap.
[Note 2: 
For the overloads with an ExecutionPolicy, there might be a performance cost if iterator_traits<ForwardIterator1>​::​value_type does not meet the Cpp17MoveConstructible (Table 31) requirements.
— end note]
Effects: Copies all the elements referred to by the iterator i in the range [first, last) for which E is false.
Returns:
  • result + N, for the algorithms in namespace std.
  • {last, result + N}, for the algorithms in namespace ranges.
Complexity: Exactly last - first applications of the corresponding predicate and any projection.
Remarks: Stable ([algorithm.stable]).

26.7.9 Unique [alg.unique]

template<class ForwardIterator> constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class BinaryPredicate> constexpr ForwardIterator unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator, class BinaryPredicate> ForwardIterator unique(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, BinaryPredicate pred); template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> constexpr subrange<I> ranges::unique(I first, S last, C comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::unique(R&& r, C comp = {}, Proj proj = {});
Let pred be equal_to{} for the overloads with no parameter pred, and let E be
  • bool(pred(*(i - 1), *i)) for the overloads in namespace std;
  • bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i))) for the overloads in namespace ranges.
Preconditions: For the overloads in namespace std, pred is an equivalence relation and the type of *first meets the Cpp17MoveAssignable requirements (Table 33).
Effects: For a nonempty range, eliminates all but the first element from every consecutive group of equivalent elements referred to by the iterator i in the range [first + 1, last) for which E is true.
Returns: Let j be the end of the resulting range.
Returns:
  • j for the overloads in namespace std.
  • {j, last} for the overloads in namespace ranges.
Complexity: For nonempty ranges, exactly (last - first) - 1 applications of the corresponding predicate and no more than twice as many applications of any projection.
template<class InputIterator, class OutputIterator> constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template<class InputIterator, class OutputIterator, class BinaryPredicate> constexpr OutputIterator unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator2 unique_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryPredicate pred); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> requires indirectly_copyable<I, O> && (forward_iterator<I> || (input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>) || indirectly_copyable_storable<I, O>) constexpr ranges::unique_copy_result<I, O> ranges::unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); template<input_range R, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires indirectly_copyable<iterator_t<R>, O> && (forward_iterator<iterator_t<R>> || (input_iterator<O> && same_as<range_value_t<R>, iter_value_t<O>>) || indirectly_copyable_storable<iterator_t<R>, O>) constexpr ranges::unique_copy_result<borrowed_iterator_t<R>, O> ranges::unique_copy(R&& r, O result, C comp = {}, Proj proj = {});
Let pred be equal_to{} for the overloads in namespace std with no parameter pred, and let E be
  • bool(pred(*i, *(i - 1))) for the overloads in namespace std;
  • bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1)))) for the overloads in namespace ranges.
Mandates: *first is writable ([iterator.requirements.general]) to result.
Preconditions:
Effects: Copies only the first element from every consecutive group of equal elements referred to by the iterator i in the range [first, last) for which E holds.
Returns:
  • result + N for the overloads in namespace std.
  • {last, result + N} for the overloads in namespace ranges.
Complexity: Exactly last - first - 1 applications of the corresponding predicate and no more than twice as many applications of any projection.

26.7.10 Reverse [alg.reverse]

template<class BidirectionalIterator> constexpr void reverse(BidirectionalIterator first, BidirectionalIterator last); template<class ExecutionPolicy, class BidirectionalIterator> void reverse(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last); template<bidirectional_iterator I, sentinel_for<I> S> requires permutable<I> constexpr I ranges::reverse(I first, S last); template<bidirectional_range R> requires permutable<iterator_t<R>> constexpr borrowed_iterator_t<R> ranges::reverse(R&& r);
Preconditions: For the overloads in namespace std, BidirectionalIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]).
Effects: For each non-negative integer i < (last - first) / 2, applies std​::​iter_swap, or ranges​::​​iter_swap for the overloads in namespace ranges, to all pairs of iterators first + i, (last - i) - 1.
Returns: last for the overloads in namespace ranges.
Complexity: Exactly (last - first)/2 swaps.
template<class BidirectionalIterator, class OutputIterator> constexpr OutputIterator reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result); template<class ExecutionPolicy, class BidirectionalIterator, class ForwardIterator> ForwardIterator reverse_copy(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, ForwardIterator result); template<bidirectional_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr ranges::reverse_copy_result<I, O> ranges::reverse_copy(I first, S last, O result); template<bidirectional_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::reverse_copy_result<borrowed_iterator_t<R>, O> ranges::reverse_copy(R&& r, O result);
Let N be last - first.
Preconditions: The ranges [first, last) and [result, result + N) do not overlap.
Effects: Copies the range [first, last) to the range [result, result + N) such that for every non-negative integer i < N the following assignment takes place: *(result + N - 1 - i) = *(first + i).
Returns:
  • result + N for the overloads in namespace std.
  • {last, result + N} for the overloads in namespace ranges.
Complexity: Exactly N assignments.

26.7.11 Rotate [alg.rotate]

template<class ForwardIterator> constexpr ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator rotate(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator middle, ForwardIterator last); template<permutable I, sentinel_for<I> S> constexpr subrange<I> ranges::rotate(I first, I middle, S last);
Preconditions: [first, middle) and [middle, last) are valid ranges.
For the overloads in namespace std, ForwardIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]), and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: For each non-negative integer i < (last - first), places the element from the position first + i into position first + (i + (last - middle)) % (last - first).
[Note 1: 
This is a left rotate.
— end note]
Returns:
  • first + (last - middle) for the overloads in namespace std.
  • {first + (last - middle), last} for the overload in namespace ranges.
Complexity: At most last - first swaps.
template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::rotate(R&& r, iterator_t<R> middle);
Effects: Equivalent to: return ranges​::​rotate(ranges​::​begin(r), middle, ranges​::​end(r));
template<class ForwardIterator, class OutputIterator> constexpr OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 rotate_copy(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 middle, ForwardIterator1 last, ForwardIterator2 result); template<forward_iterator I, sentinel_for<I> S, weakly_incrementable O> requires indirectly_copyable<I, O> constexpr ranges::rotate_copy_result<I, O> ranges::rotate_copy(I first, I middle, S last, O result);
Let N be last - first.
Preconditions: [first, middle) and [middle, last) are valid ranges.
The ranges [first, last) and [result, result + N) do not overlap.
Effects: Copies the range [first, last) to the range [result, result + N) such that for each non-negative integer the following assignment takes place: *(result + i) = *(first + (i + (middle - first)) % N).
Returns:
  • result + N for the overloads in namespace std.
  • {last, result + N} for the overload in namespace ranges.
Complexity: Exactly N assignments.
template<forward_range R, weakly_incrementable O> requires indirectly_copyable<iterator_t<R>, O> constexpr ranges::rotate_copy_result<borrowed_iterator_t<R>, O> ranges::rotate_copy(R&& r, iterator_t<R> middle, O result);
Effects: Equivalent to: return ranges::rotate_copy(ranges::begin(r), middle, ranges::end(r), std::move(result));

26.7.12 Sample [alg.random.sample]

template<class PopulationIterator, class SampleIterator, class Distance, class UniformRandomBitGenerator> SampleIterator sample(PopulationIterator first, PopulationIterator last, SampleIterator out, Distance n, UniformRandomBitGenerator&& g); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Gen> requires (forward_iterator<I> || random_access_iterator<O>) && indirectly_copyable<I, O> && uniform_random_bit_generator<remove_reference_t<Gen>> O ranges::sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); template<input_range R, weakly_incrementable O, class Gen> requires (forward_range<R> || random_access_iterator<O>) && indirectly_copyable<iterator_t<R>, O> && uniform_random_bit_generator<remove_reference_t<Gen>> O ranges::sample(R&& r, O out, range_difference_t<R> n, Gen&& g);
Mandates: For the overload in namespace std, Distance is an integer type and *first is writable ([iterator.requirements.general]) to out.
Preconditions: out is not in the range [first, last).
For the overload in namespace std:
Effects: Copies min(last - first,  n) elements (the sample) from [first, last) (the population) to out such that each possible sample has equal probability of appearance.
[Note 1: 
Algorithms that obtain such effects include selection sampling and reservoir sampling.
— end note]
Returns: The end of the resulting sample range.
Complexity: .
Remarks:
  • For the overload in namespace std, stable if and only if PopulationIterator models forward_iterator.
    For the first overload in namespace ranges, stable if and only if I models forward_iterator.
  • To the extent that the implementation of this function makes use of random numbers, the object g serves as the implementation's source of randomness.

26.7.13 Shuffle [alg.random.shuffle]

template<class RandomAccessIterator, class UniformRandomBitGenerator> void shuffle(RandomAccessIterator first, RandomAccessIterator last, UniformRandomBitGenerator&& g); template<random_access_iterator I, sentinel_for<I> S, class Gen> requires permutable<I> && uniform_random_bit_generator<remove_reference_t<Gen>> I ranges::shuffle(I first, S last, Gen&& g); template<random_access_range R, class Gen> requires permutable<iterator_t<R>> && uniform_random_bit_generator<remove_reference_t<Gen>> borrowed_iterator_t<R> ranges::shuffle(R&& r, Gen&& g);
Preconditions: For the overload in namespace std:
Effects: Permutes the elements in the range [first, last) such that each possible permutation of those elements has equal probability of appearance.
Returns: last for the overloads in namespace ranges.
Complexity: Exactly (last - first) - 1 swaps.
Remarks: To the extent that the implementation of this function makes use of random numbers, the object referenced by g shall serve as the implementation's source of randomness.

26.7.14 Shift [alg.shift]

template<class ForwardIterator> constexpr ForwardIterator shift_left(ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator shift_left(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<permutable I, sentinel_for<I> S> constexpr subrange<I> ranges::shift_left(I first, S last, iter_difference_t<I> n); template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::shift_left(R&& r, range_difference_t<R> n)
Preconditions: n >= 0 is true.
For the overloads in namespace std, the type of *first meets the Cpp17MoveAssignable requirements.
Effects: If n == 0 or n >= last - first, does nothing.
Otherwise, moves the element from position first + n + i into position first + i for each non-negative integer i < (last - first) - n.
For the overloads without an ExecutionPolicy template parameter, does so in order starting from i = 0 and proceeding to i = (last - first) - n - 1.
Returns: Let NEW_LAST be first + (last - first - n) if n < last - first, otherwise first.
  • NEW_LAST for the overloads in namespace std.
  • {first, NEW_LAST} for the overloads in namespace ranges.
Complexity: At most (last - first) - n assignments.
template<class ForwardIterator> constexpr ForwardIterator shift_right(ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator shift_right(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, typename iterator_traits<ForwardIterator>::difference_type n); template<permutable I, sentinel_for<I> S> constexpr subrange<I> ranges::shift_right(I first, S last, iter_difference_t<I> n); template<forward_range R> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::shift_right(R&& r, range_difference_t<R> n);
Preconditions: n >= 0 is true.
For the overloads in namespace std, the type of *first meets the Cpp17MoveAssignable requirements, and ForwardIterator meets the Cpp17BidirectionalIterator requirements ([bidirectional.iterators]) or the Cpp17ValueSwappable requirements.
Effects: If n == 0 or n >= last - first, does nothing.
Otherwise, moves the element from position first + i into position first + n + i for each non-negative integer i < (last - first) - n.
Does so in order starting from i = (last - first) - n - 1 and proceeding to i = 0 if
Returns: Let NEW_FIRST be first + n if n < last - first, otherwise last.
  • NEW_FIRST for the overloads in namespace std.
  • {NEW_FIRST, last} for the overloads in namespace ranges.
Complexity: At most (last - first) - n assignments or swaps.

26.8 Sorting and related operations [alg.sorting]

26.8.1 General [alg.sorting.general]

The operations in [alg.sorting] defined directly in namespace std have two versions: one that takes a function object of type Compare and one that uses an operator<.
Compare is a function object type ([function.objects]) that meets the requirements for a template parameter named BinaryPredicate ([algorithms.requirements]).
The return value of the function call operation applied to an object of type Compare, when converted to bool, yields true if the first argument of the call is less than the second, and false otherwise.
Compare comp is used throughout for algorithms assuming an ordering relation.
For all algorithms that take Compare, there is a version that uses operator< instead.
That is, comp(*i, *j) != false defaults to *i < *j != false.
For algorithms other than those described in [alg.binary.search], comp shall induce a strict weak ordering on the values.
The term strict refers to the requirement of an irreflexive relation (!comp(x, x) for all x), and the term weak to requirements that are not as strong as those for a total ordering, but stronger than those for a partial ordering.
If we define equiv(a, b) as !comp(a, b) && !comp(b, a), then the requirements are that comp and equiv both be transitive relations:
  • comp(a, b) && comp(b, c) implies comp(a, c)
  • equiv(a, b) && equiv(b, c) implies equiv(a, c)
[Note 1: 
Under these conditions, it can be shown that
  • equiv is an equivalence relation,
  • comp induces a well-defined relation on the equivalence classes determined by equiv, and
  • the induced relation is a strict total ordering.
— end note]
A sequence is sorted with respect to a comp and proj for a comparator and projection comp and proj if for every iterator i pointing to the sequence and every non-negative integer n such that i + n is a valid iterator pointing to an element of the sequence, bool(invoke(comp, invoke(proj, *(i + n)), invoke(proj, *i))) is false.
A sequence is sorted with respect to a comparator comp for a comparator comp if it is sorted with respect to comp and identity{} (the identity projection).
A sequence [start, finish) is partitioned with respect to an expression f(e) if there exists an integer n such that for all 0 <= i < (finish - start), f(*(start + i)) is true if and only if i < n.
In the descriptions of the functions that deal with ordering relationships we frequently use a notion of equivalence to describe concepts such as stability.
The equivalence to which we refer is not necessarily an operator==, but an equivalence relation induced by the strict weak ordering.
That is, two elements a and b are considered equivalent if and only if !(a < b) && !(b < a).

26.8.2 Sorting [alg.sort]

26.8.2.1 sort [sort]

template<class RandomAccessIterator> constexpr void sort(RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator> void sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::sort(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::sort(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Sorts the elements in the range [first, last) with respect to comp and proj.
Returns: last for the overloads in namespace ranges.
Complexity: Let N be last - first.
comparisons and projections.

26.8.2.2 stable_sort [stable.sort]

template<class RandomAccessIterator> constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator> void stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void stable_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::stable_sort(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::stable_sort(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Sorts the elements in the range [first, last) with respect to comp and proj.
Returns: last for the overloads in namespace ranges.
Complexity: Let N be last - first.
If enough extra memory is available, comparisons.
Otherwise, at most comparisons.
In either case, twice as many projections as the number of comparisons.
Remarks: Stable ([algorithm.stable]).

26.8.2.3 partial_sort [partial.sort]

template<class RandomAccessIterator> constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator> void partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void partial_sort(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::partial_sort(I first, I middle, S last, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: [first, middle) and [middle, last) are valid ranges.
For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Places the first middle - first elements from the range [first, last) as sorted with respect to comp and proj into the range [first, middle).
The rest of the elements in the range [middle, last) are placed in an unspecified order.
Returns: last for the overload in namespace ranges.
Complexity: Approximately (last - first) * log(middle - first) comparisons, and twice as many projections.
template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::partial_sort(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {});
Effects: Equivalent to: return ranges::partial_sort(ranges::begin(r), middle, ranges::end(r), comp, proj);

26.8.2.4 partial_sort_copy [partial.sort.copy]

template<class InputIterator, class RandomAccessIterator> constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template<class ExecutionPolicy, class ForwardIterator, class RandomAccessIterator> RandomAccessIterator partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template<class InputIterator, class RandomAccessIterator, class Compare> constexpr RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class RandomAccessIterator, class Compare> RandomAccessIterator partial_sort_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, random_access_iterator I2, sentinel_for<I2> S2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires indirectly_copyable<I1, I2> && sortable<I2, Comp, Proj2> && indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>> constexpr ranges::partial_sort_copy_result<I1, I2> ranges::partial_sort_copy(I1 first, S1 last, I2 result_first, S2 result_last, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, random_access_range R2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires indirectly_copyable<iterator_t<R1>, iterator_t<R2>> && sortable<iterator_t<R2>, Comp, Proj2> && indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> constexpr ranges::partial_sort_copy_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> ranges::partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let N be min(last - first,  result_last - result_first).
Let comp be less{}, and proj1 and proj2 be identity{} for the overloads with no parameters by those names.
Mandates: For the overloads in namespace std, the expression *first is writable ([iterator.requirements.general]) to result_first.
Preconditions: For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]), the type of *result_first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
For iterators a1 and b1 in [first, last), and iterators x2 and y2 in [result_first, result_last), after evaluating the assignment *y2 = *b1, let E be the value of bool(invoke(comp, invoke(proj1, *a1), invoke(proj2, *y2))).
Then, after evaluating the assignment *x2 = *a1, E is equal to bool(invoke(comp, invoke(proj2, *x2), invoke(proj2, *y2))).
[Note 1: 
Writing a value from the input range into the output range does not affect how it is ordered by comp and proj1 or proj2.
— end note]
Effects: Places the first N elements as sorted with respect to comp and proj2 into the range [result_first, result_first + N).
Returns:
  • result_first + N for the overloads in namespace std.
  • {last, result_first + N} for the overloads in namespace ranges.
Complexity: Approximately (last - first) * log N comparisons, and twice as many projections.

26.8.2.5 is_sorted [is.sorted]

template<class ForwardIterator> constexpr bool is_sorted(ForwardIterator first, ForwardIterator last);
Effects: Equivalent to: return is_sorted_until(first, last) == last;
template<class ExecutionPolicy, class ForwardIterator> bool is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last);
Effects: Equivalent to: return is_sorted_until(std::forward<ExecutionPolicy>(exec), first, last) == last;
template<class ForwardIterator, class Compare> constexpr bool is_sorted(ForwardIterator first, ForwardIterator last, Compare comp);
Effects: Equivalent to: return is_sorted_until(first, last, comp) == last;
template<class ExecutionPolicy, class ForwardIterator, class Compare> bool is_sorted(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp);
Effects: Equivalent to: return is_sorted_until(std::forward<ExecutionPolicy>(exec), first, last, comp) == last;
template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr bool ranges::is_sorted(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool ranges::is_sorted(R&& r, Comp comp = {}, Proj proj = {});
Effects: Equivalent to: return ranges​::​is_sorted_until(first, last, comp, proj) == last;
template<class ForwardIterator> constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator is_sorted_until(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator is_sorted_until(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I ranges::is_sorted_until(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::is_sorted_until(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Returns: The last iterator i in [first, last] for which the range [first, i) is sorted with respect to comp and proj.
Complexity: Linear.

26.8.3 Nth element [alg.nth.element]

template<class RandomAccessIterator> constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator> void nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> void nth_element(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: [first, nth) and [nth, last) are valid ranges.
For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]), and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: After nth_element the element in the position pointed to by nth is the element that would be in that position if the whole range were sorted with respect to comp and proj, unless nth == last.
Also for every iterator i in the range [first, nth) and every iterator j in the range [nth, last) it holds that: bool(invoke(comp, invoke(proj, *j), invoke(proj, *i))) is false.
Returns: last for the overload in namespace ranges.
Complexity: For the overloads with no ExecutionPolicy, linear on average.
For the overloads with an ExecutionPolicy, applications of the predicate, and swaps, where .
template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::nth_element(R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {});
Effects: Equivalent to: return ranges::nth_element(ranges::begin(r), nth, ranges::end(r), comp, proj);

26.8.4 Binary search [alg.binary.search]

26.8.4.1 General [alg.binary.search.general]

All of the algorithms in [alg.binary.search] are versions of binary search and assume that the sequence being searched is partitioned with respect to an expression formed by binding the search key to an argument of the comparison function.
They work on non-random access iterators minimizing the number of comparisons, which will be logarithmic for all types of iterators.
They are especially appropriate for random access iterators, because these algorithms do a logarithmic number of steps through the data structure.
For non-random access iterators they execute a linear number of steps.

26.8.4.2 lower_bound [lower.bound]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr I ranges::lower_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: The elements e of [first, last) are partitioned with respect to the expression
bool(invoke(comp, invoke(proj, e), value)).
Returns: The furthermost iterator i in the range [first, last] such that for every iterator j in the range [first, i), bool(invoke(comp, invoke(proj, *j), value)) is true.
Complexity: At most comparisons and projections.

26.8.4.3 upper_bound [upper.bound]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr I ranges::upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: The elements e of [first, last) are partitioned with respect to the expression
!bool(invoke(comp, value, invoke(proj, e))).
Returns: The furthermost iterator i in the range [first, last] such that for every iterator j in the range [first, i), !bool(invoke(comp, value, invoke(proj, *j))) is true.
Complexity: At most comparisons and projections.

26.8.4.4 equal_range [equal.range]

template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type> constexpr pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value); template<class ForwardIterator, class T = iterator_traits<ForwardIterator>::value_type, class Compare> constexpr pair<ForwardIterator, ForwardIterator> equal_range(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, class T = projected_value_t<I, Proj>, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr subrange<I> ranges::equal_range(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_subrange_t<R> ranges::equal_range(R&& r, const T& value, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: The elements e of [first, last) are partitioned with respect to the expressions bool(invoke(comp, invoke(proj, e), value)) and !bool(invoke(comp, value, invoke(proj, e))).
Also, for all elements e of [first, last), bool(comp(e, value)) implies !bool(comp(​value, e)) for the overloads in namespace std.
Returns:
  • For the overloads in namespace std: {lower_bound(first, last, value, comp), upper_bound(first, last, value, comp)}
  • For the overloads in namespace ranges: {ranges::lower_bound(first, last, value, comp, proj), ranges::upper_bound(first, last, value, comp, proj)}
Complexity: At most comparisons and projections.

26.8.4.5 binary_search [binary.search]

Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: The elements e of [first, last) are partitioned with respect to the expressions bool(invoke(comp, invoke(proj, e), value)) and !bool(invoke(comp, value, invoke(proj, e))).
Also, for all elements e of [first, last), bool(comp(e, value)) implies !bool(comp(​value, e)) for the overloads in namespace std.
Returns: true if and only if for some iterator i in the range [first, last), !bool(invoke(comp, invoke(proj, *i), value)) && !bool(invoke(comp, value, invoke(proj, *i))) is true.
Complexity: At most comparisons and projections.

26.8.5 Partitions [alg.partitions]

template<class InputIterator, class Predicate> constexpr bool is_partitioned(InputIterator first, InputIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> bool is_partitioned(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr bool ranges::is_partitioned(I first, S last, Pred pred, Proj proj = {}); template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr bool ranges::is_partitioned(R&& r, Pred pred, Proj proj = {});
Let proj be identity{} for the overloads with no parameter named proj.
Returns: true if and only if the elements e of [first, last) are partitioned with respect to the expression bool(invoke(pred, invoke(proj, e))).
Complexity: Linear.
At most last - first applications of pred and proj.
template<class ForwardIterator, class Predicate> constexpr ForwardIterator partition(ForwardIterator first, ForwardIterator last, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class Predicate> ForwardIterator partition(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Predicate pred); template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> ranges::partition(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::partition(R&& r, Pred pred, Proj proj = {});
Let proj be identity{} for the overloads with no parameter named proj and let E(x) be bool(invoke(​pred, invoke(proj, x))).
Preconditions: For the overloads in namespace std, ForwardIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]).
Effects: Places all the elements e in [first, last) that satisfy E(e) before all the elements that do not.
Returns: Let i be an iterator such that E(*j) is true for every iterator j in [first, i) and false for every iterator j in [i, last).
Returns:
  • i for the overloads in namespace std.
  • {i, last} for the overloads in namespace ranges.
Complexity: Let :
  • For the overload with no ExecutionPolicy, exactly N applications of the predicate and projection.
    At most swaps if the type of first meets the Cpp17BidirectionalIterator requirements for the overloads in namespace std or models bidirectional_iterator for the overloads in namespace ranges, and at most N swaps otherwise.
  • For the overload with an ExecutionPolicy, swaps and applications of the predicate.
template<class BidirectionalIterator, class Predicate> BidirectionalIterator constexpr stable_partition(BidirectionalIterator first, BidirectionalIterator last, Predicate pred); template<class ExecutionPolicy, class BidirectionalIterator, class Predicate> BidirectionalIterator stable_partition(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator last, Predicate pred); template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires permutable<I> constexpr subrange<I> ranges::stable_partition(I first, S last, Pred pred, Proj proj = {}); template<bidirectional_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> ranges::stable_partition(R&& r, Pred pred, Proj proj = {});
Let proj be identity{} for the overloads with no parameter named proj and let E(x) be bool(invoke(​pred, invoke(proj, x))).
Preconditions: For the overloads in namespace std, BidirectionalIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Places all the elements e in [first, last) that satisfy E(e) before all the elements that do not.
The relative order of the elements in both groups is preserved.
Returns: Let i be an iterator such that for every iterator j in [first, i), E(*j) is true, and for every iterator j in the range [i, last), E(*j) is false.
Returns:
  • i for the overloads in namespace std.
  • {i, last} for the overloads in namespace ranges.
Complexity: Let N = last - first:
  • For the overloads with no ExecutionPolicy, at most swaps, but only swaps if there is enough extra memory.
    Exactly N applications of the predicate and projection.
  • For the overload with an ExecutionPolicy, swaps and applications of the predicate.
template<class InputIterator, class OutputIterator1, class OutputIterator2, class Predicate> constexpr pair<OutputIterator1, OutputIterator2> partition_copy(InputIterator first, InputIterator last, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred); template<class ExecutionPolicy, class ForwardIterator, class ForwardIterator1, class ForwardIterator2, class Predicate> pair<ForwardIterator1, ForwardIterator2> partition_copy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, ForwardIterator1 out_true, ForwardIterator2 out_false, Predicate pred); template<input_iterator I, sentinel_for<I> S, weakly_incrementable O1, weakly_incrementable O2, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O1> && indirectly_copyable<I, O2> constexpr ranges::partition_copy_result<I, O1, O2> ranges::partition_copy(I first, S last, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); template<input_range R, weakly_incrementable O1, weakly_incrementable O2, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O1> && indirectly_copyable<iterator_t<R>, O2> constexpr ranges::partition_copy_result<borrowed_iterator_t<R>, O1, O2> ranges::partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {});
Let proj be identity{} for the overloads with no parameter named proj and let E(x) be bool(invoke(​pred, invoke(proj, x))).
Mandates: For the overloads in namespace std, the expression *first is writable ([iterator.requirements.general]) to out_true and out_false.
Preconditions: The input range and output ranges do not overlap.
[Note 1: 
For the overload with an ExecutionPolicy, there might be a performance cost if first's value type does not meet the Cpp17CopyConstructible requirements.
— end note]
Effects: For each iterator i in [first, last), copies *i to the output range beginning with out_true if E(*i) is true, or to the output range beginning with out_false otherwise.
Returns: Let o1 be the end of the output range beginning at out_true, and o2 the end of the output range beginning at out_false.
Returns
  • {o1, o2} for the overloads in namespace std.
  • {last, o1, o2} for the overloads in namespace ranges.
Complexity: Exactly last - first applications of pred and proj.
template<class ForwardIterator, class Predicate> constexpr ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, Predicate pred); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr I ranges::partition_point(I first, S last, Pred pred, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> ranges::partition_point(R&& r, Pred pred, Proj proj = {});
Let proj be identity{} for the overloads with no parameter named proj and let E(x) be bool(invoke(​pred, invoke(proj, x))).
Preconditions: The elements e of [first, last) are partitioned with respect to E(e).
Returns: An iterator mid such that E(*i) is true for all iterators i in [first, mid), and false for all iterators i in [mid, last).
Complexity: applications of pred and proj.

26.8.6 Merge [alg.merge]

template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator merge(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::merge_result<I1, I2, O> ranges::merge(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::merge_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> ranges::merge(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let N be (last1 - first1) + (last2 - first2).
Let comp be less{}, proj1 be identity{}, and proj2 be identity{}, for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
The resulting range does not overlap with either of the original ranges.
Effects: Copies all the elements of the two ranges [first1, last1) and [first2, last2) into the range [result, result_last), where result_last is result + N.
If an element a precedes b in an input range, a is copied into the output range before b.
If e1 is an element of [first1, last1) and e2 of [first2, last2), e2 is copied into the output range before e1 if and only if bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1))) is true.
Returns:
  • result_last for the overloads in namespace std.
  • {last1, last2, result_last} for the overloads in namespace ranges.
Complexity:
  • For the overloads with no ExecutionPolicy, at most comparisons and applications of each projection.
  • For the overloads with an ExecutionPolicy, comparisons.
Remarks: Stable ([algorithm.stable]).
template<class BidirectionalIterator> constexpr void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template<class ExecutionPolicy, class BidirectionalIterator> void inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr void inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template<class ExecutionPolicy, class BidirectionalIterator, class Compare> void inplace_merge(ExecutionPolicy&& exec, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp); template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: [first, middle) and [middle, last) are valid ranges sorted with respect to comp and proj.
For the overloads in namespace std, BidirectionalIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Merges two sorted consecutive ranges [first, middle) and [middle, last), putting the result of the merge into the range [first, last).
The resulting range is sorted with respect to comp and proj.
Returns: last for the overload in namespace ranges.
Complexity: Let :
  • For the overloads with no ExecutionPolicy, and if enough additional memory is available, exactly comparisons.
  • Otherwise, comparisons.
In either case, twice as many projections as comparisons.
Remarks: Stable.
template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {});
Effects: Equivalent to: return ranges::inplace_merge(ranges::begin(r), middle, ranges::end(r), comp, proj);

26.8.7 Set operations on sorted structures [alg.set.operations]

26.8.7.1 General [alg.set.operations.general]

Subclause [alg.set.operations] defines all the basic set operations on sorted structures.
They also work with multisets ([multiset]) containing multiple copies of equivalent elements.
The semantics of the set operations are generalized to multisets in a standard way by defining set_union to contain the maximum number of occurrences of every element, set_intersection to contain the minimum, and so on.

26.8.7.2 includes [includes]

template<class InputIterator1, class InputIterator2> constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class InputIterator1, class InputIterator2, class Compare> constexpr bool includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> bool includes(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = ranges::less> constexpr bool ranges::includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool ranges::includes(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let comp be less{}, proj1 be identity{}, and proj2 be identity{}, for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
Returns: true if and only if [first2, last2) is a subsequence of [first1, last1).
[Note 1: 
A sequence S is a subsequence of another sequence T if S can be obtained from T by removing some, all, or none of T's elements and keeping the remaining elements in the same order.
— end note]
Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.

26.8.7.3 set_union [set.union]

template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_union(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_union(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::set_union_result<I1, I2, O> ranges::set_union(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::set_union_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> ranges::set_union(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let comp be less{}, and proj1 and proj2 be identity{} for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
The resulting range does not overlap with either of the original ranges.
Effects: Constructs a sorted union of the elements from the two ranges; that is, the set of elements that are present in one or both of the ranges.
Returns: Let result_last be the end of the constructed range.
Returns
  • result_last for the overloads in namespace std.
  • {last1, last2, result_last} for the overloads in namespace ranges.
Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
Remarks: Stable ([algorithm.stable]).
If [first1, last1) contains m elements that are equivalent to each other and [first2, last2) contains n elements that are equivalent to them, then all m elements from the first range are copied to the output range, in order, and then the final elements from the second range are copied to the output range, in order.

26.8.7.4 set_intersection [set.intersection]

template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_intersection(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::set_intersection_result<I1, I2, O> ranges::set_intersection(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::set_intersection_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> ranges::set_intersection(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let comp be less{}, and proj1 and proj2 be identity{} for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
The resulting range does not overlap with either of the original ranges.
Effects: Constructs a sorted intersection of the elements from the two ranges; that is, the set of elements that are present in both of the ranges.
Returns: Let result_last be the end of the constructed range.
Returns
  • result_last for the overloads in namespace std.
  • {last1, last2, result_last} for the overloads in namespace ranges.
Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
Remarks: Stable ([algorithm.stable]).
If [first1, last1) contains m elements that are equivalent to each other and [first2, last2) contains n elements that are equivalent to them, the first elements are copied from the first range to the output range, in order.

26.8.7.5 set_difference [set.difference]

template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::set_difference_result<I1, O> ranges::set_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::set_difference_result<borrowed_iterator_t<R1>, O> ranges::set_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let comp be less{}, and proj1 and proj2 be identity{} for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
The resulting range does not overlap with either of the original ranges.
Effects: Copies the elements of the range [first1, last1) which are not present in the range [first2, last2) to the range beginning at result.
The elements in the constructed range are sorted.
Returns: Let result_last be the end of the constructed range.
Returns
  • result_last for the overloads in namespace std.
  • {last1, result_last} for the overloads in namespace ranges.
Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
Remarks: If [first1, last1) contains m elements that are equivalent to each other and [first2, last2) contains n elements that are equivalent to them, the last elements from [first1, last1) are copied to the output range, in order.

26.8.7.6 set_symmetric_difference [set.symmetric.difference]

template<class InputIterator1, class InputIterator2, class OutputIterator> constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator> ForwardIterator set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result); template<class InputIterator1, class InputIterator2, class OutputIterator, class Compare> constexpr OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class ForwardIterator, class Compare> ForwardIterator set_symmetric_difference(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, ForwardIterator result, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<I1, I2, O, Comp, Proj1, Proj2> constexpr ranges::set_symmetric_difference_result<I1, I2, O> ranges::set_symmetric_difference(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, weakly_incrementable O, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> requires mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2> constexpr ranges::set_symmetric_difference_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> ranges::set_symmetric_difference(R1&& r1, R2&& r2, O result, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Let comp be less{}, and proj1 and proj2 be identity{} for the overloads with no parameters by those names.
Preconditions: The ranges [first1, last1) and [first2, last2) are sorted with respect to comp and proj1 or proj2, respectively.
The resulting range does not overlap with either of the original ranges.
Effects: Copies the elements of the range [first1, last1) that are not present in the range [first2, last2), and the elements of the range [first2, last2) that are not present in the range [first1, last1) to the range beginning at result.
The elements in the constructed range are sorted.
Returns: Let result_last be the end of the constructed range.
Returns
  • result_last for the overloads in namespace std.
  • {last1, last2, result_last} for the overloads in namespace ranges.
Complexity: At most 2 * ((last1 - first1) + (last2 - first2)) - 1 comparisons and applications of each projection.
Remarks: Stable ([algorithm.stable]).
If [first1, last1) contains m elements that are equivalent to each other and [first2, last2) contains n elements that are equivalent to them, then of those elements shall be copied to the output range: the last of these elements from [first1, last1) if , and the last of these elements from [first2, last2) if .
In either case, the elements are copied in order.

26.8.8 Heap operations [alg.heap.operations]

26.8.8.1 General [alg.heap.operations.general]

A random access range [a, b) is a heap with respect to comp and proj for a comparator and projection comp and proj if its elements are organized such that:
  • With N = b - a, for all i, , bool(invoke(comp, invoke(proj, a[]), invoke(​proj, a[i]))) is false.
  • *a may be removed by pop_heap, or a new element added by push_heap, in time.
These properties make heaps useful as priority queues.
make_heap converts a range into a heap and sort_heap turns a heap into a sorted sequence.

26.8.8.2 push_heap [push.heap]

template<class RandomAccessIterator> constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void push_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::push_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::push_heap(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: The range [first, last - 1) is a valid heap with respect to comp and proj.
For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible requirements (Table 31) and the Cpp17MoveAssignable requirements (Table 33).
Effects: Places the value in the location last - 1 into the resulting heap [first, last).
Returns: last for the overloads in namespace ranges.
Complexity: At most comparisons and twice as many projections.

26.8.8.3 pop_heap [pop.heap]

template<class RandomAccessIterator> constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void pop_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::pop_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::pop_heap(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: The range [first, last) is a valid non-empty heap with respect to comp and proj.
For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Swaps the value in the location first with the value in the location last - 1 and makes [first, last - 1) into a heap with respect to comp and proj.
Returns: last for the overloads in namespace ranges.
Complexity: At most comparisons and twice as many projections.

26.8.8.4 make_heap [make.heap]

template<class RandomAccessIterator> constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::make_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::make_heap(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Constructs a heap with respect to comp and proj out of the range [first, last).
Returns: last for the overloads in namespace ranges.
Complexity: At most 3(last - first) comparisons and twice as many projections.

26.8.8.5 sort_heap [sort.heap]

template<class RandomAccessIterator> constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr void sort_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr I ranges::sort_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> ranges::sort_heap(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Preconditions: The range [first, last) is a valid heap with respect to comp and proj.
For the overloads in namespace std, RandomAccessIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]) and the type of *first meets the Cpp17MoveConstructible (Table 31) and Cpp17MoveAssignable (Table 33) requirements.
Effects: Sorts elements in the heap [first, last) with respect to comp and proj.
Returns: last for the overloads in namespace ranges.
Complexity: At most comparisons, where , and twice as many projections.

26.8.8.6 is_heap [is.heap]

template<class RandomAccessIterator> constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last);
Effects: Equivalent to: return is_heap_until(first, last) == last;
template<class ExecutionPolicy, class RandomAccessIterator> bool is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last);
Effects: Equivalent to: return is_heap_until(std::forward<ExecutionPolicy>(exec), first, last) == last;
template<class RandomAccessIterator, class Compare> constexpr bool is_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
Effects: Equivalent to: return is_heap_until(first, last, comp) == last;
template<class ExecutionPolicy, class RandomAccessIterator, class Compare> bool is_heap(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp);
Effects: Equivalent to: return is_heap_until(std::forward<ExecutionPolicy>(exec), first, last, comp) == last;
template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr bool ranges::is_heap(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool ranges::is_heap(R&& r, Comp comp = {}, Proj proj = {});
Effects: Equivalent to: return ranges​::​is_heap_until(first, last, comp, proj) == last;
template<class RandomAccessIterator> constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last); template<class ExecutionPolicy, class RandomAccessIterator> RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> constexpr RandomAccessIterator is_heap_until(RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<class ExecutionPolicy, class RandomAccessIterator, class Compare> RandomAccessIterator is_heap_until(ExecutionPolicy&& exec, RandomAccessIterator first, RandomAccessIterator last, Compare comp); template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I ranges::is_heap_until(I first, S last, Comp comp = {}, Proj proj = {}); template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::is_heap_until(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Returns: The last iterator i in [first, last] for which the range [first, i) is a heap with respect to comp and proj.
Complexity: Linear.

26.8.9 Minimum and maximum [alg.min.max]

template<class T> constexpr const T& min(const T& a, const T& b); template<class T, class Compare> constexpr const T& min(const T& a, const T& b, Compare comp); template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& ranges::min(const T& a, const T& b, Comp comp = {}, Proj proj = {});
Preconditions: For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: The smaller value.
Returns the first argument when the arguments are equivalent.
Complexity: Exactly one comparison and two applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class T> constexpr T min(initializer_list<T> r); template<class T, class Compare> constexpr T min(initializer_list<T> r, Compare comp); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr T ranges::min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> ranges::min(R&& r, Comp comp = {}, Proj proj = {});
Preconditions: ranges​::​distance(r) > 0.
For the overloads in namespace std, T meets the Cpp17CopyConstructible requirements.
For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: The smallest value in the input range.
Returns a copy of the leftmost element when several elements are equivalent to the smallest.
Complexity: Exactly ranges​::​distance(r) - 1 comparisons and twice as many applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class T> constexpr const T& max(const T& a, const T& b); template<class T, class Compare> constexpr const T& max(const T& a, const T& b, Compare comp); template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& ranges::max(const T& a, const T& b, Comp comp = {}, Proj proj = {});
Preconditions: For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: The larger value.
Returns the first argument when the arguments are equivalent.
Complexity: Exactly one comparison and two applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class T> constexpr T max(initializer_list<T> r); template<class T, class Compare> constexpr T max(initializer_list<T> r, Compare comp); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr T ranges::max(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> ranges::max(R&& r, Comp comp = {}, Proj proj = {});
Preconditions: ranges​::​distance(r) > 0.
For the overloads in namespace std, T meets the Cpp17CopyConstructible requirements.
For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: The largest value in the input range.
Returns a copy of the leftmost element when several elements are equivalent to the largest.
Complexity: Exactly ranges​::​distance(r) - 1 comparisons and twice as many applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class T> constexpr pair<const T&, const T&> minmax(const T& a, const T& b); template<class T, class Compare> constexpr pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp); template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr ranges::minmax_result<const T&> ranges::minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {});
Preconditions: For the first form, T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: {b, a} if b is smaller than a, and {a, b} otherwise.
Complexity: Exactly one comparison and two applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class T> constexpr pair<T, T> minmax(initializer_list<T> t); template<class T, class Compare> constexpr pair<T, T> minmax(initializer_list<T> t, Compare comp); template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr ranges::minmax_result<T> ranges::minmax(initializer_list<T> r, Comp comp = {}, Proj proj = {}); template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr ranges::minmax_result<range_value_t<R>> ranges::minmax(R&& r, Comp comp = {}, Proj proj = {});
Preconditions: ranges​::​distance(r) > 0.
For the overloads in namespace std, T meets the Cpp17CopyConstructible requirements.
For the first form, type T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: Let X be the return type.
Returns X{x, y}, where x is a copy of the leftmost element with the smallest value and y a copy of the rightmost element with the largest value in the input range.
Complexity: At most applications of the corresponding predicate and twice as many applications of the projection, if any.
Remarks: An invocation may explicitly specify an argument for the template parameter T of the overloads in namespace std.
template<class ForwardIterator> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator min_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator min_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I ranges::min_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::min_element(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Returns: The first iterator i in the range [first, last) such that for every iterator j in the range [first, last), bool(invoke(comp, invoke(proj, *j), invoke(proj, *i))) is false.
Returns last if first == last.
Complexity: Exactly comparisons and twice as many projections.
template<class ForwardIterator> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> ForwardIterator max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr ForwardIterator max_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class Compare> ForwardIterator max_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr I ranges::max_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> ranges::max_element(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for the overloads with no parameters by those names.
Returns: The first iterator i in the range [first, last) such that for every iterator j in the range [first, last), bool(invoke(comp, invoke(proj, *i), invoke(proj, *j))) is false.
Returns last if first == last.
Complexity: Exactly comparisons and twice as many projections.
template<class ForwardIterator> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator> pair<ForwardIterator, ForwardIterator> minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last); template<class ForwardIterator, class Compare> constexpr pair<ForwardIterator, ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, Compare comp); template<class ExecutionPolicy, class ForwardIterator, class Compare> pair<ForwardIterator, ForwardIterator> minmax_element(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Compare comp); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<I> ranges::minmax_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<borrowed_iterator_t<R>> ranges::minmax_element(R&& r, Comp comp = {}, Proj proj = {});
Returns: {first, first} if [first, last) is empty, otherwise {m, M}, where m is the first iterator in [first, last) such that no iterator in the range refers to a smaller element, and where M is the last iterator207 in [first, last) such that no iterator in the range refers to a larger element.
Complexity: Let N be last - first.
At most comparisons and twice as many applications of the projection, if any.
207)207)
This behavior intentionally differs from max_element.

26.8.10 Bounded value [alg.clamp]

template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi); template<class T, class Compare> constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp); template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr const T& ranges::clamp(const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {});
Let comp be less{} for the overloads with no parameter comp, and let proj be identity{} for the overloads with no parameter proj.
Preconditions: bool(invoke(comp, invoke(proj, hi), invoke(proj, lo))) is false.
For the first form, type T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: lo if bool(invoke(comp, invoke(proj, v), invoke(proj, lo))) is true, hi if bool(​invoke(comp, invoke(proj, hi), invoke(proj, v))) is true, otherwise v.
[Note 1: 
If NaN is avoided, T can be a floating-point type.
— end note]
Complexity: At most two comparisons and three applications of the projection.

26.8.11 Lexicographical comparison [alg.lex.comparison]

template<class InputIterator1, class InputIterator2> constexpr bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> bool lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); template<class InputIterator1, class InputIterator2, class Compare> constexpr bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class Compare> bool lexicographical_compare(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, Compare comp); template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = ranges::less> constexpr bool ranges::lexicographical_compare(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool ranges::lexicographical_compare(R1&& r1, R2&& r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {});
Returns: true if and only if the sequence of elements defined by the range [first1, last1) is lexicographically less than the sequence of elements defined by the range [first2, last2).
Complexity: At most 2 min(last1 - first1,  last2 - first2) applications of the corresponding comparison and each projection, if any.
Remarks: If two sequences have the same number of elements and their corresponding elements (if any) are equivalent, then neither sequence is lexicographically less than the other.
If one sequence is a proper prefix of the other, then the shorter sequence is lexicographically less than the longer sequence.
Otherwise, the lexicographical comparison of the sequences yields the same result as the comparison of the first corresponding pair of elements that are not equivalent.
[Example 1: 
ranges​::​lexicographical_compare(I1, S1, I2, S2, Comp, Proj1, Proj2) can be implemented as: for ( ; first1 != last1 && first2 != last2 ; ++first1, (void) ++first2) { if (invoke(comp, invoke(proj1, *first1), invoke(proj2, *first2))) return true; if (invoke(comp, invoke(proj2, *first2), invoke(proj1, *first1))) return false; } return first1 == last1 && first2 != last2;
— end example]
[Note 1: 
An empty sequence is lexicographically less than any non-empty sequence, but not less than any empty sequence.
— end note]

26.8.12 Three-way comparison algorithms [alg.three.way]

template<class InputIterator1, class InputIterator2, class Cmp> constexpr auto lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, Cmp comp) -> decltype(comp(*b1, *b2));
Let N be min(e1 - b1, e2 - b2).
Let E(n) be comp(*(b1 + n), *(b2 + n)).
Mandates: decltype(comp(*b1, *b2)) is a comparison category type.
Returns: E(i), where i is the smallest integer in [0, N) such that E(i) != 0 is true, or (e1 - b1) <=> (e2 - b2) if no such integer exists.
Complexity: At most N applications of comp.
template<class InputIterator1, class InputIterator2> constexpr auto lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2);
Effects: Equivalent to: return lexicographical_compare_three_way(b1, e1, b2, e2, compare_three_way());

26.8.13 Permutation generators [alg.permutation.generators]

template<class BidirectionalIterator> constexpr bool next_permutation(BidirectionalIterator first, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr bool next_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp); template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr ranges::next_permutation_result<I> ranges::next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr ranges::next_permutation_result<borrowed_iterator_t<R>> ranges::next_permutation(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: For the overloads in namespace std, BidirectionalIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]).
Effects: Takes a sequence defined by the range [first, last) and transforms it into the next permutation.
The next permutation is found by assuming that the set of all permutations is lexicographically sorted with respect to comp and proj.
If no such permutation exists, transforms the sequence into the first permutation; that is, the ascendingly-sorted one.
Returns: Let B be true if a next permutation was found and otherwise false.
Returns:
  • B for the overloads in namespace std.
  • { last, B } for the overloads in namespace ranges.
Complexity: At most (last - first) / 2 swaps.
template<class BidirectionalIterator> constexpr bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last); template<class BidirectionalIterator, class Compare> constexpr bool prev_permutation(BidirectionalIterator first, BidirectionalIterator last, Compare comp); template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr ranges::prev_permutation_result<I> ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr ranges::prev_permutation_result<borrowed_iterator_t<R>> ranges::prev_permutation(R&& r, Comp comp = {}, Proj proj = {});
Let comp be less{} and proj be identity{} for overloads with no parameters by those names.
Preconditions: For the overloads in namespace std, BidirectionalIterator meets the Cpp17ValueSwappable requirements ([swappable.requirements]).
Effects: Takes a sequence defined by the range [first, last) and transforms it into the previous permutation.
The previous permutation is found by assuming that the set of all permutations is lexicographically sorted with respect to comp and proj.
If no such permutation exists, transforms the sequence into the last permutation; that is, the descendingly-sorted one.
Returns: Let B be true if a previous permutation was found and otherwise false.
Returns:
  • B for the overloads in namespace std.
  • { last, B } for the overloads in namespace ranges.
Complexity: At most (last - first) / 2 swaps.

26.9 Header <numeric> synopsis [numeric.ops.overview]

namespace std { // [accumulate], accumulate template<class InputIterator, class T> constexpr T accumulate(InputIterator first, InputIterator last, T init); template<class InputIterator, class T, class BinaryOperation> constexpr T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op); // [reduce], reduce template<class InputIterator> constexpr typename iterator_traits<InputIterator>::value_type reduce(InputIterator first, InputIterator last); template<class InputIterator, class T> constexpr T reduce(InputIterator first, InputIterator last, T init); template<class InputIterator, class T, class BinaryOperation> constexpr T reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator> typename iterator_traits<ForwardIterator>::value_type reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template<class ExecutionPolicy, class ForwardIterator, class T> T reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, T init); template<class ExecutionPolicy, class ForwardIterator, class T, class BinaryOperation> T reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op); // [inner.product], inner product template<class InputIterator1, class InputIterator2, class T> constexpr T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init); template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2> constexpr T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2); // [transform.reduce], transform reduce template<class InputIterator1, class InputIterator2, class T> constexpr T transform_reduce(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init); template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2> constexpr T transform_reduce(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2); template<class InputIterator, class T, class BinaryOperation, class UnaryOperation> constexpr T transform_reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> T transform_reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation1, class BinaryOperation2> T transform_reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2); template<class ExecutionPolicy, class ForwardIterator, class T, class BinaryOperation, class UnaryOperation> T transform_reduce(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op); // [partial.sum], partial sum template<class InputIterator, class OutputIterator> constexpr OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result); template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); // [exclusive.scan], exclusive scan template<class InputIterator, class OutputIterator, class T> constexpr OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init); template<class InputIterator, class OutputIterator, class T, class BinaryOperation> constexpr OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation> ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op); // [inclusive.scan], inclusive scan template<class InputIterator, class OutputIterator> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result); template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); template<class InputIterator, class OutputIterator, class BinaryOperation, class T> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class T> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init); // [transform.exclusive.scan], transform exclusive scan template<class InputIterator, class OutputIterator, class T, class BinaryOperation, class UnaryOperation> constexpr OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation, class UnaryOperation> ForwardIterator2 transform_exclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op, UnaryOperation unary_op); // [transform.inclusive.scan], transform inclusive scan template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op); template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation, class T> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation, class T> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init); // [adjacent.difference], adjacent difference template<class InputIterator, class OutputIterator> constexpr OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result); template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 adjacent_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation> ForwardIterator2 adjacent_difference(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); // [numeric.iota], iota template<class ForwardIterator, class T> constexpr void iota(ForwardIterator first, ForwardIterator last, T value); namespace ranges { template<class O, class T> using iota_result = out_value_result<O, T>; template<input_or_output_iterator O, sentinel_for<O> S, weakly_incrementable T> requires indirectly_writable<O, const T&> constexpr iota_result<O, T> iota(O first, S last, T value); template<weakly_incrementable T, output_range<const T&> R> constexpr iota_result<borrowed_iterator_t<R>, T> iota(R&& r, T value); } // [numeric.ops.gcd], greatest common divisor template<class M, class N> constexpr common_type_t<M, N> gcd(M m, N n); // [numeric.ops.lcm], least common multiple template<class M, class N> constexpr common_type_t<M, N> lcm(M m, N n); // [numeric.ops.midpoint], midpoint template<class T> constexpr T midpoint(T a, T b) noexcept; template<class T> constexpr T* midpoint(T* a, T* b); // [numeric.sat], saturation arithmetic template<class T> constexpr T add_sat(T x, T y) noexcept; // freestanding template<class T> constexpr T sub_sat(T x, T y) noexcept; // freestanding template<class T> constexpr T mul_sat(T x, T y) noexcept; // freestanding template<class T> constexpr T div_sat(T x, T y) noexcept; // freestanding template<class T, class U> constexpr T saturate_cast(U x) noexcept; // freestanding }

26.10 Generalized numeric operations [numeric.ops]

26.10.1 General [numeric.ops.general]

[Note 1: 
The use of closed ranges as well as semi-open ranges to specify requirements throughout [numeric.ops] is intentional.
— end note]

26.10.2 Definitions [numerics.defns]

Define GENERALIZED_NONCOMMUTATIVE_SUM(op, a1, ..., aN) as follows:
  • a1 when N is 1, otherwise
  • op(GENERALIZED_NONCOMMUTATIVE_SUM(op, a1, ..., aK),
    op(GENERALIZED_NONCOMMUTATIVE_SUM(op, aM, ..., aN)) for any K where .
Define GENERALIZED_SUM(op, a1, ..., aN) as GENERALIZED_NONCOMMUTATIVE_SUM(op, b1, ..., bN), where b1, ..., bN may be any permutation of a1, ..., aN.

26.10.3 Accumulate [accumulate]

template<class InputIterator, class T> constexpr T accumulate(InputIterator first, InputIterator last, T init); template<class InputIterator, class T, class BinaryOperation> constexpr T accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);
Preconditions: T meets the Cpp17CopyConstructible (Table 32) and Cpp17CopyAssignable (Table 34) requirements.
In the range [first, last], binary_op neither modifies elements nor invalidates iterators or subranges.208
Effects: Computes its result by initializing the accumulator acc with the initial value init and then modifies it with acc = std​::​move(acc) + *i or acc = binary_op(std​::​move(acc), *i) for every iterator i in the range [first, last) in order.209
208)208)
The use of fully closed ranges is intentional.
209)209)
accumulate is similar to the APL reduction operator and Common Lisp reduce function, but it avoids the difficulty of defining the result of reduction on an empty sequence by always requiring an initial value.

26.10.4 Reduce [reduce]

template<class InputIterator> constexpr typename iterator_traits<InputIterator>::value_type reduce(InputIterator first, InputIterator last);
Effects: Equivalent to: return reduce(first, last, typename iterator_traits<InputIterator>::value_type{});
template<class ExecutionPolicy, class ForwardIterator> typename iterator_traits<ForwardIterator>::value_type reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last);
Effects: Equivalent to: return reduce(std::forward<ExecutionPolicy>(exec), first, last, typename iterator_traits<ForwardIterator>::value_type{});
template<class InputIterator, class T> constexpr T reduce(InputIterator first, InputIterator last, T init);
Effects: Equivalent to: return reduce(first, last, init, plus<>());
template<class ExecutionPolicy, class ForwardIterator, class T> T reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init);
Effects: Equivalent to: return reduce(std::forward<ExecutionPolicy>(exec), first, last, init, plus<>());
template<class InputIterator, class T, class BinaryOperation> constexpr T reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator, class T, class BinaryOperation> T reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op);
Mandates: All of
  • binary_op(init, *first),
  • binary_op(*first, init),
  • binary_op(init, init), and
  • binary_op(*first, *first)
are convertible to T.
Preconditions:
Returns: GENERALIZED_SUM(binary_op, init, *i, ...) for every i in [first, last).
Complexity: applications of binary_op.
[Note 1: 
The difference between reduce and accumulate is that reduce applies binary_op in an unspecified order, which yields a nondeterministic result for non-associative or non-commutative binary_op such as floating-point addition.
— end note]

26.10.5 Inner product [inner.product]

template<class InputIterator1, class InputIterator2, class T> constexpr T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init); template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2> constexpr T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
Preconditions: T meets the Cpp17CopyConstructible (Table 32) and Cpp17CopyAssignable (Table 34) requirements.
In the ranges [first1, last1] and [first2, first2 + (last1 - first1)] binary_op1 and binary_op2 neither modifies elements nor invalidates iterators or subranges.210
Effects: Computes its result by initializing the accumulator acc with the initial value init and then modifying it with acc = std​::​move(acc) + (*i1) * (*i2) or acc = binary_op1(std​::​move(acc), binary_op2(*i1, *i2)) for every iterator i1 in the range [first1, last1) and iterator i2 in the range [first2, first2 + (last1 - first1)) in order.
210)210)
The use of fully closed ranges is intentional.

26.10.6 Transform reduce [transform.reduce]

template<class InputIterator1, class InputIterator2, class T> constexpr T transform_reduce(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init);
Effects: Equivalent to: return transform_reduce(first1, last1, first2, init, plus<>(), multiplies<>());
template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> T transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init);
Effects: Equivalent to: return transform_reduce(std::forward<ExecutionPolicy>(exec), first1, last1, first2, init, plus<>(), multiplies<>());
template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2> constexpr T transform_reduce(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation1, class BinaryOperation2> T transform_reduce(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, T init, BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
Mandates: All of
  • binary_op1(init, init),
  • binary_op1(init, binary_op2(*first1, *first2)),
  • binary_op1(binary_op2(*first1, *first2), init), and
  • binary_op1(binary_op2(*first1, *first2), binary_op2(*first1, *first2))
are convertible to T.
Preconditions:
  • T meets the Cpp17MoveConstructible (Table 31) requirements.
  • Neither binary_op1 nor binary_op2 invalidates subranges, nor modifies elements in the ranges [first1, last1] and [first2, first2 + (last1 - first1)].
Returns: GENERALIZED_SUM(binary_op1, init, binary_op2(*i, *(first2 + (i - first1))), ...) for every iterator i in [first1, last1).
Complexity: applications each of binary_op1 and binary_op2.
template<class InputIterator, class T, class BinaryOperation, class UnaryOperation> constexpr T transform_reduce(InputIterator first, InputIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator, class T, class BinaryOperation, class UnaryOperation> T transform_reduce(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, T init, BinaryOperation binary_op, UnaryOperation unary_op);
Mandates: All of
  • binary_op(init, init),
  • binary_op(init, unary_op(*first)),
  • binary_op(unary_op(*first), init), and
  • binary_op(unary_op(*first), unary_op(*first))
are convertible to T.
Preconditions:
Returns: GENERALIZED_SUM(binary_op, init, unary_op(*i), ...) for every iterator i in [first, last).
Complexity: applications each of unary_op and binary_op.
[Note 1: 
transform_reduce does not apply unary_op to init.
— end note]

26.10.7 Partial sum [partial.sum]

template<class InputIterator, class OutputIterator> constexpr OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result); template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op);
Mandates: InputIterator's value type is constructible from *first.
The result of the expression std​::​move(acc) + *i or binary_op(std​::​move(acc), *i) is implicitly convertible to InputIterator's value type.
acc is writable ([iterator.requirements.general]) to result.
Preconditions: In the ranges [first, last] and [result, result + (last - first)] binary_op neither modifies elements nor invalidates iterators or subranges.211
Effects: For a non-empty range, the function creates an accumulator acc whose type is InputIterator's value type, initializes it with *first, and assigns the result to *result.
For every iterator i in [first + 1, last) in order, acc is then modified by acc = std​::​move(acc) + *i or acc = binary_op(std​::​move(acc), *i) and the result is assigned to *(result + (i - first)).
Returns: result + (last - first).
Complexity: Exactly (last - first) - 1 applications of the binary operation.
Remarks: result may be equal to first.
211)211)
The use of fully closed ranges is intentional.

26.10.8 Exclusive scan [exclusive.scan]

template<class InputIterator, class OutputIterator, class T> constexpr OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init);
Effects: Equivalent to: return exclusive_scan(first, last, result, init, plus<>());
template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T> ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init);
Effects: Equivalent to: return exclusive_scan(std::forward<ExecutionPolicy>(exec), first, last, result, init, plus<>());
template<class InputIterator, class OutputIterator, class T, class BinaryOperation> constexpr OutputIterator exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation> ForwardIterator2 exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op);
Mandates: All of
  • binary_op(init, init),
  • binary_op(init, *first), and
  • binary_op(*first, *first)
are convertible to T.
Preconditions:
  • T meets the Cpp17MoveConstructible (Table 31) requirements.
  • binary_op neither invalidates iterators or subranges, nor modifies elements in the ranges [first, last] or [result, result + (last - first)].
Effects: For each integer K in [0, last - first) assigns through result + K the value of: GENERALIZED_NONCOMMUTATIVE_SUM( binary_op, init, *(first + 0), *(first + 1), ..., *(first + K - 1))
Returns: The end of the resulting range beginning at result.
Complexity: applications of binary_op.
Remarks: result may be equal to first.
[Note 1: 
The difference between exclusive_scan and inclusive_scan is that exclusive_scan excludes the input element from the sum.
If binary_op is not mathematically associative, the behavior of exclusive_scan can be nondeterministic.
— end note]

26.10.9 Inclusive scan [inclusive.scan]

template<class InputIterator, class OutputIterator> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result);
Effects: Equivalent to: return inclusive_scan(first, last, result, plus<>());
template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);
Effects: Equivalent to: return inclusive_scan(std::forward<ExecutionPolicy>(exec), first, last, result, plus<>());
template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op); template<class InputIterator, class OutputIterator, class BinaryOperation, class T> constexpr OutputIterator inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class T> ForwardIterator2 inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, T init);
Let U be the value type of decltype(first).
Mandates: If init is provided, all of
  • binary_op(init, init),
  • binary_op(init, *first), and
  • binary_op(*first, *first)
are convertible to T; otherwise, binary_op(*first, *first) is convertible to U.
Preconditions:
  • If init is provided, T meets the Cpp17MoveConstructible (Table 31) requirements; otherwise, U meets the Cpp17MoveConstructible requirements.
  • binary_op neither invalidates iterators or subranges, nor modifies elements in the ranges [first, last] or [result, result + (last - first)].
Effects: For each integer K in [0, last - first) assigns through result + K the value of
  • GENERALIZED_NONCOMMUTATIVE_SUM(
        binary_op, init, *(first + 0), *(first + 1), ..., *(first + K))

    if init is provided, or
  • GENERALIZED_NONCOMMUTATIVE_SUM(
        binary_op, *(first + 0), *(first + 1), ..., *(first + K))

    otherwise.
Returns: The end of the resulting range beginning at result.
Complexity: applications of binary_op.
Remarks: result may be equal to first.
[Note 1: 
The difference between exclusive_scan and inclusive_scan is that inclusive_scan includes the input element in the sum.
If binary_op is not mathematically associative, the behavior of inclusive_scan can be nondeterministic.
— end note]

26.10.10 Transform exclusive scan [transform.exclusive.scan]

template<class InputIterator, class OutputIterator, class T, class BinaryOperation, class UnaryOperation> constexpr OutputIterator transform_exclusive_scan(InputIterator first, InputIterator last, OutputIterator result, T init, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class T, class BinaryOperation, class UnaryOperation> ForwardIterator2 transform_exclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, T init, BinaryOperation binary_op, UnaryOperation unary_op);
Mandates: All of
  • binary_op(init, init),
  • binary_op(init, unary_op(*first)), and
  • binary_op(unary_op(*first), unary_op(*first))
are convertible to T.
Preconditions:
  • T meets the Cpp17MoveConstructible (Table 31) requirements.
  • Neither unary_op nor binary_op invalidates iterators or subranges, nor modifies elements in the ranges [first, last] or [result, result + (last - first)].
Effects: For each integer K in [0, last - first) assigns through result + K the value of: GENERALIZED_NONCOMMUTATIVE_SUM( binary_op, init, unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K - 1)))
Returns: The end of the resulting range beginning at result.
Complexity: applications each of unary_op and binary_op.
Remarks: result may be equal to first.
[Note 1: 
The difference between transform_exclusive_scan and transform_inclusive_scan is that transform_exclusive_scan excludes the input element from the sum.
If binary_op is not mathematically associative, the behavior of transform_exclusive_scan can be nondeterministic.
transform_exclusive_scan does not apply unary_op to init.
— end note]

26.10.11 Transform inclusive scan [transform.inclusive.scan]

template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op); template<class InputIterator, class OutputIterator, class BinaryOperation, class UnaryOperation, class T> constexpr OutputIterator transform_inclusive_scan(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op, UnaryOperation unary_op, T init); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation, class UnaryOperation, class T> ForwardIterator2 transform_inclusive_scan(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op, UnaryOperation unary_op, T init);
Let U be the value type of decltype(first).
Mandates: If init is provided, all of
  • binary_op(init, init),
  • binary_op(init, unary_op(*first)), and
  • binary_op(unary_op(*first), unary_op(*first))
are convertible to T; otherwise, binary_op(unary_op(*first), unary_op(*first)) is convertible to U.
Preconditions:
  • If init is provided, T meets the Cpp17MoveConstructible (Table 31) requirements; otherwise, U meets the Cpp17MoveConstructible requirements.
  • Neither unary_op nor binary_op invalidates iterators or subranges, nor modifies elements in the ranges [first, last] or [result, result + (last - first)].
Effects: For each integer K in [0, last - first) assigns through result + K the value of
  • GENERALIZED_NONCOMMUTATIVE_SUM(
        binary_op, init,
        unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K)))

    if init is provided, or
  • GENERALIZED_NONCOMMUTATIVE_SUM(
        binary_op,
        unary_op(*(first + 0)), unary_op(*(first + 1)), ..., unary_op(*(first + K)))

    otherwise.
Returns: The end of the resulting range beginning at result.
Complexity: applications each of unary_op and binary_op.
Remarks: result may be equal to first.
[Note 1: 
The difference between transform_exclusive_scan and transform_inclusive_scan is that transform_inclusive_scan includes the input element in the sum.
If binary_op is not mathematically associative, the behavior of transform_inclusive_scan can be nondeterministic.
transform_inclusive_scan does not apply unary_op to init.
— end note]

26.10.12 Adjacent difference [adjacent.difference]

template<class InputIterator, class OutputIterator> constexpr OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2> ForwardIterator2 adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result); template<class InputIterator, class OutputIterator, class BinaryOperation> constexpr OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result, BinaryOperation binary_op); template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryOperation> ForwardIterator2 adjacent_difference(ExecutionPolicy&& exec, ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result, BinaryOperation binary_op);
Let T be the value type of decltype(first).
For the overloads that do not take an argument binary_op, let binary_op be an lvalue that denotes an object of type minus<>.
Mandates:
  • For the overloads with no ExecutionPolicy, T is constructible from *first.
    acc (defined below) is writable ([iterator.requirements.general]) to the result output iterator.
    The result of the expression binary_op(val, std​::​move(acc)) is writable to result.
  • For the overloads with an ExecutionPolicy, the result of the expressions binary_op(*first, *first) and *first are writable to result.
Preconditions:
  • For the overloads with no ExecutionPolicy, T meets the Cpp17MoveAssignable (Table 33) requirements.
  • For all overloads, in the ranges [first, last] and [result, result + (last - first)], binary_op neither modifies elements nor invalidates iterators or subranges.212
Effects: For the overloads with no ExecutionPolicy and a non-empty range, the function creates an accumulator acc of type T, initializes it with *first, and assigns the result to *result.
For every iterator i in [first + 1, last) in order, creates an object val whose type is T, initializes it with *i, computes binary_op(val, std​::​move(acc)), assigns the result to *(result + (i - first)), and move assigns from val to acc.
For the overloads with an ExecutionPolicy and a non-empty range, performs *result = *first.
Then, for every d in [1, last - first - 1], performs *(result + d) = binary_op(*(first + d), *(first + (d - 1))).
Returns: result + (last - first).
Complexity: Exactly (last - first) - 1 applications of the binary operation.
Remarks: For the overloads with no ExecutionPolicy, result may be equal to first.
For the overloads with an ExecutionPolicy, the ranges [first, last) and [result, result + (last - first)) shall not overlap.
212)212)
The use of fully closed ranges is intentional.

26.10.13 Iota [numeric.iota]

template<class ForwardIterator, class T> constexpr void iota(ForwardIterator first, ForwardIterator last, T value);
Mandates: T is convertible to ForwardIterator's value type.
The expression ++val, where val has type T, is well-formed.
Effects: For each element referred to by the iterator i in the range [first, last), assigns *i = value and increments value as if by ++value.
Complexity: Exactly last - first increments and assignments.
template<input_or_output_iterator O, sentinel_for<O> S, weakly_incrementable T> requires indirectly_writable<O, const T&> constexpr ranges::iota_result<O, T> ranges::iota(O first, S last, T value); template<weakly_incrementable T, output_range<const T&> R> constexpr ranges::iota_result<borrowed_iterator_t<R>, T> ranges::iota(R&& r, T value);
Effects: Equivalent to: while (first != last) { *first = as_const(value); ++first; ++value; } return {std::move(first), std::move(value)};

26.10.14 Greatest common divisor [numeric.ops.gcd]

template<class M, class N> constexpr common_type_t<M, N> gcd(M m, N n);
Mandates: M and N both are integer types other than cv bool.
Preconditions: |m| and |n| are representable as a value of common_type_t<M, N>.
[Note 1: 
These requirements ensure, for example, that is representable as a value of type M.
— end note]
Returns: Zero when m and n are both zero.
Otherwise, returns the greatest common divisor of |m| and |n|.
Throws: Nothing.

26.10.15 Least common multiple [numeric.ops.lcm]

template<class M, class N> constexpr common_type_t<M, N> lcm(M m, N n);
Mandates: M and N both are integer types other than cv bool.
Preconditions: |m| and |n| are representable as a value of common_type_t<M, N>.
The least common multiple of |m| and |n| is representable as a value of type common_type_t<M, N>.
Returns: Zero when either m or n is zero.
Otherwise, returns the least common multiple of |m| and |n|.
Throws: Nothing.

26.10.16 Midpoint [numeric.ops.midpoint]

template<class T> constexpr T midpoint(T a, T b) noexcept;
Constraints: T is an arithmetic type other than bool.
Returns: Half the sum of a and b.
If T is an integer type and the sum is odd, the result is rounded towards a.
Remarks: No overflow occurs.
If T is a floating-point type, at most one inexact operation occurs.
template<class T> constexpr T* midpoint(T* a, T* b);
Constraints: T is an object type.
Mandates: T is a complete type.
Preconditions: a and b point to, respectively, elements i and j of the same array object x.
[Note 1: 
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose and a pointer past the last element of an array of n elements is considered to be equivalent to a pointer to a hypothetical array element n for this purpose.
— end note]
Returns: A pointer to array element of x, where the result of the division is truncated towards zero.

26.10.17 Saturation arithmetic [numeric.sat]

26.10.17.1 Arithmetic functions [numeric.sat.func]

In the following descriptions, an arithmetic operation is performed as a mathematical operation with infinite range and then it is determined whether the mathematical result fits into the result type.
template<class T> constexpr T add_sat(T x, T y) noexcept;
Constraints: T is a signed or unsigned integer type ([basic.fundamental]).
Returns: If is representable as a value of type T, ; otherwise, either the largest or smallest representable value of type T, whichever is closer to the value of .
template<class T> constexpr T sub_sat(T x, T y) noexcept;
Constraints: T is a signed or unsigned integer type ([basic.fundamental]).
Returns: If is representable as a value of type T, ; otherwise, either the largest or smallest representable value of type T, whichever is closer to the value of .
template<class T> constexpr T mul_sat(T x, T y) noexcept;
Constraints: T is a signed or unsigned integer type ([basic.fundamental]).
Returns: If x ×y is representable as a value of type T, x ×y; otherwise, either the largest or smallest representable value of type T, whichever is closer to the value of x ×y.
template<class T> constexpr T div_sat(T x, T y) noexcept;
Constraints: T is a signed or unsigned integer type ([basic.fundamental]).
Preconditions: y != 0 is true.
Returns: If T is a signed integer type and x == numeric_limits<T>​::​min() && y == -1 is true, numeric_limits<T>​::​max(), otherwise, x / y.
Remarks: A function call expression that violates the precondition in the Preconditions element is not a core constant expression ([expr.const]).

26.10.17.2 Casting [numeric.sat.cast]

template<class R, class T> constexpr R saturate_cast(T x) noexcept;
Constraints: R and T are signed or unsigned integer types ([basic.fundamental]).
Returns: If x is representable as a value of type R, x; otherwise, either the largest or smallest representable value of type R, whichever is closer to the value of x.

26.11 Specialized <memory> algorithms [specialized.algorithms]

26.11.1 General [specialized.algorithms.general]

The contents specified in [specialized.algorithms] are declared in the header <memory>.
Unless otherwise specified, if an exception is thrown in the following algorithms, objects constructed by a placement new-expression ([expr.new]) are destroyed in an unspecified order before allowing the exception to propagate.
[Note 1: 
When new objects are created by the algorithms specified in [specialized.algorithms], the lifetime ends for any existing objects (including potentially-overlapping subobjects [intro.object]) in storage that is reused [basic.life].
— end note]
Some algorithms specified in [specialized.algorithms] make use of the following exposition-only function templates: template<class T> constexpr void* voidify(T& obj) noexcept { return addressof(obj); } template<class I> decltype(auto) deref-move(I& it) { if constexpr (is_lvalue_reference_v<decltype(*it)>) return std::move(*it); else return *it; }

26.11.2 Special memory concepts [special.mem.concepts]

Some algorithms in this subclause are constrained with the following exposition-only concepts:
template<class I> concept nothrow-input-iterator = // exposition only input_iterator<I> && is_lvalue_reference_v<iter_reference_t<I>> && same_as<remove_cvref_t<iter_reference_t<I>>, iter_value_t<I>>;
A type I models nothrow-input-iterator only if no exceptions are thrown from increment, copy construction, move construction, copy assignment, move assignment, or indirection through valid iterators.
[Note 1: 
This concept allows some input_iterator ([iterator.concept.input]) operations to throw exceptions.
— end note]
template<class S, class I> concept nothrow-sentinel-for = sentinel_for<S, I>; // exposition only
Types S and I model nothrow-sentinel-for only if no exceptions are thrown from copy construction, move construction, copy assignment, move assignment, or comparisons between valid values of type I and S.
[Note 2: 
This concept allows some sentinel_for ([iterator.concept.sentinel]) operations to throw exceptions.
— end note]
template<class R> concept nothrow-input-range = // exposition only range<R> && nothrow-input-iterator<iterator_t<R>> && nothrow-sentinel-for<sentinel_t<R>, iterator_t<R>>;
A type R models nothrow-input-range only if no exceptions are thrown from calls to ranges​::​begin and ranges​::​end on an object of type R.
template<class I> concept nothrow-forward-iterator = // exposition only nothrow-input-iterator<I> && forward_iterator<I> && nothrow-sentinel-for<I, I>;
[Note 3: 
This concept allows some forward_iterator ([iterator.concept.forward]) operations to throw exceptions.
— end note]
template<class R> concept nothrow-forward-range = // exposition only nothrow-input-range<R> && nothrow-forward-iterator<iterator_t<R>>;

26.11.3 uninitialized_default_construct [uninitialized.construct.default]

template<class NoThrowForwardIterator> constexpr void uninitialized_default_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type;
namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct(I first, S last); template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_default_construct(R&& r); }
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>; return first;
template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_default_construct_n(NoThrowForwardIterator first, Size n);
Effects: Equivalent to: for (; n > 0; (void)++first, --n) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type; return first;
namespace ranges { template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_default_construct_n(I first, iter_difference_t<I> n); }
Effects: Equivalent to: return uninitialized_default_construct(counted_iterator(first, n), default_sentinel).base();

26.11.4 uninitialized_value_construct [uninitialized.construct.value]

template<class NoThrowForwardIterator> constexpr void uninitialized_value_construct(NoThrowForwardIterator first, NoThrowForwardIterator last);
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type();
namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct(I first, S last); template<nothrow-forward-range R> requires default_initializable<range_value_t<R>> constexpr borrowed_iterator_t<R> uninitialized_value_construct(R&& r); }
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>(); return first;
template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator uninitialized_value_construct_n(NoThrowForwardIterator first, Size n);
Effects: Equivalent to: for (; n > 0; (void)++first, --n) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type(); return first;
namespace ranges { template<nothrow-forward-iterator I> requires default_initializable<iter_value_t<I>> constexpr I uninitialized_value_construct_n(I first, iter_difference_t<I> n); }
Effects: Equivalent to: return uninitialized_value_construct(counted_iterator(first, n), default_sentinel).base();

26.11.5 uninitialized_copy [uninitialized.copy]

template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy(InputIterator first, InputIterator last, NoThrowForwardIterator result);
Preconditions: does not overlap with [first, last).
Effects: Equivalent to: for (; first != last; ++result, (void) ++first) ::new (voidify(*result)) typename iterator_traits<NoThrowForwardIterator>::value_type(*first);
Returns: result.
namespace ranges { template<input_iterator I, sentinel_for<I> S1, nothrow-forward-iterator O, nothrow-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> constexpr uninitialized_copy_result<I, O> uninitialized_copy(I ifirst, S1 ilast, O ofirst, S2 olast); template<input_range IR, nothrow-forward-range OR> requires constructible_from<range_value_t<OR>, range_reference_t<IR>> constexpr uninitialized_copy_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_copy(IR&& in_range, OR&& out_range); }
Preconditions: [ofirst, olast) does not overlap with [ifirst, ilast).
Effects: Equivalent to: for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) ::new (voidify(*ofirst)) remove_reference_t<iter_reference_t<O>>(*ifirst); return {std::move(ifirst), ofirst};
template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_copy_n(InputIterator first, Size n, NoThrowForwardIterator result);
Preconditions: does not overlap with .
Effects: Equivalent to: for ( ; n > 0; ++result, (void) ++first, --n) ::new (voidify(*result)) typename iterator_traits<NoThrowForwardIterator>::value_type(*first);
Returns: result.
namespace ranges { template<input_iterator I, nothrow-forward-iterator O, nothrow-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_reference_t<I>> constexpr uninitialized_copy_n_result<I, O> uninitialized_copy_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast); }
Preconditions: [ofirst, olast) does not overlap with .
Effects: Equivalent to: auto t = uninitialized_copy(counted_iterator(std::move(ifirst), n), default_sentinel, ofirst, olast); return {std::move(t.in).base(), t.out};

26.11.6 uninitialized_move [uninitialized.move]

template<class InputIterator, class NoThrowForwardIterator> constexpr NoThrowForwardIterator uninitialized_move(InputIterator first, InputIterator last, NoThrowForwardIterator result);
Preconditions: does not overlap with [first, last).
Effects: Equivalent to: for (; first != last; (void)++result, ++first) ::new (voidify(*result)) typename iterator_traits<NoThrowForwardIterator>::value_type(deref-move(first)); return result;
namespace ranges { template<input_iterator I, sentinel_for<I> S1, nothrow-forward-iterator O, nothrow-sentinel-for<O> S2> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> constexpr uninitialized_move_result<I, O> uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); template<input_range IR, nothrow-forward-range OR> requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>> constexpr uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>> uninitialized_move(IR&& in_range, OR&& out_range); }
Preconditions: [ofirst, olast) does not overlap with [ifirst, ilast).
Effects: Equivalent to: for (; ifirst != ilast && ofirst != olast; ++ofirst, (void)++ifirst) ::new (voidify(*ofirst)) remove_reference_t<iter_reference_t<O>>(ranges::iter_move(ifirst)); return {std::move(ifirst), ofirst};
[Note 1: 
If an exception is thrown, some objects in the range [ifirst, ilast) are left in a valid, but unspecified state.
— end note]
template<class InputIterator, class Size, class NoThrowForwardIterator> constexpr pair<InputIterator, NoThrowForwardIterator> uninitialized_move_n(InputIterator first, Size n, NoThrowForwardIterator result);
Preconditions: does not overlap with .
Effects: Equivalent to: for (; n > 0; ++result, (void) ++first, --n) ::new (voidify(*result)) typename iterator_traits<NoThrowForwardIterator>::value_type(deref-move(first)); return {first, result};
namespace ranges { template<input_iterator I, nothrow-forward-iterator O, nothrow-sentinel-for<O> S> requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>> constexpr uninitialized_move_n_result<I, O> uninitialized_move_n(I ifirst, iter_difference_t<I> n, O ofirst, S olast); }
Preconditions: [ofirst, olast) does not overlap with .
Effects: Equivalent to: auto t = uninitialized_move(counted_iterator(std::move(ifirst), n), default_sentinel, ofirst, olast); return {std::move(t.in).base(), t.out};
[Note 2: 
If an exception is thrown, some objects in the range are left in a valid but unspecified state.
— end note]

26.11.7 uninitialized_fill [uninitialized.fill]

template<class NoThrowForwardIterator, class T> constexpr void uninitialized_fill(NoThrowForwardIterator first, NoThrowForwardIterator last, const T& x);
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type(x);
namespace ranges { template<nothrow-forward-iterator I, nothrow-sentinel-for<I> S, class T> requires constructible_from<iter_value_t<I>, const T&> constexpr I uninitialized_fill(I first, S last, const T& x); template<nothrow-forward-range R, class T> requires constructible_from<range_value_t<R>, const T&> constexpr borrowed_iterator_t<R> uninitialized_fill(R&& r, const T& x); }
Effects: Equivalent to: for (; first != last; ++first) ::new (voidify(*first)) remove_reference_t<iter_reference_t<I>>(x); return first;
template<class NoThrowForwardIterator, class Size, class T> constexpr NoThrowForwardIterator uninitialized_fill_n(NoThrowForwardIterator first, Size n, const T& x);
Effects: Equivalent to: for (; n--; ++first) ::new (voidify(*first)) typename iterator_traits<NoThrowForwardIterator>::value_type(x); return first;
namespace ranges { template<nothrow-forward-iterator I, class T> requires constructible_from<iter_value_t<I>, const T&> constexpr I uninitialized_fill_n(I first, iter_difference_t<I> n, const T& x); }
Effects: Equivalent to: return uninitialized_fill(counted_iterator(first, n), default_sentinel, x).base();

26.11.8 construct_at [specialized.construct]

template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); namespace ranges { template<class T, class... Args> constexpr T* construct_at(T* location, Args&&... args); }
Constraints: is_unbounded_array_v<T> is false.
The expression ​::​new (declval<void*>()) T(
declval<Args>()...)
is well-formed when treated as an unevaluated operand ([expr.context]).
Mandates: If is_array_v<T> is true, sizeof...(Args) is zero.
Effects: Equivalent to: if constexpr (is_array_v<T>) return ::new (voidify(*location)) T[1](); else return ::new (voidify(*location)) T(std::forward<Args>(args)...);

26.11.9 destroy [specialized.destroy]

template<class T> constexpr void destroy_at(T* location); namespace ranges { template<destructible T> constexpr void destroy_at(T* location) noexcept; }
Effects:
  • If T is an array type, equivalent to destroy(begin(*location), end(*location)).
  • Otherwise, equivalent to location->~T().
template<class NoThrowForwardIterator> constexpr void destroy(NoThrowForwardIterator first, NoThrowForwardIterator last);
Effects: Equivalent to: for (; first != last; ++first) destroy_at(addressof(*first));
namespace ranges { template<nothrow-input-iterator I, nothrow-sentinel-for<I> S> requires destructible<iter_value_t<I>> constexpr I destroy(I first, S last) noexcept; template<nothrow-input-range R> requires destructible<range_value_t<R>> constexpr borrowed_iterator_t<R> destroy(R&& r) noexcept; }
Effects: Equivalent to: for (; first != last; ++first) destroy_at(addressof(*first)); return first;
template<class NoThrowForwardIterator, class Size> constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, Size n);
Effects: Equivalent to: for (; n > 0; (void)++first, --n) destroy_at(addressof(*first)); return first;
namespace ranges { template<nothrow-input-iterator I> requires destructible<iter_value_t<I>> constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; }
Effects: Equivalent to: return destroy(counted_iterator(std::move(first), n), default_sentinel).base();

26.12 Specialized <random> algorithms [alg.rand]

26.12.1 General [alg.rand.general]

The contents specified in [alg.rand] are declared in the header <random>.

26.12.2 generate_random [alg.rand.generate]

template<class R, class G> requires output_range<R, invoke_result_t<G&>> && uniform_random_bit_generator<remove_cvref_t<G>> constexpr borrowed_iterator_t<R> ranges::generate_random(R&& r, G&& g);
Effects:
  • Calls g.generate_random(std​::​forward<R>(r)) if this expression is well-formed.
  • Otherwise, if R models sized_range, fills r with ranges​::​size(r) values of type invoke_result_t<G&> by performing an unspecified number of invocations of the form g() or g.generate_random(s), if such an expression is well-formed for a value N and an object s of type span<invoke_result_t<G&>, N>.
    [Note 1: 
    Values of N can differ between invocations.
    — end note]
  • Otherwise, calls ranges​::​generate(std​::​forward<R>(r), ref(g)).
Returns: ranges​::​end(r).
Remarks: The effects of generate_random(r, g) shall be equivalent to ranges​::​generate(std​::​forward<R>(r), ref(g)).
[Note 2: 
This implies that g.generate_random(a) fills a with the same values as produced by invocation of g().
— end note]
template<class G, output_iterator<invoke_result_t<G&>> O, sentinel_for<O> S> requires uniform_random_bit_generator<remove_cvref_t<G>> constexpr O ranges::generate_random(O first, S last, G&& g);
Effects: Equivalent to: return generate_random(subrange<O, S>(std::move(first), last), g);
template<class R, class G, class D> requires output_range<R, invoke_result_t<D&, G&>> && invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>> && is_arithmetic_v<invoke_result_t<D&, G&>> constexpr borrowed_iterator_t<R> ranges::generate_random(R&& r, G&& g, D&& d);
Effects:
  • Calls d.generate_random(std​::​forward<R>(r), g) if this expression is well-formed.
  • Otherwise, if R models sized_range, fills r with ranges​::​size(r) values of type invoke_result_t<D&, G&> by performing an unspecified number of invocations of the form invoke(d, g) or d.generate_random(s, g), if such an expression is well-formed for a value N and an object s of type span<invoke_result_t<D&, G&>, N>.
    [Note 3: 
    Values of N can differ between invocations.
    — end note]
  • Otherwise, calls ranges::generate(std::forward<R>(r), [&d, &g] { return invoke(d, g); });
Returns: ranges​::​end(r)
Remarks: The effects of generate_random(r, g, d) shall be equivalent to ranges::generate(std::forward<R>(r), [&d, &g] { return invoke(d, g); })
[Note 4: 
This implies that d.generate_random(a, g) fills a with the values with the same random distribution as produced by invocation of invoke(d, g).
— end note]
template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O, sentinel_for<O> S> requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>> && is_arithmetic_v<invoke_result_t<D&, G&>> constexpr O ranges::generate_random(O first, S last, G&& g, D&& d);
Effects: Equivalent to: return generate_random(subrange<O, S>(std::move(first), last), g, d);

26.13 C library algorithms [alg.c.library]

[Note 1: 
The header <cstdlib> declares the functions described in this subclause.
— end note]
void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, c-compare-pred* compar); void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, compare-pred* compar); void qsort(void* base, size_t nmemb, size_t size, c-compare-pred* compar); void qsort(void* base, size_t nmemb, size_t size, compare-pred* compar);
Preconditions: For qsort, the objects in the array pointed to by base are of trivially copyable type.
Effects: These functions have the semantics specified in the C standard library.
Throws: Any exception thrown by compar ([res.on.exception.handling]).
See also: ISO/IEC 9899:2018, 7.22.5

27 Strings library [strings]

27.1 General [strings.general]

This Clause describes components for manipulating sequences of any non-array trivially copyable standard-layout ([basic.types.general]) type T where is_trivially_default_constructible_v<T> is true.
Such types are called char-like types, and objects of char-like types are called char-like objects or simply characters.
The following subclauses describe a character traits class, string classes, and null-terminated sequence utilities, as summarized in Table 81.
Table 81 — Strings library summary [tab:strings.summary]
Subclause
Header
Character traits
<string>
String view classes
<string_view>
String classes
<string>
Null-terminated sequence utilities
<cstring>

27.2 Character traits [char.traits]

27.2.1 General [char.traits.general]

Subclause [char.traits] defines requirements on classes representing character traits, and defines a class template char_traits<charT>, along with five specializations, char_traits<char>, char_traits<char8_t>, char_traits<char16_t>, char_traits<char32_t>, and char_traits<wchar_t>, that meet those requirements.
Most classes specified in [string.classes], [string.view], and [input.output] need a set of related types and functions to complete the definition of their semantics.
These types and functions are provided as a set of member typedef-names and functions in the template parameter traits used by each such template.
Subclause [char.traits] defines the semantics of these members.
To specialize those templates to generate a string, string view, or iostream class to handle a particular character container type ([defns.character.container]) C, that and its related character traits class X are passed as a pair of parameters to the string, string view, or iostream template as parameters charT and traits.
If X​::​char_type is not the same type as C, the program is ill-formed.

27.2.2 Character traits requirements [char.traits.require]

In Table 82, X denotes a traits class defining types and functions for the character container type C; c and d denote values of type C; p and q denote values of type const C*; s denotes a value of type C*; n, i and j denote values of type size_t; e and f denote values of type X​::​int_type; pos denotes a value of type X​::​pos_type; and r denotes an lvalue of type C.
No expression which is part of the character traits requirements specified in [char.traits.require] shall exit via an exception.
Table 82 — Character traits requirements [tab:char.traits.req]
Expression
Return type
Assertion/note
Complexity
pre-/post-condition
X​::​char_type
C
X​::​int_type
(described in [char.traits.typedefs])
X​::​off_type
X​::​pos_type
X​::​state_type
(described in [char.traits.typedefs])
X​::​eq(c,d)
bool
Returns: whether c is to be treated as equal to d.
constant
X​::​lt(c,d)
bool
Returns: whether c is to be treated as less than d.
constant
X​::​compare(p,q,n)
int
Returns: 0 if for each i in [0,n), X​::​eq(p[i],q[i]) is true; else, a negative value if, for some j in [0,n), X​::​lt(p[j],q[j]) is true and for each i in [0,j) X​::​eq(p[i],q[i]) is true; else a positive value.
linear
X​::​length(p)
size_t
Returns: the smallest i such that X​::​eq(p[i],charT()) is true.
linear
X​::​find(p,n,c)
const X​::​char_type*
Returns: the smallest q in [p,p+n) such that X​::​eq(*q,c) is true, nullptr otherwise.
linear
X​::​move(s,p,n)
X​::​char_type*
for each i in [0, n), performs X​::​assign(s[i],p[i]).
Copies correctly even where the ranges [p, p+n) and [s, s+n) overlap.

Returns: s.
linear
X​::​copy(s,p,n)
X​::​char_type*
Preconditions: The ranges [p, p+n) and [s, s+n) do not overlap.
Returns: s.

for each i in [0, n), performs X​::​assign(s[i],p[i]).
linear
X​::​assign(r,d)
(not used)
assigns r=d.
constant
X​::​assign(s,n,c)
X​::​char_type*
for each i in [0, n), performs X​::​assign(s[i],c).

Returns: s.
linear
X​::​not_eof(e)
int_type
Returns: e if X​::​eq_int_type(e,X​::​eof()) is false, otherwise a value f such that X​::​eq_int_type(f,X​::​eof()) is false.
constant
X​::​to_char_type(e)
X​::​char_type
Returns: if for some c, X​::​eq_int_type(e,X​::​to_int_type(c)) is true, c; else some unspecified value.
constant
X​::​to_int_type(c)
X​::​int_type
Returns: some value e, constrained by the definitions of to_char_type and eq_int_type.
constant
X​::​eq_int_type(e,f)
bool
Returns: for all c and d, X​::​eq(c,d) is equal to X​::​eq_int_type(X​::​to_int_type(c), X​::​to_int_type(d)); otherwise, yields true if e and f are both copies of X​::​eof(); otherwise, yields false if one of e and f is a copy of X​::​eof() and the other is not; otherwise the value is unspecified.
constant
X​::​eof()
X​::​int_type
Returns: a value e such that X​::​eq_int_type(e,X​::​to_int_type(c)) is false for all values c.
constant
The class template template<class charT> struct char_traits; is provided in the header <string> as a basis for explicit specializations.

27.2.3 Traits typedefs [char.traits.typedefs]

using int_type = see below;
Preconditions: int_type shall be able to represent all of the valid characters converted from the corresponding char_type values, as well as an end-of-file value, eof().213
using state_type = see below;
Preconditions: state_type meets the Cpp17Destructible (Table 35), Cpp17CopyAssignable (Table 34), Cpp17CopyConstructible (Table 32), and Cpp17DefaultConstructible (Table 30) requirements.
213)213)
If eof() can be held in char_type then some iostreams operations can give surprising results.

27.2.4 char_traits specializations [char.traits.specializations]

27.2.4.1 General [char.traits.specializations.general]

namespace std { template<> struct char_traits<char>; template<> struct char_traits<char8_t>; template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; template<> struct char_traits<wchar_t>; }
The header <string> defines five specializations of the class template char_traits: char_traits<char>, char_traits<char8_t>, char_traits<char16_t>, char_traits<char32_t>, and char_traits<wchar_t>.

27.2.4.2 struct char_traits<char> [char.traits.specializations.char]

namespace std { template<> struct char_traits<char> { using char_type = char; using int_type = int; using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; }
The type mbstate_t is defined in <cwchar> and can represent any of the conversion states that can occur in an implementation-defined set of supported multibyte character encoding rules.
The two-argument member assign is defined identically to the built-in operator =.
The two-argument members eq and lt are defined identically to the built-in operators == and < for type unsigned char.
The member eof() returns EOF.

27.2.4.3 struct char_traits<char8_t> [char.traits.specializations.char8.t]

namespace std { template<> struct char_traits<char8_t> { using char_type = char8_t; using int_type = unsigned int; using off_type = streamoff; using pos_type = u8streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; }
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and < respectively.
The member eof() returns an implementation-defined constant that cannot appear as a valid UTF-8 code unit.

27.2.4.4 struct char_traits<char16_t> [char.traits.specializations.char16.t]

namespace std { template<> struct char_traits<char16_t> { using char_type = char16_t; using int_type = uint_least16_t; using off_type = streamoff; using pos_type = u16streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; }
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns an implementation-defined constant that cannot appear as a valid UTF-16 code unit.

27.2.4.5 struct char_traits<char32_t> [char.traits.specializations.char32.t]

namespace std { template<> struct char_traits<char32_t> { using char_type = char32_t; using int_type = uint_least32_t; using off_type = streamoff; using pos_type = u32streampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; }
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns an implementation-defined constant that cannot appear as a Unicode code point.

27.2.4.6 struct char_traits<wchar_t> [char.traits.specializations.wchar.t]

namespace std { template<> struct char_traits<wchar_t> { using char_type = wchar_t; using int_type = wint_t; using off_type = streamoff; using pos_type = wstreampos; using state_type = mbstate_t; using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; static constexpr bool lt(char_type c1, char_type c2) noexcept; static constexpr int compare(const char_type* s1, const char_type* s2, size_t n); static constexpr size_t length(const char_type* s); static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a); static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n); static constexpr char_type* assign(char_type* s, size_t n, char_type a); static constexpr int_type not_eof(int_type c) noexcept; static constexpr char_type to_char_type(int_type c) noexcept; static constexpr int_type to_int_type(char_type c) noexcept; static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept; static constexpr int_type eof() noexcept; }; }
The two-argument members assign, eq, and lt are defined identically to the built-in operators =, ==, and <, respectively.
The member eof() returns WEOF.

27.3 String view classes [string.view]

27.3.1 General [string.view.general]

The class template basic_string_view describes an object that can refer to a constant contiguous sequence of char-like ([strings.general]) objects with the first element of the sequence at position zero.
In the rest of [string.view], the type of the char-like objects held in a basic_string_view object is designated by charT.
[Note 1: 
The library provides implicit conversions from const charT* and std​::​basic_string<charT, ...> to std​::​basic_string_view<charT, ...> so that user code can accept just std​::​basic_string_view<charT> as a non-templated parameter wherever a sequence of characters is expected.
User-defined types can define their own implicit conversions to std​::​basic_string_view<charT> in order to interoperate with these functions.
— end note]

27.3.2 Header <string_view> synopsis [string.view.synop]

// mostly freestanding #include <compare> // see [compare.syn] namespace std { // [string.view.template], class template basic_string_view template<class charT, class traits = char_traits<charT>> class basic_string_view; // partially freestanding template<class charT, class traits> constexpr bool ranges::enable_view<basic_string_view<charT, traits>> = true; template<class charT, class traits> constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // [string.view.comparison], non-member comparison functions template<class charT, class traits> constexpr bool operator==(basic_string_view<charT, traits> x, type_identity_t<basic_string_view<charT, traits>> y) noexcept; template<class charT, class traits> constexpr see below operator<=>(basic_string_view<charT, traits> x, type_identity_t<basic_string_view<charT, traits>> y) noexcept; // [string.view.io], inserters and extractors template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, basic_string_view<charT, traits> str); // hosted // basic_string_view typedef-names using string_view = basic_string_view<char>; using u8string_view = basic_string_view<char8_t>; using u16string_view = basic_string_view<char16_t>; using u32string_view = basic_string_view<char32_t>; using wstring_view = basic_string_view<wchar_t>; // [string.view.hash], hash support template<class T> struct hash; template<> struct hash<string_view>; template<> struct hash<u8string_view>; template<> struct hash<u16string_view>; template<> struct hash<u32string_view>; template<> struct hash<wstring_view>; inline namespace literals { inline namespace string_view_literals { // [string.view.literals], suffix for 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; } } }
The function templates defined in [utility.swap] and [iterator.range] are available when <string_view> is included.

27.3.3 Class template basic_string_view [string.view.template]

27.3.3.1 General [string.view.template.general]

namespace std { template<class charT, class traits = char_traits<charT>> 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 = implementation-defined; // see [string.view.iterators] using iterator = const_iterator;214 using const_reverse_iterator = reverse_iterator<const_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); // [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<class It, class End> constexpr basic_string_view(It begin, End end); template<class R> constexpr explicit basic_string_view(R&& r); // [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; // [string.view.capacity], capacity constexpr size_type size() const noexcept; constexpr size_type length() const noexcept; constexpr size_type max_size() const noexcept; constexpr bool empty() const noexcept; // [string.view.access], element access constexpr const_reference operator[](size_type pos) const; constexpr const_reference at(size_type pos) const; // freestanding-deleted constexpr const_reference front() const; constexpr const_reference back() const; constexpr const_pointer data() const noexcept; // [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; // [string.view.ops], string operations constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; // freestanding-deleted constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; // freestanding-deleted constexpr int compare(basic_string_view s) const noexcept; constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; // freestanding-deleted constexpr int compare(size_type pos1, size_type n1, basic_string_view s, size_type pos2, size_type n2) const; // freestanding-deleted constexpr int compare(const charT* s) const; constexpr int compare(size_type pos1, size_type n1, const charT* s) const; // freestanding-deleted constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; // freestanding-deleted constexpr bool starts_with(basic_string_view x) const noexcept; constexpr bool starts_with(charT x) const noexcept; 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; // [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; 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; private: const_pointer data_; // exposition only size_type size_; // exposition only }; // [string.view.deduct], deduction guides template<class It, class End> basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>; template<class R> basic_string_view(R&&) -> basic_string_view<ranges::range_value_t<R>>; }
In every specialization basic_string_view<charT, traits>, the type traits shall meet the character traits requirements ([char.traits]).
[Note 1: 
The program is ill-formed if traits​::​char_type is not the same type as charT.
— end note]
For a basic_string_view str, any operation that invalidates a pointer in the range [str.data(), str.data() + str.size()) invalidates pointers, iterators, and references to elements of str.
The complexity of basic_string_view member functions is unless otherwise specified.
basic_string_view<charT, traits> is a trivially copyable type ([basic.types.general]).
214)214)
Because basic_string_view refers to a constant sequence, iterator and const_iterator are the same type.

27.3.3.2 Construction and assignment [string.view.cons]

constexpr basic_string_view() noexcept;
Postconditions: size_ == 0 and data_ == nullptr.
constexpr basic_string_view(const charT* str);
Preconditions: [str, str + traits​::​length(str)) is a valid range.
Effects: Constructs a basic_string_view, initializing data_ with str and initializing size_ with traits​::​length(str).
Complexity: .
constexpr basic_string_view(const charT* str, size_type len);
Preconditions: [str, str + len) is a valid range.
Effects: Constructs a basic_string_view, initializing data_ with str and initializing size_ with len.
template<class It, class End> constexpr basic_string_view(It begin, End end);
Constraints:
Preconditions:
Effects: Initializes data_ with to_address(begin) and initializes size_ with end - begin.
Throws: When and what end - begin throws.
template<class R> constexpr explicit basic_string_view(R&& r);
Let d be an lvalue of type remove_cvref_t<R>.
Constraints:
  • remove_cvref_t<R> is not the same type as basic_string_view,
  • R models ranges​::​contiguous_range and ranges​::​sized_range,
  • is_same_v<ranges​::​range_value_t<R>, charT> is true,
  • is_convertible_v<R, const charT*> is false, and
  • d.operator ​::​std​::​basic_string_view<charT, traits>() is not a valid expression.
Effects: Initializes data_ with ranges​::​data(r) and size_ with ranges​::​size(r).
Throws: Any exception thrown by ranges​::​data(r) and ranges​::​size(r).

27.3.3.3 Deduction guides [string.view.deduct]

template<class It, class End> basic_string_view(It, End) -> basic_string_view<iter_value_t<It>>;
Constraints:
template<class R> basic_string_view(R&&) -> basic_string_view<ranges::range_value_t<R>>;
Constraints: R satisfies ranges​::​contiguous_range.

27.3.3.4 Iterator support [string.view.iterators]

using const_iterator = implementation-defined;
A type that meets the requirements of a constant Cpp17RandomAccessIterator ([random.access.iterators]), models contiguous_iterator ([iterator.concept.contiguous]), and meets the constexpr iterator requirements ([iterator.requirements.general]), whose value_type is the template parameter charT.
All requirements on container iterators ([container.requirements]) apply to basic_string_view​::​const_iterator as well.
constexpr const_iterator begin() const noexcept; constexpr const_iterator cbegin() const noexcept;
Returns: An iterator such that
  • if !empty(), addressof(*begin()) == data_,
  • otherwise, an unspecified value such that [begin(), end()) is a valid range.
constexpr const_iterator end() const noexcept; constexpr const_iterator cend() const noexcept;
Returns: begin() + size().
constexpr const_reverse_iterator rbegin() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept;
Returns: const_reverse_iterator(end()).
constexpr const_reverse_iterator rend() const noexcept; constexpr const_reverse_iterator crend() const noexcept;
Returns: const_reverse_iterator(begin()).

27.3.3.5 Capacity [string.view.capacity]

constexpr size_type size() const noexcept; constexpr size_type length() const noexcept;
Returns: size_.
constexpr size_type max_size() const noexcept;
Returns: The largest possible number of char-like objects that can be referred to by a basic_string_view.
constexpr bool empty() const noexcept;
Returns: size_ == 0.

27.3.3.6 Element access [string.view.access]

constexpr const_reference operator[](size_type pos) const;
Preconditions: pos < size().
Returns: data_[pos].
Throws: Nothing.
[Note 1: 
Unlike basic_string​::​operator[], basic_string_view​::​operator[](size()) has undefined behavior instead of returning charT().
— end note]
constexpr const_reference at(size_type pos) const;
Returns: data_[pos].
Throws: out_of_range if pos >= size().
constexpr const_reference front() const;
Preconditions: !empty().
Returns: data_[0].
Throws: Nothing.
constexpr const_reference back() const;
Preconditions: !empty().
Returns: data_[size() - 1].
Throws: Nothing.
constexpr const_pointer data() const noexcept;
Returns: data_.
[Note 2: 
Unlike basic_string​::​data() and string-literals, data() can return a pointer to a buffer that is not null-terminated.
Therefore it is typically a mistake to pass data() to a function that takes just a const charT* and expects a null-terminated string.
— end note]

27.3.3.7 Modifiers [string.view.modifiers]

constexpr void remove_prefix(size_type n);
Preconditions: n <= size().
Effects: Equivalent to: data_ += n; size_ -= n;
constexpr void remove_suffix(size_type n);
Preconditions: n <= size().
Effects: Equivalent to: size_ -= n;
constexpr void swap(basic_string_view& s) noexcept;
Effects: Exchanges the values of *this and s.

27.3.3.8 String operations [string.view.ops]

constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
Let rlen be the smaller of n and size() - pos.
Preconditions: [s, s + rlen) is a valid range.
Effects: Equivalent to traits​::​copy(s, data() + pos, rlen).
Returns: rlen.
Throws: out_of_range if pos > size().
Complexity: .
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const;
Let rlen be the smaller of n and size() - pos.
Effects: Determines rlen, the effective length of the string to reference.
Returns: basic_string_view(data() + pos, rlen).
Throws: out_of_range if pos > size().
constexpr int compare(basic_string_view str) const noexcept;
Let rlen be the smaller of size() and str.size().
Effects: Determines rlen, the effective length of the strings to compare.
The function then compares the two strings by calling traits​::​compare(data(), str.data(), rlen).
Returns: The nonzero result if the result of the comparison is nonzero.
Otherwise, returns a value as indicated in Table 83.
Table 83compare() results [tab:string.view.compare]
Condition
Return Value
size() < str.size()
< 0
size() == str.size()
 0
size() > str.size()
> 0
Complexity: .
constexpr int compare(size_type pos1, size_type n1, basic_string_view str) const;
Effects: Equivalent to: return substr(pos1, n1).compare(str);
constexpr int compare(size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2) const;
Effects: Equivalent to: return substr(pos1, n1).compare(str.substr(pos2, n2));
constexpr int compare(const charT* s) const;
Effects: Equivalent to: return compare(basic_string_view(s));
constexpr int compare(size_type pos1, size_type n1, const charT* s) const;
Effects: Equivalent to: return substr(pos1, n1).compare(basic_string_view(s));
constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;
Effects: Equivalent to: return substr(pos1, n1).compare(basic_string_view(s, n2));
constexpr bool starts_with(basic_string_view x) const noexcept;
Let rlen be the smaller of size() and x.size().
Effects: Equivalent to: return basic_string_view(data(), rlen) == x;
constexpr bool starts_with(charT x) const noexcept;
Effects: Equivalent to: return !empty() && traits​::​eq(front(), x);
constexpr bool starts_with(const charT* x) const;
Effects: Equivalent to: return starts_with(basic_string_view(x));
constexpr bool ends_with(basic_string_view x) const noexcept;
Let rlen be the smaller of size() and x.size().
Effects: Equivalent to: return basic_string_view(data() + (size() - rlen), rlen) == x;
constexpr bool ends_with(charT x) const noexcept;
Effects: Equivalent to: return !empty() && traits​::​eq(back(), x);
constexpr bool ends_with(const charT* x) const;
Effects: Equivalent to: return ends_with(basic_string_view(x));
constexpr bool contains(basic_string_view x) const noexcept; constexpr bool contains(charT x) const noexcept; constexpr bool contains(const charT* x) const;
Effects: Equivalent to: return find(x) != npos;

27.3.3.9 Searching [string.view.find]

Member functions in this subclause have complexity at worst, although implementations should do better.
Let F be one of find, rfind, find_first_of, find_last_of, find_first_not_of, and find_last_not_of.
  • Each member function of the form constexpr return-type F(const charT* s, size_type pos) const; has effects equivalent to: return F(basic_string_view(s), pos);
  • Each member function of the form constexpr return-type F(const charT* s, size_type pos, size_type n) const; has effects equivalent to: return F(basic_string_view(s, n), pos);
  • Each member function of the form constexpr return-type F(charT c, size_type pos) const noexcept; has effects equivalent to: return F(basic_string_view(addressof(c), 1), pos);
constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept;
Let xpos be the lowest position, if possible, such that the following conditions hold:
  • pos <= xpos
  • xpos + str.size() <= size()
  • traits​::​eq(data_[xpos + I], str[I]) for all elements I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.
constexpr size_type rfind(basic_string_view str, size_type pos = npos) const noexcept;
Let xpos be the highest position, if possible, such that the following conditions hold:
  • xpos <= pos
  • xpos + str.size() <= size()
  • traits​::​eq(data_[xpos + I], str[I]) for all elements I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.
constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept;
Let xpos be the lowest position, if possible, such that the following conditions hold:
  • pos <= xpos
  • xpos < size()
  • traits​::​eq(data_[xpos], str[I]) for some element I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.
constexpr size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept;
Let xpos be the highest position, if possible, such that the following conditions hold:
  • xpos <= pos
  • xpos < size()
  • traits​::​eq(data_[xpos], str[I]) for some element I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.
constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept;
Let xpos be the lowest position, if possible, such that the following conditions hold:
  • pos <= xpos
  • xpos < size()
  • traits​::​eq(data_[xpos], str[I]) for no element I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.
constexpr size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept;
Let xpos be the highest position, if possible, such that the following conditions hold:
  • xpos <= pos
  • xpos < size()
  • traits​::​eq(data_[xpos], str[I]) for no element I of the string referenced by str.
Effects: Determines xpos.
Returns: xpos if the function can determine such a value for xpos.
Otherwise, returns npos.

27.3.4 Non-member comparison functions [string.view.comparison]

template<class charT, class traits> constexpr bool operator==(basic_string_view<charT, traits> lhs, type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
Returns: lhs.compare(rhs) == 0.
template<class charT, class traits> constexpr see below operator<=>(basic_string_view<charT, traits> lhs, type_identity_t<basic_string_view<charT, traits>> rhs) noexcept;
Let R denote the type traits​::​comparison_category if that qualified-id is valid and denotes a type ([temp.deduct]), otherwise R is weak_ordering.
Mandates: R denotes a comparison category type ([cmp.categories]).
Returns: static_cast<R>(lhs.compare(rhs) <=> 0).
[Note 1: 
The usage of type_identity_t as parameter ensures that an object of type basic_string_view<charT, traits> can always be compared with an object of a type T with an implicit conversion to basic_string_view<charT, traits>, and vice versa, as per [over.match.oper].
— end note]

27.3.5 Inserters and extractors [string.view.io]

template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, basic_string_view<charT, traits> str);
Effects: Behaves as a formatted output function ([ostream.formatted.reqmts]) of os.
Forms a character sequence seq, initially consisting of the elements defined by the range [str.begin(), str.end()).
Determines padding for seq as described in [ostream.formatted.reqmts].
Then inserts seq as if by calling os.rdbuf()->sputn(​seq, n), where n is the larger of os.width() and str.size(); then calls os.​width(0).
Returns: os

27.3.6 Hash support [string.view.hash]

template<> struct hash<string_view>; template<> struct hash<u8string_view>; template<> struct hash<u16string_view>; template<> struct hash<u32string_view>; template<> struct hash<wstring_view>;
The specialization is enabled ([unord.hash]).
[Note 1: 
The hash value of a string view object is equal to the hash value of the corresponding string object ([basic.string.hash]).
— end note]

27.3.7 Suffix for basic_string_view literals [string.view.literals]

constexpr string_view operator""sv(const char* str, size_t len) noexcept;
Returns: string_view{str, len}.
constexpr u8string_view operator""sv(const char8_t* str, size_t len) noexcept;
Returns: u8string_view{str, len}.
constexpr u16string_view operator""sv(const char16_t* str, size_t len) noexcept;
Returns: u16string_view{str, len}.
constexpr u32string_view operator""sv(const char32_t* str, size_t len) noexcept;
Returns: u32string_view{str, len}.
constexpr wstring_view operator""sv(const wchar_t* str, size_t len) noexcept;
Returns: wstring_view{str, len}.

27.4 String classes [string.classes]

27.4.1 General [string.classes.general]

The header <string> defines the basic_string class template for manipulating varying-length sequences of char-like objects and five typedef-names, string, u8string, u16string, u32string, and wstring, that name the specializations basic_string<char>, basic_string<char8_t>, basic_string<char16_t>, basic_string<char32_t>, and basic_string<wchar_t>, respectively.

27.4.2 Header <string> synopsis [string.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [char.traits], character traits template<class charT> struct char_traits; // freestanding template<> struct char_traits<char>; // freestanding template<> struct char_traits<char8_t>; // freestanding template<> struct char_traits<char16_t>; // freestanding template<> struct char_traits<char32_t>; // freestanding template<> struct char_traits<wchar_t>; // freestanding // [basic.string], basic_string template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string; template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const charT* lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(charT lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(charT lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, charT rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, type_identity_t<basic_string_view<charT, traits>> rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, type_identity_t<basic_string_view<charT, traits>> rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(type_identity_t<basic_string_view<charT, traits>> lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(type_identity_t<basic_string_view<charT, traits>> lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); template<class charT, class traits, class Allocator> constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); // [string.special], swap template<class charT, class traits, class Allocator> constexpr void swap(basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs))); // [string.io], inserters and extractors template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>&& is, basic_string<charT, traits, Allocator>& str, charT delim); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>&& is, basic_string<charT, traits, Allocator>& str); // [string.erasure], erasure template<class charT, class traits, class Allocator, class U = charT> constexpr typename basic_string<charT, traits, Allocator>::size_type erase(basic_string<charT, traits, Allocator>& c, const U& value); template<class charT, class traits, class Allocator, class Predicate> constexpr typename basic_string<charT, traits, Allocator>::size_type erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // basic_string typedef-names using string = basic_string<char>; using u8string = basic_string<char8_t>; using u16string = basic_string<char16_t>; using u32string = basic_string<char32_t>; using wstring = basic_string<wchar_t>; // [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<class charT, class traits = char_traits<charT>> using basic_string = std::basic_string<charT, traits, polymorphic_allocator<charT>>; using string = basic_string<char>; using u8string = basic_string<char8_t>; using u16string = basic_string<char16_t>; using u32string = basic_string<char32_t>; using wstring = basic_string<wchar_t>; } // [basic.string.hash], hash support template<class T> struct hash; template<class A> struct hash<basic_string<char, char_traits<char>, A>>; template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>; template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>; template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>; template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>; inline namespace literals { inline namespace string_literals { // [basic.string.literals], suffix for 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); } } }

27.4.3 Class template basic_string [basic.string]

27.4.3.1 General [basic.string.general]

The class template 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 [basic.string], the type of the char-like objects held in a basic_string object is designated by charT.
A specialization of basic_string is a contiguous container ([container.reqmts]).
In all cases, [data(), data() + size()] is a valid range, data() + size() points at an object with value charT() (a “null terminator”), and size() <= capacity() is true.
namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { public: // types using traits_type = traits; using value_type = charT; using allocator_type = Allocator; using size_type = typename allocator_traits<Allocator>::size_type; using difference_type = typename allocator_traits<Allocator>::difference_type; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using iterator = implementation-defined; // see [container.requirements] using const_iterator = implementation-defined; // see [container.requirements] using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; static constexpr size_type npos = size_type(-1); // [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()); constexpr basic_string(basic_string&& str, size_type pos, const Allocator& a = Allocator()); constexpr basic_string(basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); template<class T> constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); template<class T> 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<class InputIterator> constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); template<container-compatible-range<charT> R> constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); constexpr basic_string(initializer_list<charT>, 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<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); template<class T> 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<charT>); // [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; // [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<class Operation> 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; constexpr bool empty() const noexcept; // [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(); // [string.modifiers], modifiers constexpr basic_string& operator+=(const basic_string& str); template<class T> 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<charT>); constexpr basic_string& append(const basic_string& str); constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); template<class T> constexpr basic_string& append(const T& t); template<class T> 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<class InputIterator> constexpr basic_string& append(InputIterator first, InputIterator last); template<container-compatible-range<charT> R> constexpr basic_string& append_range(R&& rg); constexpr basic_string& append(initializer_list<charT>); constexpr void push_back(charT c); constexpr basic_string& assign(const basic_string& str); constexpr basic_string& assign(basic_string&& str) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); template<class T> constexpr basic_string& assign(const T& t); template<class T> 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<class InputIterator> constexpr basic_string& assign(InputIterator first, InputIterator last); template<container-compatible-range<charT> R> constexpr basic_string& assign_range(R&& rg); constexpr basic_string& assign(initializer_list<charT>); 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<class T> constexpr basic_string& insert(size_type pos, const T& t); template<class T> 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<class InputIterator> constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); template<container-compatible-range<charT> R> constexpr iterator insert_range(const_iterator p, R&& rg); constexpr iterator insert(const_iterator p, initializer_list<charT>); 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<class T> constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); template<class T> 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<class T> 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<class InputIterator> constexpr basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); template<container-compatible-range<charT> 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<charT>); constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; constexpr void swap(basic_string& str) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value); // [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<charT, traits>() const noexcept; constexpr allocator_type get_allocator() const noexcept; template<class T> constexpr size_type find(const T& t, size_type pos = 0) const noexcept(see below); 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<class T> constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(see below); 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<class T> constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(see below); 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<class T> constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(see below); 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<class T> constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(see below); 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<class T> constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(see below); 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 &; constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; template<class T> constexpr int compare(const T& t) const noexcept(see below); template<class T> constexpr int compare(size_type pos1, size_type n1, const T& t) const; template<class T> 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<charT, traits> 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<charT, traits> 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<charT, traits> x) const noexcept; constexpr bool contains(charT x) const noexcept; constexpr bool contains(const charT* x) const; }; template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> basic_string(InputIterator, InputIterator, Allocator = Allocator()) -> basic_string<typename iterator_traits<InputIterator>::value_type, char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>; template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> basic_string(from_range_t, R&&, Allocator = Allocator()) -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>, Allocator>; template<class charT, class traits, class Allocator = allocator<charT>> explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; template<class charT, class traits, class Allocator = allocator<charT>> basic_string(basic_string_view<charT, traits>, typename see below::size_type, typename see below::size_type, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; }
A size_type parameter type in a basic_string deduction guide refers to the size_type member type of the type deduced by the deduction guide.
The types iterator and const_iterator meet the constexpr iterator requirements ([iterator.requirements.general]).

27.4.3.2 General requirements [string.require]

If any operation would cause size() to exceed max_size(), that operation throws an exception object of type length_error.
If any member function or operator of basic_string throws an exception, that function or operator has no other effect on the basic_string object.
Every object of type basic_string<charT, traits, Allocator> uses an object of type Allocator to allocate and free storage for the contained charT objects as needed.
The Allocator object used is obtained as described in [container.reqmts].
In every specialization basic_string<charT, traits, Allocator>, the type traits shall meet the character traits requirements ([char.traits]).
[Note 1: 
Every specialization basic_string<charT, traits, Allocator> is an allocator-aware container ([container.alloc.reqmts]), but does not use the allocator's construct and destroy member functions ([container.requirements.pre]).
The program is ill-formed if Allocator​::​value_type is not the same type as charT.
— end note]
[Note 2: 
The program is ill-formed if traits​::​char_type is not the same type as charT.
— end note]
References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:
  • Passing as an argument to any standard library function taking a reference to non-const basic_string as an argument.215
  • Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.
215)215)
For example, as an argument to non-member functions swap() ([string.special]), operator>>() ([string.io]), and getline() ([string.io]), or as an argument to basic_string​::​swap().

27.4.3.3 Constructors and assignment operators [string.cons]

constexpr explicit basic_string(const Allocator& a) noexcept;
Postconditions: size() is equal to 0.
constexpr basic_string(const basic_string& str); constexpr basic_string(basic_string&& str) noexcept;
Effects: Constructs an object whose value is that of str prior to this call.
Remarks: In the second form, str is left in a valid but unspecified state.
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(basic_string&& str, size_type pos, const Allocator& a = Allocator()); constexpr basic_string(basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator());
Let
  • s be the value of str prior to this call and
  • rlen be pos + min(n, s.size() - pos) for the overloads with parameter n, and s.size() otherwise.
Effects: Constructs an object whose initial value is the range [s.data() + pos, s.data() + rlen).
Throws: out_of_range if pos > s.size().
Remarks: For the overloads with a basic_string&& parameter, str is left in a valid but unspecified state.
Recommended practice: For the overloads with a basic_string&& parameter, implementations should avoid allocation if s.get_allocator() == a is true.
template<class T> constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator());
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Creates a variable, sv, as if by basic_string_view<charT, traits> sv = t; and then behaves the same as: basic_string(sv.substr(pos, n), a);
template<class T> constexpr explicit basic_string(const T& t, const Allocator& a = Allocator());
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Creates a variable, sv, as if by basic_string_view<charT, traits> sv = t; and then behaves the same as basic_string(sv.data(), sv.size(), a).
constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
Preconditions: [s, s + n) is a valid range.
Effects: Constructs an object whose initial value is the range [s, s + n).
Postconditions: size() is equal to n, and traits​::​compare(data(), s, n) is equal to 0.
constexpr basic_string(const charT* s, const Allocator& a = Allocator());
Constraints: Allocator is a type that qualifies as an allocator ([container.reqmts]).
[Note 1: 
This affects class template argument deduction.
— end note]
Effects: Equivalent to: basic_string(s, traits​::​length(s), a).
constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator());
Constraints: Allocator is a type that qualifies as an allocator ([container.reqmts]).
[Note 2: 
This affects class template argument deduction.
— end note]
Effects: Constructs an object whose value consists of n copies of c.
template<class InputIterator> constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
Constraints: InputIterator is a type that qualifies as an input iterator ([container.reqmts]).
Effects: Constructs a string from the values in the range [begin, end), as specified in [sequence.reqmts].
template<container-compatible-range<charT> R> constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator());
Effects: Constructs a string from the values in the range rg, as specified in [sequence.reqmts].
constexpr basic_string(initializer_list<charT> il, const Allocator& a = Allocator());
Effects: Equivalent to basic_string(il.begin(), il.end(), a).
constexpr basic_string(const basic_string& str, const Allocator& alloc); constexpr basic_string(basic_string&& str, const Allocator& alloc);
Effects: Constructs an object whose value is that of str prior to this call.
The stored allocator is constructed from alloc.
In the second form, str is left in a valid but unspecified state.
Throws: The second form throws nothing if alloc == str.get_allocator().
template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> basic_string(InputIterator, InputIterator, Allocator = Allocator()) -> basic_string<typename iterator_traits<InputIterator>::value_type, char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>;
Constraints: InputIterator is a type that qualifies as an input iterator, and Allocator is a type that qualifies as an allocator ([container.reqmts]).
template<class charT, class traits, class Allocator = allocator<charT>> explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>; template<class charT, class traits, class Allocator = allocator<charT>> basic_string(basic_string_view<charT, traits>, typename see below::size_type, typename see below::size_type, const Allocator& = Allocator()) -> basic_string<charT, traits, Allocator>;
Constraints: Allocator is a type that qualifies as an allocator ([container.reqmts]).
constexpr basic_string& operator=(const basic_string& str);
Effects: If *this and str are the same object, has no effect.
Otherwise, replaces the value of *this with a copy of str.
Returns: *this.
constexpr basic_string& operator=(basic_string&& str) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);
Effects: Move assigns as a sequence container ([sequence.reqmts]), except that iterators, pointers and references may be invalidated.
Returns: *this.
template<class T> constexpr basic_string& operator=(const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return assign(sv);
constexpr basic_string& operator=(const charT* s);
Effects: Equivalent to: return *this = basic_string_view<charT, traits>(s);
constexpr basic_string& operator=(charT c);
Effects: Equivalent to: return *this = basic_string_view<charT, traits>(addressof(c), 1);
constexpr basic_string& operator=(initializer_list<charT> il);
Effects: Equivalent to: return *this = basic_string_view<charT, traits>(il.begin(), il.size());

27.4.3.4 Iterator support [string.iterators]

constexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr const_iterator cbegin() const noexcept;
Returns: An iterator referring to the first character in the string.
constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr const_iterator cend() const noexcept;
Returns: An iterator which is the past-the-end value.
constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept;
Returns: An iterator which is semantically equivalent to reverse_iterator(end()).
constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_reverse_iterator crend() const noexcept;
Returns: An iterator which is semantically equivalent to reverse_iterator(begin()).

27.4.3.5 Capacity [string.capacity]

constexpr size_type size() const noexcept; constexpr size_type length() const noexcept;
Returns: A count of the number of char-like objects currently in the string.
Complexity: Constant time.
constexpr size_type max_size() const noexcept;
Returns: The largest possible number of char-like objects that can be stored in a basic_string.
Complexity: Constant time.
constexpr void resize(size_type n, charT c);
Effects: Alters the value of *this as follows:
  • If n <= size(), erases the last size() - n elements.
  • If n > size(), appends n - size() copies of c.
constexpr void resize(size_type n);
Effects: Equivalent to resize(n, charT()).
template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op);
Let
  • o = size() before the call to resize_and_overwrite.
  • k be min(o, n).
  • p be a value of type charT* or charT* const, such that the range [p, p + n] is valid and this->compare(0, k, p, k) == 0 is true before the call.
    The values in the range [p + k, p + n] may be indeterminate ([basic.indet]).
  • m be a value of type size_type or const size_type equal to n.
  • OP be the expression std​::​move(op)(p, m).
  • r = OP.
Mandates: OP has an integer-like type ([iterator.concept.winc]).
Preconditions:
  • OP does not throw an exception or modify p or m.
  • r  ≥ 0.
  • r  ≤ m.
  • After evaluating OP there are no indeterminate values in the range [p, p + r).
Effects: Evaluates OP, replaces the contents of *this with [p, p + r), and invalidates all pointers and references to the range [p, p + n].
Recommended practice: Implementations should avoid unnecessary copies and allocations by, for example, making p a pointer into internal storage and by restoring *(p + r) to charT() after evaluating OP.
constexpr size_type capacity() const noexcept;
Returns: The size of the allocated storage in the string.
Complexity: Constant time.
constexpr void reserve(size_type res_arg);
Effects: A directive that informs a basic_string of a planned change in size, so that the storage allocation can be managed accordingly.
Following a call to reserve, capacity() is greater or equal to the argument of reserve if reallocation happens; and equal to the previous value of capacity() otherwise.
Reallocation happens at this point if and only if the current capacity is less than the argument of reserve.
Throws: length_error if res_arg > max_size() or any exceptions thrown by allocator_traits <Allocator>​::​allocate.
constexpr void shrink_to_fit();
Effects: shrink_to_fit is a non-binding request to reduce capacity() to size().
[Note 1: 
The request is non-binding to allow latitude for implementation-specific optimizations.
— end note]
It does not increase capacity(), but may reduce capacity() by causing reallocation.
Complexity: If the size is not equal to the old capacity, linear in the size of the sequence; otherwise constant.
Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence, as well as the past-the-end iterator.
[Note 2: 
If no reallocation happens, they remain valid.
— end note]
constexpr void clear() noexcept;
Effects: Equivalent to: erase(begin(), end());
constexpr bool empty() const noexcept;
Effects: Equivalent to: return size() == 0;

27.4.3.6 Element access [string.access]

constexpr const_reference operator[](size_type pos) const; constexpr reference operator[](size_type pos);
Preconditions: pos <= size().
Returns: *(begin() + pos) if pos < size().
Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object to any value other than charT() leads to undefined behavior.
Throws: Nothing.
Complexity: Constant time.
constexpr const_reference at(size_type pos) const; constexpr reference at(size_type pos);
Returns: operator[](pos).
Throws: out_of_range if pos >= size().
constexpr const charT& front() const; constexpr charT& front();
Preconditions: !empty().
Effects: Equivalent to: return operator[](0);
constexpr const charT& back() const; constexpr charT& back();
Preconditions: !empty().
Effects: Equivalent to: return operator[](size() - 1);

27.4.3.7 Modifiers [string.modifiers]

27.4.3.7.1 basic_string​::​operator+= [string.op.append]

constexpr basic_string& operator+=(const basic_string& str);
Effects: Equivalent to: return append(str);
template<class T> constexpr basic_string& operator+=(const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return append(sv);
constexpr basic_string& operator+=(const charT* s);
Effects: Equivalent to: return append(s);
constexpr basic_string& operator+=(charT c);
Effects: Equivalent to: return append(size_type{1}, c);
constexpr basic_string& operator+=(initializer_list<charT> il);
Effects: Equivalent to: return append(il);

27.4.3.7.2 basic_string​::​append [string.append]

constexpr basic_string& append(const basic_string& str);
Effects: Equivalent to: return append(str.data(), str.size());
constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos);
Effects: Equivalent to: return append(basic_string_view<charT, traits>(str).substr(pos, n));
template<class T> constexpr basic_string& append(const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return append(sv.data(), sv.size());
template<class T> constexpr basic_string& append(const T& t, size_type pos, size_type n = npos);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return append(sv.substr(pos, n));
constexpr basic_string& append(const charT* s, size_type n);
Preconditions: [s, s + n) is a valid range.
Effects: Appends a copy of the range [s, s + n) to the string.
Returns: *this.
constexpr basic_string& append(const charT* s);
Effects: Equivalent to: return append(s, traits​::​length(s));
constexpr basic_string& append(size_type n, charT c);
Effects: Appends n copies of c to the string.
Returns: *this.
template<class InputIterator> constexpr basic_string& append(InputIterator first, InputIterator last);
Constraints: InputIterator is a type that qualifies as an input iterator ([container.reqmts]).
Effects: Equivalent to: return append(basic_string(first, last, get_allocator()));
template<container-compatible-range<charT> R> constexpr basic_string& append_range(R&& rg);
Effects: Equivalent to: return append(basic_string(from_range, std​::​forward<R>(rg), get_allocator()));
constexpr basic_string& append(initializer_list<charT> il);
Effects: Equivalent to: return append(il.begin(), il.size());
constexpr void push_back(charT c);
Effects: Equivalent to append(size_type{1}, c).

27.4.3.7.3 basic_string​::​assign [string.assign]

constexpr basic_string& assign(const basic_string& str);
Effects: Equivalent to: return *this = str;
constexpr basic_string& assign(basic_string&& str) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);
Effects: Equivalent to: return *this = std​::​move(str);
constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos);
Effects: Equivalent to: return assign(basic_string_view<charT, traits>(str).substr(pos, n));
template<class T> constexpr basic_string& assign(const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return assign(sv.data(), sv.size());
template<class T> constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return assign(sv.substr(pos, n));
constexpr basic_string& assign(const charT* s, size_type n);
Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.
constexpr basic_string& assign(const charT* s);
Effects: Equivalent to: return assign(s, traits​::​length(s));
constexpr basic_string& assign(initializer_list<charT> il);
Effects: Equivalent to: return assign(il.begin(), il.size());
constexpr basic_string& assign(size_type n, charT c);
Effects: Equivalent to: clear(); resize(n, c); return *this;
template<class InputIterator> constexpr basic_string& assign(InputIterator first, InputIterator last);
Constraints: InputIterator is a type that qualifies as an input iterator ([container.reqmts]).
Effects: Equivalent to: return assign(basic_string(first, last, get_allocator()));
template<container-compatible-range<charT> R> constexpr basic_string& assign_range(R&& rg);
Effects: Equivalent to: return assign(basic_string(from_range, std​::​forward<R>(rg), get_allocator()));

27.4.3.7.4 basic_string​::​insert [string.insert]

constexpr basic_string& insert(size_type pos, const basic_string& str);
Effects: Equivalent to: return insert(pos, str.data(), str.size());
constexpr basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n = npos);
Effects: Equivalent to: return insert(pos1, basic_string_view<charT, traits>(str), pos2, n);
template<class T> constexpr basic_string& insert(size_type pos, const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return insert(pos, sv.data(), sv.size());
template<class T> constexpr basic_string& insert(size_type pos1, const T& t, size_type pos2, size_type n = npos);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return insert(pos1, sv.substr(pos2, n));
constexpr basic_string& insert(size_type pos, const charT* s, size_type n);
Preconditions: [s, s + n) is a valid range.
Effects: Inserts a copy of the range [s, s + n) immediately before the character at position pos if pos < size(), or otherwise at the end of the string.
Returns: *this.
Throws:
  • out_of_range if pos > size(),
  • length_error if n > max_size() - size(), or
  • any exceptions thrown by allocator_traits<Allocator>​::​allocate.
constexpr basic_string& insert(size_type pos, const charT* s);
Effects: Equivalent to: return insert(pos, s, traits​::​length(s));
constexpr basic_string& insert(size_type pos, size_type n, charT c);
Effects: Inserts n copies of c before the character at position pos if pos < size(), or otherwise at the end of the string.
Returns: *this
Throws:
  • out_of_range if pos > size(),
  • length_error if n > max_size() - size(), or
  • any exceptions thrown by allocator_traits<Allocator>​::​allocate.
constexpr iterator insert(const_iterator p, charT c);
Preconditions: p is a valid iterator on *this.
Effects: Inserts a copy of c at the position p.
Returns: An iterator which refers to the inserted character.
constexpr iterator insert(const_iterator p, size_type n, charT c);
Preconditions: p is a valid iterator on *this.
Effects: Inserts n copies of c at the position p.
Returns: An iterator which refers to the first inserted character, or p if n == 0.
template<class InputIterator> constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last);
Constraints: InputIterator is a type that qualifies as an input iterator ([container.reqmts]).
Preconditions: p is a valid iterator on *this.
Effects: Equivalent to insert(p - begin(), basic_string(first, last, get_allocator())).
Returns: An iterator which refers to the first inserted character, or p if first == last.
template<container-compatible-range<charT> R> constexpr iterator insert_range(const_iterator p, R&& rg);
Preconditions: p is a valid iterator on *this.
Effects: Equivalent to insert(p - begin(), basic_string(from_range, std​::​forward<R>(rg), get_allocator())).
Returns: An iterator which refers to the first inserted character, or p if rg is empty.
constexpr iterator insert(const_iterator p, initializer_list<charT> il);
Effects: Equivalent to: return insert(p, il.begin(), il.end());

27.4.3.7.5 basic_string​::​erase [string.erase]

constexpr basic_string& erase(size_type pos = 0, size_type n = npos);
Effects: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
Removes the characters in the range [begin() + pos, begin() + pos + xlen).
Returns: *this.
Throws: out_of_range if pos > size().
constexpr iterator erase(const_iterator p);
Preconditions: p is a valid dereferenceable iterator on *this.
Effects: Removes the character referred to by p.
Returns: An iterator which points to the element immediately following p prior to the element being erased.
If no such element exists, end() is returned.
Throws: Nothing.
constexpr iterator erase(const_iterator first, const_iterator last);
Preconditions: first and last are valid iterators on *this.
[first, last) is a valid range.
Effects: Removes the characters in the range [first, last).
Returns: An iterator which points to the element pointed to by last prior to the other elements being erased.
If no such element exists, end() is returned.
Throws: Nothing.
constexpr void pop_back();
Preconditions: !empty().
Effects: Equivalent to erase(end() - 1).
Throws: Nothing.

27.4.3.7.6 basic_string​::​replace [string.replace]

constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
Effects: Equivalent to: return replace(pos1, n1, str.data(), str.size());
constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos);
Effects: Equivalent to: return replace(pos1, n1, basic_string_view<charT, traits>(str).substr(pos2, n2));
template<class T> constexpr basic_string& replace(size_type pos1, size_type n1, const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return replace(pos1, n1, sv.data(), sv.size());
template<class T> constexpr basic_string& replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return replace(pos1, n1, sv.substr(pos2, n2));
constexpr basic_string& replace(size_type pos1, size_type n1, const charT* s, size_type n2);
Preconditions: [s, s + n2) is a valid range.
Effects: Determines the effective length xlen of the string to be removed as the smaller of n1 and size() - pos1.
If size() - xlen >= max_size() - n2 throws length_error.
Otherwise, the function replaces the characters in the range [begin() + pos1, begin() + pos1 + xlen) with a copy of the range [s, s + n2).
Returns: *this.
Throws:
  • out_of_range if pos1 > size(),
  • length_error if the length of the resulting string would exceed max_size(), or
  • any exceptions thrown by allocator_traits<Allocator>​::​allocate.
constexpr basic_string& replace(size_type pos, size_type n, const charT* s);
Effects: Equivalent to: return replace(pos, n, s, traits​::​length(s));
constexpr basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
Effects: Determines the effective length xlen of the string to be removed as the smaller of n1 and size() - pos1.
If size() - xlen >= max_size() - n2 throws length_error.
Otherwise, the function replaces the characters in the range [begin() + pos1, begin() + pos1 + xlen) with n2 copies of c.
Returns: *this.
Throws:
  • out_of_range if pos1 > size(),
  • length_error if the length of the resulting string would exceedmax_size(), or
  • any exceptions thrown by allocator_traits<Allocator>​::​allocate.
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str);
Effects: Equivalent to: return replace(i1, i2, basic_string_view<charT, traits>(str));
template<class T> constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Preconditions: [begin(), i1) and [i1, i2) are valid ranges.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; return replace(i1 - begin(), i2 - i1, sv.data(), sv.size());
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s, size_type n);
Effects: Equivalent to: return replace(i1, i2, basic_string_view<charT, traits>(s, n));
constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s);
Effects: Equivalent to: return replace(i1, i2, basic_string_view<charT, traits>(s));
constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c);
Preconditions: [begin(), i1) and [i1, i2) are valid ranges.
Effects: Equivalent to: return replace(i1 - begin(), i2 - i1, n, c);
template<class InputIterator> constexpr basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2);
Constraints: InputIterator is a type that qualifies as an input iterator ([container.reqmts]).
Effects: Equivalent to: return replace(i1, i2, basic_string(j1, j2, get_allocator()));
template<container-compatible-range<charT> R> constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg);
Effects: Equivalent to: return replace(i1, i2, basic_string(from_range, std::forward<R>(rg), get_allocator()));
constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<charT> il);
Effects: Equivalent to: return replace(i1, i2, il.begin(), il.size());

27.4.3.7.7 basic_string​::​copy [string.copy]

constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const;
Effects: Equivalent to: return basic_string_view<charT, traits>(*this).copy(s, n, pos);
[Note 1: 
This does not terminate s with a null object.
— end note]

27.4.3.7.8 basic_string​::​swap [string.swap]

constexpr void swap(basic_string& s) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value);
Preconditions: allocator_traits<Allocator>​::​propagate_on_container_swap​::​value is true or get_allocator() == s.get_allocator().
Postconditions: *this contains the same sequence of characters that was in s, s contains the same sequence of characters that was in *this.
Throws: Nothing.
Complexity: Constant time.

27.4.3.8 String operations [string.ops]

27.4.3.8.1 Accessors [string.accessors]

constexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept;
Returns: A pointer p such that p + i == addressof(operator[](i)) for each i in [0, size()].
Complexity: Constant time.
Remarks: The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined.
constexpr charT* data() noexcept;
Returns: A pointer p such that p + i == addressof(operator[](i)) for each i in [0, size()].
Complexity: Constant time.
Remarks: The program shall not modify the value stored at p + size() to any value other than charT(); otherwise, the behavior is undefined.
constexpr operator basic_string_view<charT, traits>() const noexcept;
Effects: Equivalent to: return basic_string_view<charT, traits>(data(), size());
constexpr allocator_type get_allocator() const noexcept;
Returns: A copy of the Allocator object used to construct the string or, if that allocator has been replaced, a copy of the most recent replacement.

27.4.3.8.2 Searching [string.find]

Let F be one of find, rfind, find_first_of, find_last_of, find_first_not_of, and find_last_not_of.
  • Each member function of the form constexpr size_type F(const basic_string& str, size_type pos) const noexcept; has effects equivalent to: return F(basic_string_view<charT, traits>(str), pos);
  • Each member function of the form constexpr size_type F(const charT* s, size_type pos) const; has effects equivalent to: return F(basic_string_view<charT, traits>(s), pos);
  • Each member function of the form constexpr size_type F(const charT* s, size_type pos, size_type n) const; has effects equivalent to: return F(basic_string_view<charT, traits>(s, n), pos);
  • Each member function of the form constexpr size_type F(charT c, size_type pos) const noexcept; has effects equivalent to: return F(basic_string_view<charT, traits>(addressof(c), 1), pos);
template<class T> constexpr size_type find(const T& t, size_type pos = 0) const noexcept(see below); template<class T> constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(see below); template<class T> constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(see below); template<class T> constexpr size_type find_last_of(const T& t, size_type pos = npos) const noexcept(see below); template<class T> constexpr size_type find_first_not_of(const T& t, size_type pos = 0) const noexcept(see below); template<class T> constexpr size_type find_last_not_of(const T& t, size_type pos = npos) const noexcept(see below);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Let G be the name of the function.
Equivalent to: basic_string_view<charT, traits> s = *this, sv = t; return s.G(sv, pos);
Remarks: The exception specification is equivalent to is_nothrow_convertible_v<const T&, basic_string_view<charT, traits>>.

27.4.3.8.3 basic_string​::​substr [string.substr]

constexpr basic_string substr(size_type pos = 0, size_type n = npos) const &;
Effects: Equivalent to: return basic_string(*this, pos, n);
constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&;
Effects: Equivalent to: return basic_string(std​::​move(*this), pos, n);

27.4.3.8.4 basic_string​::​compare [string.compare]

template<class T> constexpr int compare(const T& t) const noexcept(see below);
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: return basic_string_view<charT, traits>(*this).compare(t);
Remarks: The exception specification is equivalent to is_nothrow_convertible_v<const T&, basic_string_view<charT, traits>>.
template<class T> constexpr int compare(size_type pos1, size_type n1, const T& t) const;
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: return basic_string_view<charT, traits>(*this).substr(pos1, n1).compare(t);
template<class T> constexpr int compare(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos) const;
Constraints:
  • is_convertible_v<const T&, basic_string_view<charT, traits>> is true and
  • is_convertible_v<const T&, const charT*> is false.
Effects: Equivalent to: basic_string_view<charT, traits> s = *this, sv = t; return s.substr(pos1, n1).compare(sv.substr(pos2, n2));
constexpr int compare(const basic_string& str) const noexcept;
Effects: Equivalent to: return compare(basic_string_view<charT, traits>(str));
constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const;
Effects: Equivalent to: return compare(pos1, n1, basic_string_view<charT, traits>(str));
constexpr int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const;
Effects: Equivalent to: return compare(pos1, n1, basic_string_view<charT, traits>(str), pos2, n2);
constexpr int compare(const charT* s) const;
Effects: Equivalent to: return compare(basic_string_view<charT, traits>(s));
constexpr int compare(size_type pos, size_type n1, const charT* s) const;
Effects: Equivalent to: return compare(pos, n1, basic_string_view<charT, traits>(s));
constexpr int compare(size_type pos, size_type n1, const charT* s, size_type n2) const;
Effects: Equivalent to: return compare(pos, n1, basic_string_view<charT, traits>(s, n2));

27.4.3.8.5 basic_string​::​starts_with [string.starts.with]

constexpr bool starts_with(basic_string_view<charT, traits> x) const noexcept; constexpr bool starts_with(charT x) const noexcept; constexpr bool starts_with(const charT* x) const;
Effects: Equivalent to: return basic_string_view<charT, traits>(data(), size()).starts_with(x);

27.4.3.8.6 basic_string​::​ends_with [string.ends.with]

constexpr bool ends_with(basic_string_view<charT, traits> x) const noexcept; constexpr bool ends_with(charT x) const noexcept; constexpr bool ends_with(const charT* x) const;
Effects: Equivalent to: return basic_string_view<charT, traits>(data(), size()).ends_with(x);

27.4.3.8.7 basic_string​::​contains [string.contains]

constexpr bool contains(basic_string_view<charT, traits> x) const noexcept; constexpr bool contains(charT x) const noexcept; constexpr bool contains(const charT* x) const;
Effects: Equivalent to: return basic_string_view<charT, traits>(data(), size()).contains(x);

27.4.4 Non-member functions [string.nonmembers]

27.4.4.1 operator+ [string.op.plus]

template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
Effects: Equivalent to: basic_string<charT, traits, Allocator> r = lhs; r.append(rhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, const basic_string<charT, traits, Allocator>& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs);
Effects: Equivalent to: lhs.append(rhs); return std::move(lhs);
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, basic_string<charT, traits, Allocator>&& rhs);
Effects: Equivalent to: lhs.append(rhs); return std::move(lhs); except that both lhs and rhs are left in valid but unspecified states.
[Note 1: 
If lhs and rhs have equal allocators, the implementation can move from either.
— end note]
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>&& rhs); template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const charT* lhs, basic_string<charT, traits, Allocator>&& rhs);
Effects: Equivalent to: rhs.insert(0, lhs); return std::move(rhs);
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);
Effects: Equivalent to: basic_string<charT, traits, Allocator> r = rhs; r.insert(0, lhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(charT lhs, const basic_string<charT, traits, Allocator>& rhs);
Effects: Equivalent to: basic_string<charT, traits, Allocator> r = rhs; r.insert(r.begin(), lhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(charT lhs, basic_string<charT, traits, Allocator>&& rhs);
Effects: Equivalent to: rhs.insert(rhs.begin(), lhs); return std::move(rhs);
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);
Effects: Equivalent to: basic_string<charT, traits, Allocator> r = lhs; r.push_back(rhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, charT rhs);
Effects: Equivalent to: lhs.push_back(rhs); return std::move(lhs);
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, type_identity_t<basic_string_view<charT, traits>> rhs);
Equivalent to: basic_string<charT, traits, Allocator> r = lhs; r.append(rhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(basic_string<charT, traits, Allocator>&& lhs, type_identity_t<basic_string_view<charT, traits>> rhs);
Equivalent to: lhs.append(rhs); return std::move(lhs);
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(type_identity_t<basic_string_view<charT, traits>> lhs, const basic_string<charT, traits, Allocator>& rhs);
Equivalent to: basic_string<charT, traits, Allocator> r = rhs; r.insert(0, lhs); return r;
template<class charT, class traits, class Allocator> constexpr basic_string<charT, traits, Allocator> operator+(type_identity_t<basic_string_view<charT, traits>> lhs, basic_string<charT, traits, Allocator>&& rhs);
Equivalent to: rhs.insert(0, lhs); return std::move(rhs);
[Note 2: 
Using a specialization of type_identity_t as a parameter type ensures that an object of type basic_string<charT, traits, Allocator> can be concatenated with an object of a type T having an implicit conversion to basic_string_view<charT, traits> ([over.match.oper]).
— end note]

27.4.4.2 Non-member comparison operator functions [string.cmp]

template<class charT, class traits, class Allocator> constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs); template<class charT, class traits, class Allocator> constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs) noexcept; template<class charT, class traits, class Allocator> constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
Effects: Let op be the operator.
Equivalent to: return basic_string_view<charT, traits>(lhs) op basic_string_view<charT, traits>(rhs);

27.4.4.3 swap [string.special]

template<class charT, class traits, class Allocator> constexpr void swap(basic_string<charT, traits, Allocator>& lhs, basic_string<charT, traits, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)));
Effects: Equivalent to lhs.swap(rhs).

27.4.4.4 Inserters and extractors [string.io]

template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
Effects: Behaves as a formatted input function ([istream.formatted.reqmts]).
After constructing a sentry object, if the sentry object returns true when converted to a value of type bool, calls str.erase() and then extracts characters from is and appends them to str as if by calling str.append(1, c).
If is.width() is greater than zero, the maximum number n of characters appended is is.width(); otherwise n is str.max_size().
Characters are extracted and appended until any of the following occurs:
  • n characters are stored;
  • end-of-file occurs on the input sequence;
  • isspace(c, is.getloc()) is true for the next available input character c.
After the last character (if any) is extracted, is.width(0) is called and the sentry object is destroyed.
If the function extracts no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: is.
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
Effects: Equivalent to: return os << basic_string_view<charT, traits>(str);
template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>&& is, basic_string<charT, traits, Allocator>& str, charT delim);
Effects: Behaves as an unformatted input function ([istream.unformatted]), except that it does not affect the value returned by subsequent calls to basic_istream<>​::​gcount().
After constructing a sentry object, if the sentry object returns true when converted to a value of type bool, calls str.erase() and then extracts characters from is and appends them to str as if by calling str.append(1, c) until any of the following occurs:
  • end-of-file occurs on the input sequence;
  • traits​::​eq(c, delim) for the next available input character c (in which case, c is extracted but not appended);
  • str.max_size() characters are stored (in which case, ios_base​::​failbit is set in the input function's local error state).
The conditions are tested in the order shown.
In any case, after the last character is extracted, the sentry object is destroyed.
If the function extracts no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: is.
template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str); template<class charT, class traits, class Allocator> basic_istream<charT, traits>& getline(basic_istream<charT, traits>&& is, basic_string<charT, traits, Allocator>& str);
Returns: getline(is, str, is.widen('\n')).

27.4.4.5 Erasure [string.erasure]

template<class charT, class traits, class Allocator, class U = charT> constexpr typename basic_string<charT, traits, Allocator>::size_type erase(basic_string<charT, traits, Allocator>& c, const U& value);
Effects: Equivalent to: auto it = remove(c.begin(), c.end(), value); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;
template<class charT, class traits, class Allocator, class Predicate> constexpr typename basic_string<charT, traits, Allocator>::size_type erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred);
Effects: Equivalent to: auto it = remove_if(c.begin(), c.end(), pred); auto r = distance(it, c.end()); c.erase(it, c.end()); return r;

27.4.5 Numeric conversions [string.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);
Effects: The first two functions call strtol(str.c_str(), ptr, base), and the last three functions call strtoul(str.c_str(), ptr, base), strtoll(str.c_str(), ptr, base), and strtoull(​str.c_str(), ptr, base), respectively.
Each function returns the converted result, if any.
The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx.
If the function does not throw an exception and idx != nullptr, the function stores in *idx the index of the first unconverted element of str.
Returns: The converted result.
Throws: invalid_argument if strtol, strtoul, strtoll, or strtoull reports that no conversion can be performed.
Throws out_of_range if strtol, strtoul, strtoll or strtoull sets errno to ERANGE, or if the converted value is outside the range of representable values for the return type.
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);
Effects: These functions call strtof(str.c_str(), ptr), strtod(str.c_str(), ptr), and strtold(​str.c_str(), ptr), respectively.
Each function returns the converted result, if any.
The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx.
If the function does not throw an exception and idx != nullptr, the function stores in *idx the index of the first unconverted element of str.
Returns: The converted result.
Throws: invalid_argument if strtof, strtod, or strtold reports that no conversion can be performed.
Throws out_of_range if strtof, strtod, or strtold sets errno to ERANGE or if the converted value is outside the range of representable values for the return type.
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);
Returns: format("{}", 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);
Effects: The first two functions call wcstol(str.c_str(), ptr, base), and the last three functions call wcstoul(str.c_str(), ptr, base), wcstoll(str.c_str(), ptr, base), and wcstoull(​str.c_str(), ptr, base), respectively.
Each function returns the converted result, if any.
The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx.
If the function does not throw an exception and idx != nullptr, the function stores in *idx the index of the first unconverted element of str.
Returns: The converted result.
Throws: invalid_argument if wcstol, wcstoul, wcstoll, or wcstoull reports that no conversion can be performed.
Throws out_of_range if the converted value is outside the range of representable values for the return type.
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);
Effects: These functions call wcstof(str.c_str(), ptr), wcstod(str.c_str(), ptr), and wcstold(​str.c_str(), ptr), respectively.
Each function returns the converted result, if any.
The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx.
If the function does not throw an exception and idx != nullptr, the function stores in *idx the index of the first unconverted element of str.
Returns: The converted result.
Throws: invalid_argument if wcstof, wcstod, or wcstold reports that no conversion can be performed.
Throws out_of_range if wcstof, wcstod, or wcstold sets errno to ERANGE.
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);
Returns: format(L"{}", val).

27.4.6 Hash support [basic.string.hash]

template<class A> struct hash<basic_string<char, char_traits<char>, A>>; template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>; template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>; template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>; template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>;
If S is one of these string types, SV is the corresponding string view type, and s is an object of type S, then hash<S>()(s) == hash<SV>()(SV(s)).

27.4.7 Suffix for basic_string literals [basic.string.literals]

constexpr string operator""s(const char* str, size_t len);
Returns: string{str, len}.
constexpr u8string operator""s(const char8_t* str, size_t len);
Returns: u8string{str, len}.
constexpr u16string operator""s(const char16_t* str, size_t len);
Returns: u16string{str, len}.
constexpr u32string operator""s(const char32_t* str, size_t len);
Returns: u32string{str, len}.
constexpr wstring operator""s(const wchar_t* str, size_t len);
Returns: wstring{str, len}.
[Note 1: 
The same suffix s is used for 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]

27.5 Null-terminated sequence utilities [c.strings]

27.5.1 Header <cstring> synopsis [cstring.syn]

namespace std { using size_t = see [support.types.layout]; // freestanding void* memcpy(void* s1, const void* s2, size_t n); // freestanding void* memmove(void* s1, const void* s2, size_t n); // freestanding char* strcpy(char* s1, const char* s2); // freestanding char* strncpy(char* s1, const char* s2, size_t n); // freestanding char* strcat(char* s1, const char* s2); // freestanding char* strncat(char* s1, const char* s2, size_t n); // freestanding int memcmp(const void* s1, const void* s2, size_t n); // freestanding int strcmp(const char* s1, const char* s2); // freestanding int strcoll(const char* s1, const char* s2); int strncmp(const char* s1, const char* s2, size_t n); // freestanding size_t strxfrm(char* s1, const char* s2, size_t n); const void* memchr(const void* s, int c, size_t n); // freestanding; see [library.c] void* memchr(void* s, int c, size_t n); // freestanding; see [library.c] const char* strchr(const char* s, int c); // freestanding; see [library.c] char* strchr(char* s, int c); // freestanding; see [library.c] size_t strcspn(const char* s1, const char* s2); // freestanding const char* strpbrk(const char* s1, const char* s2); // freestanding; see [library.c] char* strpbrk(char* s1, const char* s2); // freestanding; see [library.c] const char* strrchr(const char* s, int c); // freestanding; see [library.c] char* strrchr(char* s, int c); // freestanding; see [library.c] size_t strspn(const char* s1, const char* s2); // freestanding const char* strstr(const char* s1, const char* s2); // freestanding; see [library.c] char* strstr(char* s1, const char* s2); // freestanding; see [library.c] char* strtok(char* s1, const char* s2); void* memset(void* s, int c, size_t n); // freestanding char* strerror(int errnum); size_t strlen(const char* s); // freestanding } #define NULL see [support.types.nullptr] // freestanding
The contents and meaning of the header <cstring> are the same as the C standard library header <string.h>.
The functions strerror and strtok are not required to avoid data races.
The functions memcpy and memmove are signal-safe.
Each of these functions implicitly creates objects ([intro.object]) in the destination region of storage immediately prior to copying the sequence of characters to the destination.
Each of these functions returns a pointer to a suitable created object, if any, otherwise the value of the first parameter.
[Note 1: 
The functions strchr, strpbrk, strrchr, strstr, and memchr, have different signatures in this document, but they have the same behavior as in the C standard library.
— end note]
See also: ISO/IEC 9899:2018, 7.24

28 Text processing library [text]

28.1 General [text.general]

This Clause describes components for dealing with text.
These components are summarized in Table 84.
Table 84 — Text library summary [tab:text.summary]
Subclause
Header
Primitive numeric conversions
<charconv>
Localization library
<locale>, <clocale>
Formatting
<format>
Text encodings identification
<text_encoding>
Regular expressions library
<regex>
Null-terminated sequence utilities
<cctype>, <cstdlib>, <cuchar>, <cwchar>, <cwctype>

28.2 Primitive numeric conversions [charconv]

28.2.1 Header <charconv> synopsis [charconv.syn]

When a function is specified with a type placeholder of integer-type, the implementation provides overloads for char and all cv-unqualified signed and unsigned integer types in lieu of integer-type.
When a function is specified with a type placeholder of floating-point-type, the implementation provides overloads for all cv-unqualified floating-point types ([basic.fundamental]) in lieu of floating-point-type.
namespace std { // floating-point format for primitive numerical conversion enum class chars_format { scientific = unspecified, fixed = unspecified, hex = unspecified, general = fixed | scientific }; // [charconv.to.chars], primitive numerical output conversion struct to_chars_result { // freestanding char* ptr; errc ec; friend bool operator==(const to_chars_result&, const to_chars_result&) = default; constexpr explicit operator bool() const noexcept { return ec == errc{}; } }; constexpr to_chars_result to_chars(char* first, char* last, // freestanding integer-type value, int base = 10); to_chars_result to_chars(char* first, char* last, // freestanding bool value, int base = 10) = delete; to_chars_result to_chars(char* first, char* last, // freestanding-deleted floating-point-type value); to_chars_result to_chars(char* first, char* last, // freestanding-deleted floating-point-type value, chars_format fmt); to_chars_result to_chars(char* first, char* last, // freestanding-deleted floating-point-type value, chars_format fmt, int precision); // [charconv.from.chars], primitive numerical input conversion struct from_chars_result { // freestanding const char* ptr; errc ec; friend bool operator==(const from_chars_result&, const from_chars_result&) = default; constexpr explicit operator bool() const noexcept { return ec == errc{}; } }; constexpr from_chars_result from_chars(const char* first, const char* last, // freestanding integer-type& value, int base = 10); from_chars_result from_chars(const char* first, const char* last, // freestanding-deleted floating-point-type& value, chars_format fmt = chars_format::general); }
The type chars_format is a bitmask type ([bitmask.types]) with elements scientific, fixed, and hex.
The types to_chars_result and from_chars_result have the data members and special members specified above.
They have no base classes or members other than those specified.

28.2.2 Primitive numeric output conversion [charconv.to.chars]

All functions named to_chars convert value into a character string by successively filling the range [first, last), where [first, last) is required to be a valid range.
If the member ec of the return value is such that the value is equal to the value of a value-initialized errc, the conversion was successful and the member ptr is the one-past-the-end pointer of the characters written.
Otherwise, the member ec has the value errc​::​value_too_large, the member ptr has the value last, and the contents of the range [first, last) are unspecified.
The functions that take a floating-point value but not a precision parameter ensure that the string representation consists of the smallest number of characters such that there is at least one digit before the radix point (if present) and parsing the representation using the corresponding from_chars function recovers value exactly.
[Note 1: 
This guarantee applies only if to_chars and from_chars are executed on the same implementation.
— end note]
If there are several such representations, the representation with the smallest difference from the floating-point argument value is chosen, resolving any remaining ties using rounding according to round_to_nearest ([round.style]).
The functions taking a chars_format parameter determine the conversion specifier for printf as follows: The conversion specifier is f if fmt is chars_format​::​fixed, e if fmt is chars_format​::​scientific, a (without leading "0x" in the result) if fmt is chars_format​::​hex, and g if fmt is chars_format​::​general.
constexpr to_chars_result to_chars(char* first, char* last, integer-type value, int base = 10);
Preconditions: base has a value between 2 and 36 (inclusive).
Effects: The value of value is converted to a string of digits in the given base (with no redundant leading zeroes).
Digits in the range 10..35 (inclusive) are represented as lowercase characters a..z.
If value is less than zero, the representation starts with '-'.
Throws: Nothing.
to_chars_result to_chars(char* first, char* last, floating-point-type value);
Effects: value is converted to a string in the style of printf in the "C" locale.
The conversion specifier is f or e, chosen according to the requirement for a shortest representation (see above); a tie is resolved in favor of f.
Throws: Nothing.
to_chars_result to_chars(char* first, char* last, floating-point-type value, chars_format fmt);
Preconditions: fmt has the value of one of the enumerators of chars_format.
Effects: value is converted to a string in the style of printf in the "C" locale.
Throws: Nothing.
to_chars_result to_chars(char* first, char* last, floating-point-type value, chars_format fmt, int precision);
Preconditions: fmt has the value of one of the enumerators of chars_format.
Effects: value is converted to a string in the style of printf in the "C" locale with the given precision.
Throws: Nothing.
See also: ISO/IEC 9899:2018, 7.21.6.1

28.2.3 Primitive numeric input conversion [charconv.from.chars]

All functions named from_chars analyze the string [first, last) for a pattern, where [first, last) is required to be a valid range.
If no characters match the pattern, value is unmodified, the member ptr of the return value is first and the member ec is equal to errc​::​invalid_argument.
[Note 1: 
If the pattern allows for an optional sign, but the string has no digit characters following the sign, no characters match the pattern.
— end note]
Otherwise, the characters matching the pattern are interpreted as a representation of a value of the type of value.
The member ptr of the return value points to the first character not matching the pattern, or has the value last if all characters match.
If the parsed value is not in the range representable by the type of value, value is unmodified and the member ec of the return value is equal to errc​::​result_out_of_range.
Otherwise, value is set to the parsed value, after rounding according to round_to_nearest ([round.style]), and the member ec is value-initialized.
constexpr from_chars_result from_chars(const char* first, const char* last, integer-type& value, int base = 10);
Preconditions: base has a value between 2 and 36 (inclusive).
Effects: The pattern is the expected form of the subject sequence in the "C" locale for the given nonzero base, as described for strtol, except that no "0x" or "0X" prefix shall appear if the value of base is 16, and except that '-' is the only sign that may appear, and only if value has a signed type.
Throws: Nothing.
from_chars_result from_chars(const char* first, const char* last, floating-point-type& value, chars_format fmt = chars_format::general);
Preconditions: fmt has the value of one of the enumerators of chars_format.
Effects: The pattern is the expected form of the subject sequence in the "C" locale, as described for strtod, except that
  • the sign '+' may only appear in the exponent part;
  • if fmt has chars_format​::​scientific set but not chars_format​::​fixed, the otherwise optional exponent part shall appear;
  • if fmt has chars_format​::​fixed set but not chars_format​::​scientific, the optional exponent part shall not appear; and
  • if fmt is chars_format​::​hex, the prefix "0x" or "0X" is assumed.
    [Example 1: 
    The string 0x123 is parsed to have the value 0 with remaining characters x123.
    — end example]
In any case, the resulting value is one of at most two floating-point values closest to the value of the string matching the pattern.
Throws: Nothing.
See also: ISO/IEC 9899:2018, 7.22.1.3, 7.22.1.4

28.3 Localization library [localization]

28.3.1 General [localization.general]

Subclause [localization] describes components that C++ programs may use to encapsulate (and therefore be more portable when confronting) cultural differences.
The locale facility includes internationalization support for character classification and string collation, numeric, monetary, and date/time formatting and parsing, and message retrieval.
The following subclauses describe components for locales themselves, the standard facets, and facilities from the C library, as summarized in Table 85.
Table 85 — Localization library summary [tab:localization.summary]
Subclause
Header
Locales
<locale>
Standard locale categories
C library locales
<clocale>

28.3.2 Header <locale> synopsis [locale.syn]

namespace std { // [locale], locale class locale; template<class Facet> const Facet& use_facet(const locale&); template<class Facet> bool has_facet(const locale&) noexcept; // [locale.convenience], convenience interfaces template<class charT> bool isspace (charT c, const locale& loc); template<class charT> bool isprint (charT c, const locale& loc); template<class charT> bool iscntrl (charT c, const locale& loc); template<class charT> bool isupper (charT c, const locale& loc); template<class charT> bool islower (charT c, const locale& loc); template<class charT> bool isalpha (charT c, const locale& loc); template<class charT> bool isdigit (charT c, const locale& loc); template<class charT> bool ispunct (charT c, const locale& loc); template<class charT> bool isxdigit(charT c, const locale& loc); template<class charT> bool isalnum (charT c, const locale& loc); template<class charT> bool isgraph (charT c, const locale& loc); template<class charT> bool isblank (charT c, const locale& loc); template<class charT> charT toupper(charT c, const locale& loc); template<class charT> charT tolower(charT c, const locale& loc); // [category.ctype], ctype class ctype_base; template<class charT> class ctype; template<> class ctype<char>; // specialization template<class charT> class ctype_byname; class codecvt_base; template<class internT, class externT, class stateT> class codecvt; template<class internT, class externT, class stateT> class codecvt_byname; // [category.numeric], numeric template<class charT, class InputIterator = istreambuf_iterator<charT>> class num_get; template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class num_put; template<class charT> class numpunct; template<class charT> class numpunct_byname; // [category.collate], collation template<class charT> class collate; template<class charT> class collate_byname; // [category.time], date and time class time_base; template<class charT, class InputIterator = istreambuf_iterator<charT>> class time_get; template<class charT, class InputIterator = istreambuf_iterator<charT>> class time_get_byname; template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class time_put; template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class time_put_byname; // [category.monetary], money class money_base; template<class charT, class InputIterator = istreambuf_iterator<charT>> class money_get; template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class money_put; template<class charT, bool Intl = false> class moneypunct; template<class charT, bool Intl = false> class moneypunct_byname; // [category.messages], message retrieval class messages_base; template<class charT> class messages; template<class charT> class messages_byname; }
The header <locale> defines classes and declares functions that encapsulate and manipulate the information peculiar to a locale.216
216)216)
In this subclause, the type name tm is an incomplete type that is defined in <ctime>.

28.3.3 Locales [locales]

28.3.3.1 Class locale [locale]

28.3.3.1.1 General [locale.general]

namespace std { class locale { public: // [locale.types], types // [locale.facet], class locale​::​facet class facet; // [locale.id], class locale​::​id class id; // [locale.category], type locale​::​category using category = int; static const category // values assigned here are for exposition only none = 0, collate = 0x010, ctype = 0x020, monetary = 0x040, numeric = 0x080, time = 0x100, messages = 0x200, all = collate | ctype | monetary | numeric | time | messages; // [locale.cons], construct/copy/destroy locale() noexcept; locale(const locale& other) noexcept; explicit locale(const char* std_name); explicit locale(const string& std_name); locale(const locale& other, const char* std_name, category); locale(const locale& other, const string& std_name, category); template<class Facet> locale(const locale& other, Facet* f); locale(const locale& other, const locale& one, category); ~locale(); // not virtual const locale& operator=(const locale& other) noexcept; // [locale.members], locale operations template<class Facet> locale combine(const locale& other) const; string name() const; text_encoding encoding() const; bool operator==(const locale& other) const; template<class charT, class traits, class Allocator> bool operator()(const basic_string<charT, traits, Allocator>& s1, const basic_string<charT, traits, Allocator>& s2) const; // [locale.statics], global locale objects static locale global(const locale&); static const locale& classic(); }; }
Class locale implements a type-safe polymorphic set of facets, indexed by facet type.
In other words, a facet has a dual role: in one sense, it's just a class interface; at the same time, it's an index into a locale's set of facets.
Access to the facets of a locale is via two function templates, use_facet<> and has_facet<>.
[Example 1: 
An iostream operator<< can be implemented as:217
template<class charT, class traits> basic_ostream<charT, traits>& operator<< (basic_ostream<charT, traits>& s, Date d) { typename basic_ostream<charT, traits>::sentry cerberos(s); if (cerberos) { tm tmbuf; d.extract(tmbuf); bool failed = use_facet<time_put<charT, ostreambuf_iterator<charT, traits>>>( s.getloc()).put(s, s, s.fill(), &tmbuf, 'x').failed(); if (failed) s.setstate(s.badbit); // can throw } return s; } — end example]
In the call to use_facet<Facet>(loc), the type argument chooses a facet, making available all members of the named type.
If Facet is not present in a locale, it throws the standard exception bad_cast.
A C++ program can check if a locale implements a particular facet with the function template has_facet<Facet>().
User-defined facets may be installed in a locale, and used identically as may standard facets.
[Note 1: 
All locale semantics are accessed via use_facet<> and has_facet<>, except that:
  • A member operator template operator()(const basic_string<C, T, A>&, const basic_string<C, T, A>&) is provided so that a locale can be used as a predicate argument to the standard collections, to collate strings.
  • Convenient global interfaces are provided for traditional ctype functions such as isdigit() and isspace(), so that given a locale object loc a C++ program can call isspace(c, loc).
    (This eases upgrading existing extractors ([istream.formatted]).)
— end note]
Once a facet reference is obtained from a locale object by calling use_facet<>, that reference remains usable, and the results from member functions of it may be cached and re-used, as long as some locale object refers to that facet.
In successive calls to a locale facet member function on a facet object installed in the same locale, the returned result shall be identical.
A locale constructed from a name string (such as "POSIX"), or from parts of two named locales, has a name; all others do not.
Named locales may be compared for equality; an unnamed locale is equal only to (copies of) itself.
For an unnamed locale, locale​::​name() returns the string "*".
Whether there is one global locale object for the entire program or one global locale object per thread is implementation-defined.
Implementations should provide one global locale object per thread.
If there is a single global locale object for the entire program, implementations are not required to avoid data races on it ([res.on.data.races]).
217)217)
Note that in the call to put, the stream is implicitly converted to an ostreambuf_iterator<charT, traits>.

28.3.3.1.2 Types [locale.types]

28.3.3.1.2.1 Type locale​::​category [locale.category]

using category = int;
Valid category values include the locale member bitmask elements collate, ctype, monetary, numeric, time, and messages, each of which represents a single locale category.
In addition, locale member bitmask constant none is defined as zero and represents no category.
And locale member bitmask constant all is defined such that the expression (collate | ctype | monetary | numeric | time | messages | all) == all is true, and represents the union of all categories.
Further, the expression (X | Y), where X and Y each represent a single category, represents the union of the two categories.
locale member functions expecting a category argument require one of the category values defined above, or the union of two or more such values.
Such a category value identifies a set of locale categories.
Each locale category, in turn, identifies a set of locale facets, including at least those shown in Table 86.
Table 86 — Locale category facets [tab:locale.category.facets]
Category
Includes facets
collate
collate<char>, collate<wchar_t>
ctype
ctype<char>, ctype<wchar_t>
codecvt<char, char, mbstate_t>
codecvt<wchar_t, char, mbstate_t>
monetary
moneypunct<char>, moneypunct<wchar_t>
moneypunct<char, true>, moneypunct<wchar_t, true>
money_get<char>, money_get<wchar_t>
money_put<char>, money_put<wchar_t>
numeric
numpunct<char>, numpunct<wchar_t>
num_get<char>, num_get<wchar_t>
num_put<char>, num_put<wchar_t>
time
time_get<char>, time_get<wchar_t>
time_put<char>, time_put<wchar_t>
messages
messages<char>, messages<wchar_t>
For any locale loc either constructed, or returned by locale​::​classic(), and any facet Facet shown in Table 86, has_facet<Facet>(loc) is true.
Each locale member function which takes a locale​::​category argument operates on the corresponding set of facets.
An implementation is required to provide those specializations for facet templates identified as members of a category, and for those shown in Table 87.
Table 87 — Required specializations [tab:locale.spec]
Category
Includes facets
collate
collate_byname<char>, collate_byname<wchar_t>
ctype
ctype_byname<char>, ctype_byname<wchar_t>
codecvt_byname<char, char, mbstate_t>
codecvt_byname<wchar_t, char, mbstate_t>
monetary
moneypunct_byname<char, International>
moneypunct_byname<wchar_t, International>
money_get<C, InputIterator>
money_put<C, OutputIterator>
numeric
numpunct_byname<char>, numpunct_byname<wchar_t>
num_get<C, InputIterator>, num_put<C, OutputIterator>
time
time_get<char, InputIterator>
time_get_byname<char, InputIterator>
time_get<wchar_t, InputIterator>
time_get_byname<wchar_t, InputIterator>
time_put<char, OutputIterator>
time_put_byname<char, OutputIterator>
time_put<wchar_t, OutputIterator>
time_put_byname<wchar_t, OutputIterator>
messages
messages_byname<char>, messages_byname<wchar_t>
The provided implementation of members of facets num_get<charT> and num_put<charT> calls use_facet<F>(l) only for facet F of types numpunct<charT> and ctype<charT>, and for locale l the value obtained by calling member getloc() on the ios_base& argument to these functions.
In declarations of facets, a template parameter with name InputIterator or OutputIterator indicates the set of all possible specializations on parameters that meet the Cpp17InputIterator requirements or Cpp17OutputIterator requirements, respectively ([iterator.requirements]).
A template parameter with name C represents the set of types containing char, wchar_t, and any other implementation-defined character container types ([defns.character.container]) that meet the requirements for a character on which any of the iostream components can be instantiated.
A template parameter with name International represents the set of all possible specializations on a bool parameter.

28.3.3.1.2.2 Class locale​::​facet [locale.facet]

namespace std { class locale::facet { protected: explicit facet(size_t refs = 0); virtual ~facet(); facet(const facet&) = delete; void operator=(const facet&) = delete; }; }
Class facet is the base class for locale feature sets.
A class is a facet if it is publicly derived from another facet, or if it is a class derived from locale​::​facet and contains a publicly accessible declaration as follows:218 static ::std::locale::id id;
Template parameters in this Clause which are required to be facets are those named Facet in declarations.
A program that passes a type that is not a facet, or a type that refers to a volatile-qualified facet, as an (explicit or deduced) template parameter to a locale function expecting a facet, is ill-formed.
A const-qualified facet is a valid template argument to any locale function that expects a Facet template parameter.
The refs argument to the constructor is used for lifetime management.
For refs == 0, the implementation performs delete static_cast<locale​::​facet*>(f) (where f is a pointer to the facet) when the last locale object containing the facet is destroyed; for refs == 1, the implementation never destroys the facet.
Constructors of all facets defined in this Clause take such an argument and pass it along to their facet base class constructor.
All one-argument constructors defined in this Clause are explicit, preventing their participation in implicit conversions.
For some standard facets a standard “_byname” class, derived from it, implements the virtual function semantics equivalent to that facet of the locale constructed by locale(const char*) with the same name.
Each such facet provides a constructor that takes a const char* argument, which names the locale, and a refs argument, which is passed to the base class constructor.
Each such facet also provides a constructor that takes a string argument str and a refs argument, which has the same effect as calling the first constructor with the two arguments str.c_str() and refs.
If there is no “_byname” version of a facet, the base class implements named locale semantics itself by reference to other facets.
218)218)
This is a complete list of requirements; there are no other requirements.
Thus, a facet class need not have a public copy constructor, assignment, default constructor, destructor, etc.

28.3.3.1.2.3 Class locale​::​id [locale.id]

namespace std { class locale::id { public: id(); void operator=(const id&) = delete; id(const id&) = delete; }; }
The class locale​::​id provides identification of a locale facet interface, used as an index for lookup and to encapsulate initialization.
[Note 1: 
Because facets are used by iostreams, potentially while static constructors are running, their initialization cannot depend on programmed static initialization.
One initialization strategy is for locale to initialize each facet's id member the first time an instance of the facet is installed into a locale.
This depends only on static storage being zero before constructors run ([basic.start.static]).
— end note]

28.3.3.1.3 Constructors and destructor [locale.cons]

locale() noexcept;
Effects: Constructs a copy of the argument last passed to locale​::​global(locale&), if it has been called; else, the resulting facets have virtual function semantics identical to those of locale​::​classic().
[Note 1: 
This constructor yields a copy of the current global locale.
It is commonly used as a default argument for function parameters of type const locale&.
— end note]
explicit locale(const char* std_name);
Effects: Constructs a locale using standard C locale names, e.g., "POSIX".
The resulting locale implements semantics defined to be associated with that name.
Throws: runtime_error if the argument is not valid, or is null.
Remarks: The set of valid string argument values is "C", "", and any implementation-defined values.
explicit locale(const string& std_name);
Effects: Equivalent to locale(std_name.c_str()).
locale(const locale& other, const char* std_name, category cats);
Preconditions: cats is a valid category value ([locale.category]).
Effects: Constructs a locale as a copy of other except for the facets identified by the category argument, which instead implement the same semantics as locale(std_name).
Throws: runtime_error if the second argument is not valid, or is null.
Remarks: The locale has a name if and only if other has a name.
locale(const locale& other, const string& std_name, category cats);
Effects: Equivalent to locale(other, std_name.c_str(), cats).
template<class Facet> locale(const locale& other, Facet* f);
Effects: Constructs a locale incorporating all facets from the first argument except that of type Facet, and installs the second argument as the remaining facet.
If f is null, the resulting object is a copy of other.
Remarks: If f is null, the resulting locale has the same name as other.
Otherwise, the resulting locale has no name.
locale(const locale& other, const locale& one, category cats);
Preconditions: cats is a valid category value.
Effects: Constructs a locale incorporating all facets from the first argument except those that implement cats, which are instead incorporated from the second argument.
Remarks: If cats is equal to locale​::​none, the resulting locale has a name if and only if the first argument has a name.
Otherwise, the resulting locale has a name if and only if the first two arguments both have names.
const locale& operator=(const locale& other) noexcept;
Effects: Creates a copy of other, replacing the current value.
Returns: *this.

28.3.3.1.4 Members [locale.members]

template<class Facet> locale combine(const locale& other) const;
Effects: Constructs a locale incorporating all facets from *this except for that one facet of other that is identified by Facet.
Returns: The newly created locale.
Throws: runtime_error if has_facet<Facet>(other) is false.
Remarks: The resulting locale has no name.
string name() const;
Returns: The name of *this, if it has one; otherwise, the string "*".
text_encoding encoding() const;
Mandates: CHAR_BIT == 8 is true.
Returns: A text_encoding object representing the implementation-defined encoding scheme associated with the locale *this.

28.3.3.1.5 Operators [locale.operators]

bool operator==(const locale& other) const;
Returns: true if both arguments are the same locale, or one is a copy of the other, or each has a name and the names are identical; false otherwise.
template<class charT, class traits, class Allocator> bool operator()(const basic_string<charT, traits, Allocator>& s1, const basic_string<charT, traits, Allocator>& s2) const;
Effects: Compares two strings according to the collate<charT> facet.
Returns: use_facet<collate<charT>>(*this).compare(s1.data(), s1.data() + s1.size(), s2.data(), s2.data() + s2.size()) < 0
Remarks: This member operator template (and therefore locale itself) meets the requirements for a comparator predicate template argument ([algorithms]) applied to strings.
[Example 1: 
A vector of strings v can be collated according to collation rules in locale loc simply by ([alg.sort], [vector]):
std::sort(v.begin(), v.end(), loc); — end example]

28.3.3.1.6 Static members [locale.statics]

static locale global(const locale& loc);
Effects: Sets the global locale to its argument.
Causes future calls to the constructor locale() to return a copy of the argument.
If the argument has a name, does setlocale(LC_ALL, loc.name().c_str()); otherwise, the effect on the C locale, if any, is implementation-defined.
Returns: The previous value of locale().
Remarks: No library function other than locale​::​global() affects the value returned by locale().
[Note 1: 
See [c.locales] for data race considerations when setlocale is invoked.
— end note]
static const locale& classic();
The "C" locale.
Returns: A locale that implements the classic "C" locale semantics, equivalent to the value locale("C").
Remarks: This locale, its facets, and their member functions, do not change with time.

28.3.3.2 locale globals [locale.global.templates]

template<class Facet> const Facet& use_facet(const locale& loc);
Mandates: Facet is a facet class whose definition contains the public static member id as defined in [locale.facet].
Returns: A reference to the corresponding facet of loc, if present.
Throws: bad_cast if has_facet<Facet>(loc) is false.
Remarks: The reference returned remains valid at least as long as any copy of loc exists.
template<class Facet> bool has_facet(const locale& loc) noexcept;
Returns: true if the facet requested is present in loc; otherwise false.

28.3.3.3 Convenience interfaces [locale.convenience]

28.3.3.3.1 Character classification [classification]

template<class charT> bool isspace (charT c, const locale& loc); template<class charT> bool isprint (charT c, const locale& loc); template<class charT> bool iscntrl (charT c, const locale& loc); template<class charT> bool isupper (charT c, const locale& loc); template<class charT> bool islower (charT c, const locale& loc); template<class charT> bool isalpha (charT c, const locale& loc); template<class charT> bool isdigit (charT c, const locale& loc); template<class charT> bool ispunct (charT c, const locale& loc); template<class charT> bool isxdigit(charT c, const locale& loc); template<class charT> bool isalnum (charT c, const locale& loc); template<class charT> bool isgraph (charT c, const locale& loc); template<class charT> bool isblank (charT c, const locale& loc);
Each of these functions isF returns the result of the expression: use_facet<ctype<charT>>(loc).is(ctype_base::F, c) where F is the ctype_base​::​mask value corresponding to that function ([category.ctype]).219
219)219)
When used in a loop, it is faster to cache the ctype<> facet and use it directly, or use the vector form of ctype<>​::​is.

28.3.3.3.2 Character conversions [conversions.character]

template<class charT> charT toupper(charT c, const locale& loc);
Returns: use_facet<ctype<charT>>(loc).toupper(c).
template<class charT> charT tolower(charT c, const locale& loc);
Returns: use_facet<ctype<charT>>(loc).tolower(c).

28.3.4 Standard locale categories [locale.categories]

28.3.4.1 General [locale.categories.general]

Each of the standard categories includes a family of facets.
Some of these implement formatting or parsing of a datum, for use by standard or users' iostream operators << and >>, as members put() and get(), respectively.
Each such member function takes an ios_base& argument whose members flags(), precision(), and width(), specify the format of the corresponding datum ([ios.base]).
Those functions which need to use other facets call its member getloc() to retrieve the locale imbued there.
Formatting facets use the character argument fill to fill out the specified width where necessary.
The put() members make no provision for error reporting.
(Any failures of the OutputIterator argument can be extracted from the returned iterator.)
The get() members take an ios_base​::​iostate& argument whose value they ignore, but set to ios_base​::​failbit in case of a parse error.
Within [locale.categories] it is unspecified whether one virtual function calls another virtual function.

28.3.4.2 The ctype category [category.ctype]

28.3.4.2.1 General [category.ctype.general]

namespace std { class ctype_base { public: using mask = see below; // numeric values are for exposition only. static constexpr mask space = 1 << 0; static constexpr mask print = 1 << 1; static constexpr mask cntrl = 1 << 2; static constexpr mask upper = 1 << 3; static constexpr mask lower = 1 << 4; static constexpr mask alpha = 1 << 5; static constexpr mask digit = 1 << 6; static constexpr mask punct = 1 << 7; static constexpr mask xdigit = 1 << 8; static constexpr mask blank = 1 << 9; static constexpr mask alnum = alpha | digit; static constexpr mask graph = alnum | punct; }; }
The type mask is a bitmask type ([bitmask.types]).

28.3.4.2.2 Class template ctype [locale.ctype]

28.3.4.2.2.1 General [locale.ctype.general]

namespace std { template<class charT> class ctype : public locale::facet, public ctype_base { public: using char_type = charT; explicit ctype(size_t refs = 0); bool is(mask m, charT c) const; const charT* is(const charT* low, const charT* high, mask* vec) const; const charT* scan_is(mask m, const charT* low, const charT* high) const; const charT* scan_not(mask m, const charT* low, const charT* high) const; charT toupper(charT c) const; const charT* toupper(charT* low, const charT* high) const; charT tolower(charT c) const; const charT* tolower(charT* low, const charT* high) const; charT widen(char c) const; const char* widen(const char* low, const char* high, charT* to) const; char narrow(charT c, char dfault) const; const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const; static locale::id id; protected: ~ctype(); virtual bool do_is(mask m, charT c) const; virtual const charT* do_is(const charT* low, const charT* high, mask* vec) const; virtual const charT* do_scan_is(mask m, const charT* low, const charT* high) const; virtual const charT* do_scan_not(mask m, const charT* low, const charT* high) const; virtual charT do_toupper(charT) const; virtual const charT* do_toupper(charT* low, const charT* high) const; virtual charT do_tolower(charT) const; virtual const charT* do_tolower(charT* low, const charT* high) const; virtual charT do_widen(char) const; virtual const char* do_widen(const char* low, const char* high, charT* dest) const; virtual char do_narrow(charT, char dfault) const; virtual const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const; }; }
Class ctype encapsulates the C library <cctype> features.
istream members are required to use ctype<> for character classing during input parsing.
The specializations required in Table 86 ([locale.category]), namely ctype<char> and ctype<wchar_t>, implement character classing appropriate to the implementation's native character set.

28.3.4.2.2.2 ctype members [locale.ctype.members]

bool is(mask m, charT c) const; const charT* is(const charT* low, const charT* high, mask* vec) const;
Returns: do_is(m, c) or do_is(low, high, vec).
const charT* scan_is(mask m, const charT* low, const charT* high) const;
Returns: do_scan_is(m, low, high).
const charT* scan_not(mask m, const charT* low, const charT* high) const;
Returns: do_scan_not(m, low, high).
charT toupper(charT c) const; const charT* toupper(charT* low, const charT* high) const;
Returns: do_toupper(c) or do_toupper(low, high).
charT tolower(charT c) const; const charT* tolower(charT* low, const charT* high) const;
Returns: do_tolower(c) or do_tolower(low, high).
charT widen(char c) const; const char* widen(const char* low, const char* high, charT* to) const;
Returns: do_widen(c) or do_widen(low, high, to).
char narrow(charT c, char dfault) const; const charT* narrow(const charT* low, const charT* high, char dfault, char* to) const;
Returns: do_narrow(c, dfault) or do_narrow(low, high, dfault, to).

28.3.4.2.2.3 ctype virtual functions [locale.ctype.virtuals]

bool do_is(mask m, charT c) const; const charT* do_is(const charT* low, const charT* high, mask* vec) const;
Effects: Classifies a character or sequence of characters.
For each argument character, identifies a value M of type ctype_base​::​mask.
The second form identifies a value M of type ctype_base​::​mask for each *p where (low <= p && p < high), and places it into vec[p - low].
Returns: The first form returns the result of the expression (M & m) != 0; i.e., true if the character has the characteristics specified.
The second form returns high.
const charT* do_scan_is(mask m, const charT* low, const charT* high) const;
Effects: Locates a character in a buffer that conforms to a classification m.
Returns: The smallest pointer p in the range [low, high) such that is(m, *p) would return true; otherwise, returns high.
const charT* do_scan_not(mask m, const charT* low, const charT* high) const;
Effects: Locates a character in a buffer that fails to conform to a classification m.
Returns: The smallest pointer p, if any, in the range [low, high) such that is(m, *p) would return false; otherwise, returns high.
charT do_toupper(charT c) const; const charT* do_toupper(charT* low, const charT* high) const;
Effects: Converts a character or characters to upper case.
The second form replaces each character *p in the range [low, high) for which a corresponding upper-case character exists, with that character.
Returns: The first form returns the corresponding upper-case character if it is known to exist, or its argument if not.
The second form returns high.
charT do_tolower(charT c) const; const charT* do_tolower(charT* low, const charT* high) const;
Effects: Converts a character or characters to lower case.
The second form replaces each character *p in the range [low, high) and for which a corresponding lower-case character exists, with that character.
Returns: The first form returns the corresponding lower-case character if it is known to exist, or its argument if not.
The second form returns high.
charT do_widen(char c) const; const char* do_widen(const char* low, const char* high, charT* dest) const;
Effects: Applies the simplest reasonable transformation from a char value or sequence of char values to the corresponding charT value or values.220
The only characters for which unique transformations are required are those in the basic character set ([lex.charset]).
For any named ctype category with a ctype<char> facet ctc and valid ctype_base​::​mask value M, (ctc.​is(M, c) || !is(M, do_widen(c)) ) is true.221
The second form transforms each character *p in the range [low, high), placing the result in dest[p - low].
Returns: The first form returns the transformed value.
The second form returns high.
char do_narrow(charT c, char dfault) const; const charT* do_narrow(const charT* low, const charT* high, char dfault, char* dest) const;
Effects: Applies the simplest reasonable transformation from a charT value or sequence of charT values to the corresponding char value or values.
For any character c in the basic character set ([lex.charset]) the transformation is such that do_widen(do_narrow(c, 0)) == c
For any named ctype category with a ctype<char> facet ctc however, and ctype_base​::​mask value M, (is(M, c) || !ctc.is(M, do_narrow(c, dfault)) ) is true (unless do_narrow returns dfault).
In addition, for any digit character c, the expression (do_narrow(c, dfault) - '0') evaluates to the digit value of the character.
The second form transforms each character *p in the range [low, high), placing the result (or dfault if no simple transformation is readily available) in dest[p - low].
Returns: The first form returns the transformed value; or dfault if no mapping is readily available.
The second form returns high.
220)220)
The parameter c of do_widen is intended to accept values derived from character-literals for conversion to the locale's encoding.
221)221)
In other words, the transformed character is not a member of any character classification that c is not also a member of.

28.3.4.2.3 Class template ctype_byname [locale.ctype.byname]

namespace std { template<class charT> class ctype_byname : public ctype<charT> { public: using mask = typename ctype<charT>::mask; explicit ctype_byname(const char*, size_t refs = 0); explicit ctype_byname(const string&, size_t refs = 0); protected: ~ctype_byname(); }; }

28.3.4.2.4 ctype<char> specialization [facet.ctype.special]

28.3.4.2.4.1 General [facet.ctype.special.general]

namespace std { template<> class ctype<char> : public locale::facet, public ctype_base { public: using char_type = char; explicit ctype(const mask* tab = nullptr, bool del = false, size_t refs = 0); bool is(mask m, char c) const; const char* is(const char* low, const char* high, mask* vec) const; const char* scan_is (mask m, const char* low, const char* high) const; const char* scan_not(mask m, const char* low, const char* high) const; char toupper(char c) const; const char* toupper(char* low, const char* high) const; char tolower(char c) const; const char* tolower(char* low, const char* high) const; char widen(char c) const; const char* widen(const char* low, const char* high, char* to) const; char narrow(char c, char dfault) const; const char* narrow(const char* low, const char* high, char dfault, char* to) const; static locale::id id; static const size_t table_size = implementation-defined; const mask* table() const noexcept; static const mask* classic_table() noexcept; protected: ~ctype(); virtual char do_toupper(char c) const; virtual const char* do_toupper(char* low, const char* high) const; virtual char do_tolower(char c) const; virtual const char* do_tolower(char* low, const char* high) const; virtual char do_widen(char c) const; virtual const char* do_widen(const char* low, const char* high, char* to) const; virtual char do_narrow(char c, char dfault) const; virtual const char* do_narrow(const char* low, const char* high, char dfault, char* to) const; }; }
A specialization ctype<char> is provided so that the member functions on type char can be implemented inline.222
The implementation-defined value of member table_size is at least 256.
222)222)
Only the char (not unsigned char and signed char) form is provided.
The specialization is specified in the standard, and not left as an implementation detail, because it affects the derivation interface for ctype<char>.

28.3.4.2.4.2 Destructor [facet.ctype.char.dtor]

~ctype();
Effects: If the constructor's first argument was nonzero, and its second argument was true, does delete [] table().

28.3.4.2.4.3 Members [facet.ctype.char.members]

In the following member descriptions, for unsigned char values v where v >= table_size, table()[v] is assumed to have an implementation-specific value (possibly different for each such value v) without performing the array lookup.
explicit ctype(const mask* tbl = nullptr, bool del = false, size_t refs = 0);
Preconditions: Either tbl == nullptr is true or [tbl, tbl+table_size) is a valid range.
Effects: Passes its refs argument to its base class constructor.
bool is(mask m, char c) const; const char* is(const char* low, const char* high, mask* vec) const;
Effects: The second form, for all *p in the range [low, high), assigns into vec[p - low] the value table()[(unsigned char)*p].
Returns: The first form returns table()[(unsigned char)c] & m; the second form returns high.
const char* scan_is(mask m, const char* low, const char* high) const;
Returns: The smallest p in the range [low, high) such that table()[(unsigned char) *p] & m is true.
const char* scan_not(mask m, const char* low, const char* high) const;
Returns: The smallest p in the range [low, high) such that table()[(unsigned char) *p] & m is false.
char toupper(char c) const; const char* toupper(char* low, const char* high) const;
Returns: do_toupper(c) or do_toupper(low, high), respectively.
char tolower(char c) const; const char* tolower(char* low, const char* high) const;
Returns: do_tolower(c) or do_tolower(low, high), respectively.
char widen(char c) const; const char* widen(const char* low, const char* high, char* to) const;
Returns: do_widen(c) or do_widen(low, high, to), respectively.
char narrow(char c, char dfault) const; const char* narrow(const char* low, const char* high, char dfault, char* to) const;
Returns: do_narrow(c, dfault) or do_narrow(low, high, dfault, to), respectively.
const mask* table() const noexcept;
Returns: The first constructor argument, if it was nonzero, otherwise classic_table().

28.3.4.2.4.4 Static members [facet.ctype.char.statics]

static const mask* classic_table() noexcept;
Returns: A pointer to the initial element of an array of size table_size which represents the classifications of characters in the "C" locale.

28.3.4.2.4.5 Virtual functions [facet.ctype.char.virtuals]

char do_toupper(char) const; const char* do_toupper(char* low, const char* high) const; char do_tolower(char) const; const char* do_tolower(char* low, const char* high) const; virtual char do_widen(char c) const; virtual const char* do_widen(const char* low, const char* high, char* to) const; virtual char do_narrow(char c, char dfault) const; virtual const char* do_narrow(const char* low, const char* high, char dfault, char* to) const;
These functions are described identically as those members of the same name in the ctype class template ([locale.ctype.members]).

28.3.4.2.5 Class template codecvt [locale.codecvt]

28.3.4.2.5.1 General [locale.codecvt.general]

namespace std { class codecvt_base { public: enum result { ok, partial, error, noconv }; }; template<class internT, class externT, class stateT> class codecvt : public locale::facet, public codecvt_base { public: using intern_type = internT; using extern_type = externT; using state_type = stateT; explicit codecvt(size_t refs = 0); result out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_end, externT*& to_next) const; result unshift( stateT& state, externT* to, externT* to_end, externT*& to_next) const; result in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_end, internT*& to_next) const; int encoding() const noexcept; bool always_noconv() const noexcept; int length(stateT&, const externT* from, const externT* end, size_t max) const; int max_length() const noexcept; static locale::id id; protected: ~codecvt(); virtual result do_out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_end, externT*& to_next) const; virtual result do_in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_end, internT*& to_next) const; virtual result do_unshift( stateT& state, externT* to, externT* to_end, externT*& to_next) const; virtual int do_encoding() const noexcept; virtual bool do_always_noconv() const noexcept; virtual int do_length(stateT&, const externT* from, const externT* end, size_t max) const; virtual int do_max_length() const noexcept; }; }
The class codecvt<internT, externT, stateT> is for use when converting from one character encoding to another, such as from wide characters to multibyte characters or between wide character encodings such as UTF-32 and EUC.
The stateT argument selects the pair of character encodings being mapped between.
The specializations required in Table 86 ([locale.category]) convert the implementation-defined native character set.
codecvt<char, char, mbstate_t> implements a degenerate conversion; it does not convert at all.
codecvt<wchar_t, char, mbstate_t> converts between the native character sets for ordinary and wide characters.
Specializations on mbstate_t perform conversion between encodings known to the library implementer.
Other encodings can be converted by specializing on a program-defined stateT type.
Objects of type stateT can contain any state that is useful to communicate to or from the specialized do_in or do_out members.

28.3.4.2.5.2 Members [locale.codecvt.members]

result out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_end, externT*& to_next) const;
Returns: do_out(state, from, from_end, from_next, to, to_end, to_next).
result unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const;
Returns: do_unshift(state, to, to_end, to_next).
result in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_end, internT*& to_next) const;
Returns: do_in(state, from, from_end, from_next, to, to_end, to_next).
int encoding() const noexcept;
Returns: do_encoding().
bool always_noconv() const noexcept;
Returns: do_always_noconv().
int length(stateT& state, const externT* from, const externT* from_end, size_t max) const;
Returns: do_length(state, from, from_end, max).
int max_length() const noexcept;
Returns: do_max_length().

28.3.4.2.5.3 Virtual functions [locale.codecvt.virtuals]

result do_out( stateT& state, const internT* from, const internT* from_end, const internT*& from_next, externT* to, externT* to_end, externT*& to_next) const; result do_in( stateT& state, const externT* from, const externT* from_end, const externT*& from_next, internT* to, internT* to_end, internT*& to_next) const;
Preconditions: (from <= from_end && to <= to_end) is well-defined and true; state is initialized, if at the beginning of a sequence, or else is equal to the result of converting the preceding characters in the sequence.
Effects: Translates characters in the source range [from, from_end), placing the results in sequential positions starting at destination to.
Converts no more than (from_end - from) source elements, and stores no more than (to_end - to) destination elements.
Stops if it encounters a character it cannot convert.
It always leaves the from_next and to_next pointers pointing one beyond the last element successfully converted.
If it returns noconv, internT and externT are the same type, and the converted sequence is identical to the input sequence [from, from_next), to_next is set equal to to, the value of state is unchanged, and there are no changes to the values in [to, to_end).
A codecvt facet that is used by basic_filebuf ([file.streams]) shall have the property that if do_out(state, from, from_end, from_next, to, to_end, to_next) would return ok, where from != from_end, then do_out(state, from, from + 1, from_next, to, to_end, to_next) shall also return ok, and that if do_in(state, from, from_end, from_next, to, to_end, to_next) would return ok, where to != to_end, then do_in(state, from, from_end, from_next, to, to + 1, to_next) shall also return ok.223
[Note 1: 
As a result of operations on state, it can return ok or partial and set from_next == from and to_next != to.
— end note]
Returns: An enumeration value, as summarized in Table 88.
Table 88do_in/do_out result values [tab:locale.codecvt.inout]
Value
Meaning
ok
completed the conversion
partial
not all source characters converted
error
encountered a character in [from, from_end) that cannot be converted
noconv
internT and externT are the same type, and input sequence is identical to converted sequence
A return value of partial, if (from_next == from_end), indicates that either the destination sequence has not absorbed all the available destination elements, or that additional source elements are needed before another destination element can be produced.
Remarks: Its operations on state are unspecified.
[Note 2: 
This argument can be used, for example, to maintain shift state, to specify conversion options (such as count only), or to identify a cache of seek offsets.
— end note]
result do_unshift(stateT& state, externT* to, externT* to_end, externT*& to_next) const;
Preconditions: (to <= to_end) is well-defined and true; state is initialized, if at the beginning of a sequence, or else is equal to the result of converting the preceding characters in the sequence.
Effects: Places characters starting at to that should be appended to terminate a sequence when the current stateT is given by state.224
Stores no more than (to_end - to) destination elements, and leaves the to_next pointer pointing one beyond the last element successfully stored.
Returns: An enumeration value, as summarized in Table 89.
Table 89do_unshift result values [tab:locale.codecvt.unshift]
Value
Meaning
ok
completed the sequence
partial
space for more than to_end - to destination elements was needed to terminate a sequence given the value of state
error
an unspecified error has occurred
noconv
no termination is needed for this state_type
int do_encoding() const noexcept;
Returns: -1 if the encoding of the externT sequence is state-dependent; else the constant number of externT characters needed to produce an internal character; or 0 if this number is not a constant.225
bool do_always_noconv() const noexcept;
Returns: true if do_in() and do_out() return noconv for all valid argument values.
codecvt<char, char, mbstate_t> returns true.
int do_length(stateT& state, const externT* from, const externT* from_end, size_t max) const;
Preconditions: (from <= from_end) is well-defined and true; state is initialized, if at the beginning of a sequence, or else is equal to the result of converting the preceding characters in the sequence.
Effects: The effect on the state argument is as if it called do_in(state, from, from_end, from, to, to+max, to) for to pointing to a buffer of at least max elements.
Returns: (from_next-from) where from_next is the largest value in the range [from, from_end] such that the sequence of values in the range [from, from_next) represents max or fewer valid complete characters of type internT.
The specialization codecvt<char, char, mbstate_t>, returns the lesser of max and (from_end-from).
int do_max_length() const noexcept;
Returns: The maximum value that do_length(state, from, from_end, 1) can return for any valid range [from, from_end) and stateT value state.
The specialization codecvt<char, char, mbstate_t>​::​do_max_length() returns 1.
223)223)
Informally, this means that basic_filebuf assumes that the mappings from internal to external characters is 1 to N: that a codecvt facet that is used by basic_filebuf can translate characters one internal character at a time.
224)224)
Typically these will be characters to return the state to stateT().
225)225)
If encoding() yields -1, then more than max_length() externT elements can be consumed when producing a single internT character, and additional externT elements can appear at the end of a sequence after those that yield the final internT character.

28.3.4.2.6 Class template codecvt_byname [locale.codecvt.byname]

namespace std { template<class internT, class externT, class stateT> class codecvt_byname : public codecvt<internT, externT, stateT> { public: explicit codecvt_byname(const char*, size_t refs = 0); explicit codecvt_byname(const string&, size_t refs = 0); protected: ~codecvt_byname(); }; }

28.3.4.3 The numeric category [category.numeric]

28.3.4.3.1 General [category.numeric.general]

The classes num_get<> and num_put<> handle numeric formatting and parsing.
Virtual functions are provided for several numeric types.
Implementations may (but are not required to) delegate extraction of smaller types to extractors for larger types.226
All specifications of member functions for num_put and num_get in the subclauses of [category.numeric] only apply to the specializations required in Tables 86 and 87 ([locale.category]), namely num_get<char>, num_get<wchar_t>, num_get<C, InputIterator>, num_put<char>, num_put<wchar_t>, and num_put<C, OutputIterator>.
These specializations refer to the ios_base& argument for formatting specifications ([locale.categories]), and to its imbued locale for the numpunct<> facet to identify all numeric punctuation preferences, and also for the ctype<> facet to perform character classification.
Extractor and inserter members of the standard iostreams use num_get<> and num_put<> member functions for formatting and parsing numeric values ([istream.formatted.reqmts], [ostream.formatted.reqmts]).
226)226)
Parsing "-1" correctly into, e.g., an unsigned short requires that the corresponding member get() at least extract the sign before delegating.

28.3.4.3.2 Class template num_get [locale.num.get]

28.3.4.3.2.1 General [locale.num.get.general]

namespace std { template<class charT, class InputIterator = istreambuf_iterator<charT>> class num_get : public locale::facet { public: using char_type = charT; using iter_type = InputIterator; explicit num_get(size_t refs = 0); iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, bool& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, long& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, long long& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, unsigned short& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, unsigned int& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, unsigned long& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, unsigned long long& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, float& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, double& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, long double& v) const; iter_type get(iter_type in, iter_type end, ios_base&, ios_base::iostate& err, void*& v) const; static locale::id id; protected: ~num_get(); virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, bool& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, long long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, unsigned short& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, unsigned int& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, unsigned long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, unsigned long long& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, float& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, double& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, long double& v) const; virtual iter_type do_get(iter_type, iter_type, ios_base&, ios_base::iostate& err, void*& v) const; }; }
The facet num_get is used to parse numeric values from an input sequence such as an istream.

28.3.4.3.2.2 Members [facet.num.get.members]

iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const; iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const;
Returns: do_get(in, end, str, err, val).

28.3.4.3.2.3 Virtual functions [facet.num.get.virtuals]

iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const; iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const;
Effects: Reads characters from in, interpreting them according to str.flags(), use_facet<ctype<​charT>>(loc), and use_facet<numpunct<charT>>(loc), where loc is str.getloc().
The details of this operation occur in three stages:
  • Stage 1: Determine a conversion specifier.
  • Stage 2: Extract characters from in and determine a corresponding char value for the format expected by the conversion specification determined in stage 1.
  • Stage 3: Store results.
The details of the stages are presented below.
  • Stage 1:
    The function initializes local variables via fmtflags flags = str.flags(); fmtflags basefield = (flags & ios_base::basefield); fmtflags uppercase = (flags & ios_base::uppercase); fmtflags boolalpha = (flags & ios_base::boolalpha);
    For conversion to an integral type, the function determines the integral conversion specifier as indicated in Table 90.
    The table is ordered.
    That is, the first line whose condition is true applies.
    Table 90 — Integer conversions [tab:facet.num.get.int]
    State
    stdio equivalent
    basefield == oct
    %o
    basefield == hex
    %X
    basefield == 0
    %i
    signed integral type
    %d
    unsigned integral type
    %u
    For conversions to a floating-point type the specifier is %g.
    For conversions to void* the specifier is %p.
    A length modifier is added to the conversion specification, if needed, as indicated in Table 91.
    Table 91 — Length modifier [tab:facet.num.get.length]
    Type
    Length modifier
    short
    h
    unsigned short
    h
    long
    l
    unsigned long
    l
    long long
    ll
    unsigned long long
    ll
    double
    l
    long double
    L
  • Stage 2:
    If in == end then stage 2 terminates.
    Otherwise a charT is taken from in and local variables are initialized as if by char_type ct = *in; char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms]; if (ct == use_facet<numpunct<charT>>(loc).decimal_point()) c = '.'; bool discard = ct == use_facet<numpunct<charT>>(loc).thousands_sep() && use_facet<numpunct<charT>>(loc).grouping().length() != 0; where the values src and atoms are defined as if by: static const char src[] = "0123456789abcdefpxABCDEFPX+-"; char_type atoms[sizeof(src)]; use_facet<ctype<charT>>(loc).widen(src, src + sizeof(src), atoms); for this value of loc.
    If discard is true, then if '.' has not yet been accumulated, then the position of the character is remembered, but the character is otherwise ignored.
    Otherwise, if '.' has already been accumulated, the character is discarded and Stage 2 terminates.
    If it is not discarded, then a check is made to determine if c is allowed as the next character of an input field of the conversion specifier returned by Stage 1.
    If so, it is accumulated.
    If the character is either discarded or accumulated then in is advanced by ++in and processing returns to the beginning of stage 2.
    [Example 1: 
    Given an input sequence of "0x1a.bp+07p",
    • if the conversion specifier returned by Stage 1 is %d, "0" is accumulated;
    • if the conversion specifier returned by Stage 1 is %i, "0x1a" are accumulated;
    • if the conversion specifier returned by Stage 1 is %g, "0x1a.bp+07" are accumulated.
    In all cases, the remainder is left in the input.
    — end example]
  • Stage 3:
    The sequence of chars accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header <cstdlib>:
    • For a signed integer value, the function strtoll.
    • For an unsigned integer value, the function strtoull.
    • For a float value, the function strtof.
    • For a double value, the function strtod.
    • For a long double value, the function strtold.
    The numeric value to be stored can be one of:
    • zero, if the conversion function does not convert the entire field.
    • the most positive (or negative) representable value, if the field to be converted to a signed integer type represents a value too large positive (or negative) to be represented in val.
    • the most positive representable value, if the field to be converted to an unsigned integer type represents a value that cannot be represented in val.
    • the converted value, otherwise.
    The resultant numeric value is stored in val.
    If the conversion function does not convert the entire field, or if the field represents a value outside the range of representable values, ios_base​::​failbit is assigned to err.
Digit grouping is checked.
That is, the positions of discarded separators are examined for consistency with use_facet<numpunct<charT>>(loc).grouping().
If they are not consistent then ios_base​::​failbit is assigned to err.
In any case, if stage 2 processing was terminated by the test for in == end then err |= ios_base​::​eofbit is performed.
iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const;
Effects: If (str.flags()&ios_base​::​boolalpha) == 0 then input proceeds as it would for a long except that if a value is being stored into val, the value is determined according to the following: If the value to be stored is 0 then false is stored.
If the value is 1 then true is stored.
Otherwise true is stored and ios_base​::​failbit is assigned to err.
Otherwise target sequences are determined “as if” by calling the members falsename() and truename() of the facet obtained by use_facet<numpunct<charT>>(str.getloc()).
Successive characters in the range [in, end) (see [sequence.reqmts]) are obtained and matched against corresponding positions in the target sequences only as necessary to identify a unique match.
The input iterator in is compared to end only when necessary to obtain a character.
If a target sequence is uniquely matched, val is set to the corresponding value.
Otherwise false is stored and ios_base​::​failbit is assigned to err.
The in iterator is always left pointing one position beyond the last character successfully matched.
If val is set, then err is set to str.goodbit; or to str.eofbit if, when seeking another character to match, it is found that (in == end).
If val is not set, then err is set to str.failbit; or to (str.failbit|str.eofbit) if the reason for the failure was that (in == end).
[Example 2: 
For targets true: "a" and false: "abb", the input sequence "a" yields val == true and err == str.eofbit; the input sequence "abc" yields err = str.failbit, with in ending at the 'c' element.
For targets true: "1" and false: "0", the input sequence "1" yields val == true and err == str.goodbit.
For empty targets (""), any input sequence yields err == str.failbit.
— end example]
Returns: in.

28.3.4.3.3 Class template num_put [locale.nm.put]

28.3.4.3.3.1 General [locale.nm.put.general]

namespace std { template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class num_put : public locale::facet { public: using char_type = charT; using iter_type = OutputIterator; explicit num_put(size_t refs = 0); iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const; iter_type put(iter_type s, ios_base& f, char_type fill, long v) const; iter_type put(iter_type s, ios_base& f, char_type fill, long long v) const; iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long v) const; iter_type put(iter_type s, ios_base& f, char_type fill, unsigned long long v) const; iter_type put(iter_type s, ios_base& f, char_type fill, double v) const; iter_type put(iter_type s, ios_base& f, char_type fill, long double v) const; iter_type put(iter_type s, ios_base& f, char_type fill, const void* v) const; static locale::id id; protected: ~num_put(); virtual iter_type do_put(iter_type, ios_base&, char_type fill, bool v) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, long v) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, long long v) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, unsigned long long) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, double v) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, long double v) const; virtual iter_type do_put(iter_type, ios_base&, char_type fill, const void* v) const; }; }
The facet num_put is used to format numeric values to a character sequence such as an ostream.

28.3.4.3.3.2 Members [facet.num.put.members]

iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; iter_type put(iter_type out, ios_base& str, char_type fill, double val) const; iter_type put(iter_type out, ios_base& str, char_type fill, long double val) const; iter_type put(iter_type out, ios_base& str, char_type fill, const void* val) const;
Returns: do_put(out, str, fill, val).

28.3.4.3.3.3 Virtual functions [facet.num.put.virtuals]

iter_type do_put(iter_type out, ios_base& str, char_type fill, long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, long long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, long double val) const; iter_type do_put(iter_type out, ios_base& str, char_type fill, const void* val) const;
Effects: Writes characters to the sequence out, formatting val as desired.
In the following description, loc names a local variable initialized as locale loc = str.getloc();
The details of this operation occur in several stages:
  • Stage 1: Determine a printf conversion specifier spec and determine the characters that would be printed by printf ([c.files]) given this conversion specifier for printf(spec, val) assuming that the current locale is the "C" locale.
  • Stage 2: Adjust the representation by converting each char determined by stage 1 to a charT using a conversion and values returned by members of use_facet<numpunct<charT>>(loc).
  • Stage 3: Determine where padding is required.
  • Stage 4: Insert the sequence into the out.
Detailed descriptions of each stage follow.
Returns: out.
  • Stage 1:
    The first action of stage 1 is to determine a conversion specifier.
    The tables that describe this determination use the following local variables
    fmtflags flags = str.flags(); fmtflags basefield = (flags & (ios_base::basefield)); fmtflags uppercase = (flags & (ios_base::uppercase)); fmtflags floatfield = (flags & (ios_base::floatfield)); fmtflags showpos = (flags & (ios_base::showpos)); fmtflags showbase = (flags & (ios_base::showbase)); fmtflags showpoint = (flags & (ios_base::showpoint));
    All tables used in describing stage 1 are ordered.
    That is, the first line whose condition is true applies.
    A line without a condition is the default behavior when none of the earlier lines apply.
    For conversion from an integral type other than a character type, the function determines the integral conversion specifier as indicated in Table 92.
    Table 92 — Integer conversions [tab:facet.num.put.int]
    State
    stdio equivalent
    basefield == ios_base​::​oct
    %o
    (basefield == ios_base​::​hex) && !uppercase
    %x
    (basefield == ios_base​::​hex)
    %X
    for a signed integral type
    %d
    for an unsigned integral type
    %u
    For conversion from a floating-point type, the function determines the floating-point conversion specifier as indicated in Table 93.
    Table 93 — Floating-point conversions [tab:facet.num.put.fp]
    State
    stdio equivalent
    floatfield == ios_base​::​fixed && !uppercase
    %f
    floatfield == ios_base​::​fixed
    %F
    floatfield == ios_base​::​scientific && !uppercase
    %e
    floatfield == ios_base​::​scientific
    %E
    floatfield == (ios_base​::​fixed | ios_base​::​scientific) && !uppercase
    %a
    floatfield == (ios_base​::​fixed | ios_base​::​scientific)
    %A
    !uppercase
    %g
    otherwise
    %G
    For conversions from an integral or floating-point type a length modifier is added to the conversion specifier as indicated in Table 94.
    Table 94 — Length modifier [tab:facet.num.put.length]
    Type
    Length modifier
    long
    l
    long long
    ll
    unsigned long
    l
    unsigned long long
    ll
    long double
    L
    otherwise
    none
    The conversion specifier has the following optional additional qualifiers prepended as indicated in Table 95.
    Table 95 — Numeric conversions [tab:facet.num.put.conv]
    Type(s)
    State
    stdio equivalent
    an integral type
    showpos
    +
    showbase
    #
    a floating-point type
    showpos
    +
    showpoint
    #
    For conversion from a floating-point type, if floatfield != (ios_base​::​fixed | ios_base​::​​scientific), str.precision() is specified as precision in the conversion specification.
    Otherwise, no precision is specified.
    For conversion from void* the specifier is %p.
    The representations at the end of stage 1 consists of the char's that would be printed by a call of printf(s, val) where s is the conversion specifier determined above.
  • Stage 2:
    Any character c other than a decimal point(.) is converted to a charT via use_facet<ctype<charT>>(loc).widen(c)
    A local variable punct is initialized via const numpunct<charT>& punct = use_facet<numpunct<charT>>(loc);
    For arithmetic types, punct.thousands_sep() characters are inserted into the sequence as determined by the value returned by punct.do_grouping() using the method described in [facet.numpunct.virtuals].
    Decimal point characters(.) are replaced by punct.decimal_point().
  • Stage 3:
    A local variable is initialized as fmtflags adjustfield = (flags & (ios_base::adjustfield));
    The location of any padding227 is determined according to Table 96.
    Table 96 — Fill padding [tab:facet.num.put.fill]
    State
    Location
    adjustfield == ios_base​::​left
    pad after
    adjustfield == ios_base​::​right
    pad before
    adjustfield == internal and a sign occurs in the representation
    pad after the sign
    adjustfield == internal and representation after stage 1 began with 0x or 0X
    pad after x or X
    otherwise
    pad before
    If str.width() is nonzero and the number of charT's in the sequence after stage 2 is less than str.​width(), then enough fill characters are added to the sequence at the position indicated for padding to bring the length of the sequence to str.width().
    str.width(0) is called.
  • Stage 4:
    The sequence of charT's at the end of stage 3 are output via *out++ = c
iter_type do_put(iter_type out, ios_base& str, char_type fill, bool val) const;
Returns: If (str.flags() & ios_base​::​boolalpha) == 0 returns do_put(out, str, fill,
(int)val)
, otherwise obtains a string s as if by string_type s = val ? use_facet<numpunct<charT>>(loc).truename() : use_facet<numpunct<charT>>(loc).falsename(); and then inserts each character c of s into out via *out++ = c and returns out.
227)227)
The conversion specification #o generates a leading 0 which is not a padding character.

28.3.4.4 The numeric punctuation facet [facet.numpunct]

28.3.4.4.1 Class template numpunct [locale.numpunct]

28.3.4.4.1.1 General [locale.numpunct.general]

namespace std { template<class charT> class numpunct : public locale::facet { public: using char_type = charT; using string_type = basic_string<charT>; explicit numpunct(size_t refs = 0); char_type decimal_point() const; char_type thousands_sep() const; string grouping() const; string_type truename() const; string_type falsename() const; static locale::id id; protected: ~numpunct(); // virtual virtual char_type do_decimal_point() const; virtual char_type do_thousands_sep() const; virtual string do_grouping() const; virtual string_type do_truename() const; // for bool virtual string_type do_falsename() const; // for bool }; }
numpunct<> specifies numeric punctuation.
The specializations required in Table 86 ([locale.category]), namely numpunct<wchar_t> and numpunct<char>, provide classic "C" numeric formats, i.e., they contain information equivalent to that contained in the "C" locale or their wide character counterparts as if obtained by a call to widen.
The syntax for number formats is as follows, where digit represents the radix set specified by the fmtflags argument value, and thousands-sep and decimal-point are the results of corresponding numpunct<charT> members.
Integer values have the format:
intval:
sign units
sign:
+
-
units:
digits
digits thousands-sep units
digits:
digit digits
and floating-point values have:
floatval:
sign units fractional exponent
sign decimal-point digits exponent
fractional:
decimal-point digits
exponent:
e sign digits
e:
e
E
where the number of digits between thousands-seps is as specified by do_grouping().
For parsing, if the digits portion contains no thousands-separators, no grouping constraint is applied.

28.3.4.4.1.2 Members [facet.numpunct.members]

char_type decimal_point() const;
Returns: do_decimal_point().
char_type thousands_sep() const;
Returns: do_thousands_sep().
string grouping() const;
Returns: do_grouping().
string_type truename() const; string_type falsename() const;
Returns: do_truename() or do_falsename(), respectively.

28.3.4.4.1.3 Virtual functions [facet.numpunct.virtuals]

char_type do_decimal_point() const;
Returns: A character for use as the decimal radix separator.
The required specializations return '.' or L'.'.
char_type do_thousands_sep() const;
Returns: A character for use as the digit group separator.
The required specializations return ',' or L','.
string do_grouping() const;
Returns: A string vec used as a vector of integer values, in which each element vec[i] represents the number of digits228 in the group at position i, starting with position 0 as the rightmost group.
If vec.size() <= i, the number is the same as group (i - 1); if (i < 0 || vec[i] <= 0 || vec[i] == CHAR_MAX), the size of the digit group is unlimited.
The required specializations return the empty string, indicating no grouping.
string_type do_truename() const; string_type do_falsename() const;
Returns: A string representing the name of the boolean value true or false, respectively.
In the base class implementation these names are "true" and "false", or L"true" and L"false".
228)228)
Thus, the string "\003" specifies groups of 3 digits each, and "3" probably indicates groups of 51 (!) digits each, because 51 is the ASCII value of "3".

28.3.4.4.2 Class template numpunct_byname [locale.numpunct.byname]

namespace std { template<class charT> class numpunct_byname : public numpunct<charT> { // this class is specialized for char and wchar_t. public: using char_type = charT; using string_type = basic_string<charT>; explicit numpunct_byname(const char*, size_t refs = 0); explicit numpunct_byname(const string&, size_t refs = 0); protected: ~numpunct_byname(); }; }

28.3.4.5 The collate category [category.collate]

28.3.4.5.1 Class template collate [locale.collate]

28.3.4.5.1.1 General [locale.collate.general]

namespace std { template<class charT> class collate : public locale::facet { public: using char_type = charT; using string_type = basic_string<charT>; explicit collate(size_t refs = 0); int compare(const charT* low1, const charT* high1, const charT* low2, const charT* high2) const; string_type transform(const charT* low, const charT* high) const; long hash(const charT* low, const charT* high) const; static locale::id id; protected: ~collate(); virtual int do_compare(const charT* low1, const charT* high1, const charT* low2, const charT* high2) const; virtual string_type do_transform(const charT* low, const charT* high) const; virtual long do_hash (const charT* low, const charT* high) const; }; }
The class collate<charT> provides features for use in the collation (comparison) and hashing of strings.
A locale member function template, operator(), uses the collate facet to allow a locale to act directly as the predicate argument for standard algorithms ([algorithms]) and containers operating on strings.
The specializations required in Table 86 ([locale.category]), namely collate<char> and collate<wchar_t>, apply lexicographical ordering ([alg.lex.comparison]).
Each function compares a string of characters *p in the range [low, high).

28.3.4.5.1.2 Members [locale.collate.members]

int compare(const charT* low1, const charT* high1, const charT* low2, const charT* high2) const;
Returns: do_compare(low1, high1, low2, high2).
string_type transform(const charT* low, const charT* high) const;
Returns: do_transform(low, high).
long hash(const charT* low, const charT* high) const;
Returns: do_hash(low, high).

28.3.4.5.1.3 Virtual functions [locale.collate.virtuals]

int do_compare(const charT* low1, const charT* high1, const charT* low2, const charT* high2) const;
Returns: 1 if the first string is greater than the second, -1 if less, zero otherwise.
The specializations required in Table 86 ([locale.category]), namely collate<char> and collate<wchar_t>, implement a lexicographical comparison ([alg.lex.comparison]).
string_type do_transform(const charT* low, const charT* high) const;
Returns: A basic_string<charT> value that, compared lexicographically with the result of calling transform() on another string, yields the same result as calling do_compare() on the same two strings.229
long do_hash(const charT* low, const charT* high) const;
Returns: An integer value equal to the result of calling hash() on any other string for which do_compare() returns 0 (equal) when passed the two strings.
Recommended practice: The probability that the result equals that for another string which does not compare equal should be very small, approaching (1.0/numeric_limits<unsigned long>​::​max()).
229)229)
This function is useful when one string is being compared to many other strings.

28.3.4.5.2 Class template collate_byname [locale.collate.byname]

namespace std { template<class charT> class collate_byname : public collate<charT> { public: using string_type = basic_string<charT>; explicit collate_byname(const char*, size_t refs = 0); explicit collate_byname(const string&, size_t refs = 0); protected: ~collate_byname(); }; }

28.3.4.6 The time category [category.time]

28.3.4.6.1 General [category.time.general]

Templates time_get<charT, InputIterator> and time_put<charT, OutputIterator> provide date and time formatting and parsing.
All specifications of member functions for time_put and time_get in the subclauses of [category.time] only apply to the specializations required in Tables 86 and 87 ([locale.category]).
Their members use their ios_base&, ios_base​::​iostate&, and fill arguments as described in [locale.categories], and the ctype<> facet, to determine formatting details.

28.3.4.6.2 Class template time_get [locale.time.get]

28.3.4.6.2.1 General [locale.time.get.general]

namespace std { class time_base { public: enum dateorder { no_order, dmy, mdy, ymd, ydm }; }; template<class charT, class InputIterator = istreambuf_iterator<charT>> class time_get : public locale::facet, public time_base { public: using char_type = charT; using iter_type = InputIterator; explicit time_get(size_t refs = 0); dateorder date_order() const { return do_date_order(); } iter_type get_time(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t) const; iter_type get_date(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t) const; iter_type get_weekday(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t) const; iter_type get_monthname(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t) const; iter_type get_year(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t) const; iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, char format, char modifier = 0) const; iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, const char_type* fmt, const char_type* fmtend) const; static locale::id id; protected: ~time_get(); virtual dateorder do_date_order() const; virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&, ios_base::iostate& err, tm* t) const; virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&, ios_base::iostate& err, tm* t) const; virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&, ios_base::iostate& err, tm* t) const; virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&, ios_base::iostate& err, tm* t) const; virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&, ios_base::iostate& err, tm* t) const; virtual iter_type do_get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, char format, char modifier) const; }; }
time_get is used to parse a character sequence, extracting components of a time or date into a tm object.
Each get member parses a format as produced by a corresponding format specifier to time_put<>​::​put.
If the sequence being parsed matches the correct format, the corresponding members of the tm argument are set to the values used to produce the sequence; otherwise either an error is reported or unspecified values are assigned.230
If the end iterator is reached during parsing by any of the get() member functions, the member sets ios_base​::​eofbit in err.
230)230)
In other words, user confirmation is required for reliable parsing of user-entered dates and times, but machine-generated formats can be parsed reliably.
This allows parsers to be aggressive about interpreting user variations on standard formats.

28.3.4.6.2.2 Members [locale.time.get.members]

dateorder date_order() const;
Returns: do_date_order().
iter_type get_time(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Returns: do_get_time(s, end, str, err, t).
iter_type get_date(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Returns: do_get_date(s, end, str, err, t).
iter_type get_weekday(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const; iter_type get_monthname(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Returns: do_get_weekday(s, end, str, err, t) or do_get_monthname(s, end, str, err, t).
iter_type get_year(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Returns: do_get_year(s, end, str, err, t).
iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, char format, char modifier = 0) const;
Returns: do_get(s, end, f, err, t, format, modifier).
iter_type get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, const char_type* fmt, const char_type* fmtend) const;
Preconditions: [fmt, fmtend) is a valid range.
Effects: The function starts by evaluating err = ios_base​::​goodbit.
It then enters a loop, reading zero or more characters from s at each iteration.
Unless otherwise specified below, the loop terminates when the first of the following conditions holds:
  • The expression fmt == fmtend evaluates to true.
  • The expression err == ios_base​::​goodbit evaluates to false.
  • The expression s == end evaluates to true, in which case the function evaluates err = ios_base​::​eofbit | ios_base​::​failbit.
  • The next element of fmt is equal to '%', optionally followed by a modifier character, followed by a conversion specifier character, format, together forming a conversion specification valid for the POSIX function strptime.
    If the number of elements in the range [fmt, fmtend) is not sufficient to unambiguously determine whether the conversion specification is complete and valid, the function evaluates err = ios_base​::​failbit.
    Otherwise, the function evaluates s = do_get(s, end, f, err, t, format, modifier), where the value of modifier is '\0' when the optional modifier is absent from the conversion specification.
    If err == ios_base​::​goodbit holds after the evaluation of the expression, the function increments fmt to point just past the end of the conversion specification and continues looping.
  • The expression isspace(*fmt, f.getloc()) evaluates to true, in which case the function first increments fmt until fmt == fmtend || !isspace(*fmt, f.getloc()) evaluates to true, then advances s until s == end || !isspace(*s, f.getloc()) is true, and finally resumes looping.
  • The next character read from s matches the element pointed to by fmt in a case-insensitive comparison, in which case the function evaluates ++fmt, ++s and continues looping.
    Otherwise, the function evaluates err = ios_base​::​failbit.
[Note 1: 
The function uses the ctype<charT> facet installed in f's locale to determine valid whitespace characters.
It is unspecified by what means the function performs case-insensitive comparison or whether multi-character sequences are considered while doing so.
— end note]
Returns: s.

28.3.4.6.2.3 Virtual functions [locale.time.get.virtuals]

dateorder do_date_order() const;
Returns: An enumeration value indicating the preferred order of components for those date formats that are composed of day, month, and year.231
Returns no_order if the date format specified by 'x' contains other variable components (e.g., Julian day, week number, week day).
iter_type do_get_time(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Effects: Reads characters starting at s until it has extracted those tm members, and remaining format characters, used by time_put<>​::​put to produce the format specified by "%H:%M:%S", or until it encounters an error or end of sequence.
Returns: An iterator pointing immediately beyond the last character recognized as possibly part of a valid time.
iter_type do_get_date(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Effects: Reads characters starting at s until it has extracted those tm members and remaining format characters used by time_put<>​::​put to produce one of the following formats, or until it encounters an error.
The format depends on the value returned by date_order() as shown in Table 97.
Table 97do_get_date effects [tab:locale.time.get.dogetdate]
date_order()
Format
no_order
"%m%d%y"
dmy
"%d%m%y"
mdy
"%m%d%y"
ymd
"%y%m%d"
ydm
"%y%d%m"
An implementation may also accept additional implementation-defined formats.
Returns: An iterator pointing immediately beyond the last character recognized as possibly part of a valid date.
iter_type do_get_weekday(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const; iter_type do_get_monthname(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Effects: Reads characters starting at s until it has extracted the (perhaps abbreviated) name of a weekday or month.
If it finds an abbreviation that is followed by characters that can match a full name, it continues reading until it matches the full name or fails.
It sets the appropriate tm member accordingly.
Returns: An iterator pointing immediately beyond the last character recognized as part of a valid name.
iter_type do_get_year(iter_type s, iter_type end, ios_base& str, ios_base::iostate& err, tm* t) const;
Effects: Reads characters starting at s until it has extracted an unambiguous year identifier.
It is implementation-defined whether two-digit year numbers are accepted, and (if so) what century they are assumed to lie in.
Sets the t->tm_year member accordingly.
Returns: An iterator pointing immediately beyond the last character recognized as part of a valid year identifier.
iter_type do_get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm* t, char format, char modifier) const;
Preconditions: t points to an object.
Effects: The function starts by evaluating err = ios_base​::​goodbit.
It then reads characters starting at s until it encounters an error, or until it has extracted and assigned those tm members, and any remaining format characters, corresponding to a conversion specification appropriate for the POSIX function strptime, formed by concatenating '%', the modifier character, when non-NUL, and the format character.
When the concatenation fails to yield a complete valid directive the function leaves the object pointed to by t unchanged and evaluates err |= ios_base​::​failbit.
When s == end evaluates to true after reading a character the function evaluates err |= ios_base​::​eofbit.
For complex conversion specifications such as %c, %x, or %X, or conversion specifications that involve the optional modifiers E or O, when the function is unable to unambiguously determine some or all tm members from the input sequence [s, end), it evaluates err |= ios_base​::​eofbit.
In such cases the values of those tm members are unspecified and may be outside their valid range.
Returns: An iterator pointing immediately beyond the last character recognized as possibly part of a valid input sequence for the given format and modifier.
Remarks: It is unspecified whether multiple calls to do_get() with the address of the same tm object will update the current contents of the object or simply overwrite its members.
Portable programs should zero out the object before invoking the function.
231)231)
This function is intended as a convenience only, for common formats, and can return no_order in valid locales.

28.3.4.6.3 Class template time_get_byname [locale.time.get.byname]

namespace std { template<class charT, class InputIterator = istreambuf_iterator<charT>> class time_get_byname : public time_get<charT, InputIterator> { public: using dateorder = time_base::dateorder; using iter_type = InputIterator; explicit time_get_byname(const char*, size_t refs = 0); explicit time_get_byname(const string&, size_t refs = 0); protected: ~time_get_byname(); }; }

28.3.4.6.4 Class template time_put [locale.time.put]

28.3.4.6.4.1 General [locale.time.put.general]

namespace std { template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class time_put : public locale::facet { public: using char_type = charT; using iter_type = OutputIterator; explicit time_put(size_t refs = 0); // the following is implemented in terms of other member functions. iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb, const charT* pattern, const charT* pat_end) const; iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb, char format, char modifier = 0) const; static locale::id id; protected: ~time_put(); virtual iter_type do_put(iter_type s, ios_base&, char_type, const tm* t, char format, char modifier) const; }; }

28.3.4.6.4.2 Members [locale.time.put.members]

iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, const charT* pattern, const charT* pat_end) const; iter_type put(iter_type s, ios_base& str, char_type fill, const tm* t, char format, char modifier = 0) const;
Effects: The first form steps through the sequence from pattern to pat_end, identifying characters that are part of a format sequence.
Each character that is not part of a format sequence is written to s immediately, and each format sequence, as it is identified, results in a call to do_put; thus, format elements and other characters are interleaved in the output in the order in which they appear in the pattern.
Format sequences are identified by converting each character c to a char value as if by ct.narrow(c, 0), where ct is a reference to ctype<charT> obtained from str.getloc().
The first character of each sequence is equal to '%', followed by an optional modifier character mod232 and a format specifier character spec as defined for the function strftime.
If no modifier character is present, mod is zero.
For each valid format sequence identified, calls do_put(s, str, fill, t, spec, mod).
The second form calls do_put(s, str, fill, t, format, modifier).
[Note 1: 
The fill argument can be used in the implementation-defined formats or by derivations.
A space character is a reasonable default for this argument.
— end note]
Returns: An iterator pointing immediately after the last character produced.
232)232)
Although the C programming language defines no modifiers, most vendors do.

28.3.4.6.4.3 Virtual functions [locale.time.put.virtuals]

iter_type do_put(iter_type s, ios_base&, char_type fill, const tm* t, char format, char modifier) const;
Effects: Formats the contents of the parameter t into characters placed on the output sequence s.
Formatting is controlled by the parameters format and modifier, interpreted identically as the format specifiers in the string argument to the standard library function strftime(), except that the sequence of characters produced for those specifiers that are described as depending on the C locale are instead implementation-defined.
[Note 1: 
Interpretation of the modifier argument is implementation-defined.
— end note]
Returns: An iterator pointing immediately after the last character produced.
[Note 2: 
The fill argument can be used in the implementation-defined formats or by derivations.
A space character is a reasonable default for this argument.
— end note]
Recommended practice: Interpretation of the modifier should follow POSIX conventions.
Implementations should refer to other standards such as POSIX for a specification of the character sequences produced for those specifiers described as depending on the C locale.

28.3.4.6.5 Class template time_put_byname [locale.time.put.byname]

namespace std { template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class time_put_byname : public time_put<charT, OutputIterator> { public: using char_type = charT; using iter_type = OutputIterator; explicit time_put_byname(const char*, size_t refs = 0); explicit time_put_byname(const string&, size_t refs = 0); protected: ~time_put_byname(); }; }

28.3.4.7 The monetary category [category.monetary]

28.3.4.7.1 General [category.monetary.general]

These templates handle monetary formats.
A template parameter indicates whether local or international monetary formats are to be used.
All specifications of member functions for money_put and money_get in the subclauses of [category.monetary] only apply to the specializations required in Tables 86 and 87 ([locale.category]).
Their members use their ios_base&, ios_base​::​iostate&, and fill arguments as described in [locale.categories], and the moneypunct<> and ctype<> facets, to determine formatting details.

28.3.4.7.2 Class template money_get [locale.money.get]

28.3.4.7.2.1 General [locale.money.get.general]

namespace std { template<class charT, class InputIterator = istreambuf_iterator<charT>> class money_get : public locale::facet { public: using char_type = charT; using iter_type = InputIterator; using string_type = basic_string<charT>; explicit money_get(size_t refs = 0); iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, ios_base::iostate& err, long double& units) const; iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, ios_base::iostate& err, string_type& digits) const; static locale::id id; protected: ~money_get(); virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, ios_base::iostate& err, long double& units) const; virtual iter_type do_get(iter_type, iter_type, bool, ios_base&, ios_base::iostate& err, string_type& digits) const; }; }

28.3.4.7.2.2 Members [locale.money.get.members]

iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, ios_base::iostate& err, long double& quant) const; iter_type get(iter_type s, iter_type end, bool intl, ios_base& f, ios_base::iostate& err, string_type& quant) const;
Returns: do_get(s, end, intl, f, err, quant).

28.3.4.7.2.3 Virtual functions [locale.money.get.virtuals]

iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, ios_base::iostate& err, long double& units) const; iter_type do_get(iter_type s, iter_type end, bool intl, ios_base& str, ios_base::iostate& err, string_type& digits) const;
Effects: Reads characters from s to parse and construct a monetary value according to the format specified by a moneypunct<charT, Intl> facet reference mp and the character mapping specified by a ctype<charT> facet reference ct obtained from the locale returned by str.getloc(), and str.flags().
If a valid sequence is recognized, does not change err; otherwise, sets err to (err|str.failbit), or (err|str.failbit|str.eofbit) if no more characters are available, and does not change units or digits.
Uses the pattern returned by mp.neg_format() to parse all values.
The result is returned as an integral value stored in units or as a sequence of digits possibly preceded by a minus sign (as produced by ct.widen(c) where c is '-' or in the range from '0' through '9' (inclusive)) stored in digits.
[Example 1: 
The sequence $1,056.23 in a common United States locale would yield, for units, 105623, or, for digits, "105623".
— end example]
If mp.grouping() indicates that no thousands separators are permitted, any such characters are not read, and parsing is terminated at the point where they first appear.
Otherwise, thousands separators are optional; if present, they are checked for correct placement only after all format components have been read.
Where money_base​::​space or money_base​::​none appears as the last element in the format pattern, no whitespace is consumed.
Otherwise, where money_base​::​space appears in any of the initial elements of the format pattern, at least one whitespace character is required.
Where money_base​::​none appears in any of the initial elements of the format pattern, whitespace is allowed but not required.
If (str.flags() & str.showbase) is false, the currency symbol is optional and is consumed only if other characters are needed to complete the format; otherwise, the currency symbol is required.
If the first character (if any) in the string pos returned by mp.positive_sign() or the string neg returned by mp.negative_sign() is recognized in the position indicated by sign in the format pattern, it is consumed and any remaining characters in the string are required after all the other format components.
[Example 2: 
If showbase is off, then for a neg value of "()" and a currency symbol of "L", in "(100 L)" the "L" is consumed; but if neg is "-", the "L" in "-100 L" is not consumed.
— end example]
If pos or neg is empty, the sign component is optional, and if no sign is detected, the result is given the sign that corresponds to the source of the empty string.
Otherwise, the character in the indicated position must match the first character of pos or neg, and the result is given the corresponding sign.
If the first character of pos is equal to the first character of neg, or if both strings are empty, the result is given a positive sign.
Digits in the numeric monetary component are extracted and placed in digits, or into a character buffer buf1 for conversion to produce a value for units, in the order in which they appear, preceded by a minus sign if and only if the result is negative.
The value units is produced as if by233 for (int i = 0; i < n; ++i) buf2[i] = src[find(atoms, atoms+sizeof(src), buf1[i]) - atoms]; buf2[n] = 0; sscanf(buf2, "%Lf", &units); where n is the number of characters placed in buf1, buf2 is a character buffer, and the values src and atoms are defined as if by static const char src[] = "0123456789-"; charT atoms[sizeof(src)]; ct.widen(src, src + sizeof(src) - 1, atoms);
Returns: An iterator pointing immediately beyond the last character recognized as part of a valid monetary quantity.
233)233)
The semantics here are different from ct.narrow.

28.3.4.7.3 Class template money_put [locale.money.put]

28.3.4.7.3.1 General [locale.money.put.general]

namespace std { template<class charT, class OutputIterator = ostreambuf_iterator<charT>> class money_put : public locale::facet { public: using char_type = charT; using iter_type = OutputIterator; using string_type = basic_string<charT>; explicit money_put(size_t refs = 0); iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, long double units) const; iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, const string_type& digits) const; static locale::id id; protected: ~money_put(); virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, long double units) const; virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill, const string_type& digits) const; }; }

28.3.4.7.3.2 Members [locale.money.put.members]

iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, long double quant) const; iter_type put(iter_type s, bool intl, ios_base& f, char_type fill, const string_type& quant) const;
Returns: do_put(s, intl, f, loc, quant).

28.3.4.7.3.3 Virtual functions [locale.money.put.virtuals]

iter_type do_put(iter_type s, bool intl, ios_base& str, char_type fill, long double units) const; iter_type do_put(iter_type s, bool intl, ios_base& str, char_type fill, const string_type& digits) const;
Effects: Writes characters to s according to the format specified by a moneypunct<charT, Intl> facet reference mp and the character mapping specified by a ctype<charT> facet reference ct obtained from the locale returned by str.getloc(), and str.flags().
The argument units is transformed into a sequence of wide characters as if by ct.widen(buf1, buf1 + sprintf(buf1, "%.0Lf", units), buf2) for character buffers buf1 and buf2.
If the first character in digits or buf2 is equal to ct.widen('-'), then the pattern used for formatting is the result of mp.neg_format(); otherwise the pattern is the result of mp.pos_format().
Digit characters are written, interspersed with any thousands separators and decimal point specified by the format, in the order they appear (after the optional leading minus sign) in digits or buf2.
In digits, only the optional leading minus sign and the immediately subsequent digit characters (as classified according to ct) are used; any trailing characters (including digits appearing after a non-digit character) are ignored.
Calls str.width(0).
Returns: An iterator pointing immediately after the last character produced.
Remarks: The currency symbol is generated if and only if (str.flags() & str.showbase) is nonzero.
If the number of characters generated for the specified format is less than the value returned by str.width() on entry to the function, then copies of fill are inserted as necessary to pad to the specified width.
For the value af equal to (str.flags() & str.adjustfield), if (af == str.internal) is true, the fill characters are placed where none or space appears in the formatting pattern; otherwise if (af == str.left) is true, they are placed after the other characters; otherwise, they are placed before the other characters.
[Note 1: 
It is possible, with some combinations of format patterns and flag values, to produce output that cannot be parsed using num_get<>​::​get.
— end note]

28.3.4.7.4 Class template moneypunct [locale.moneypunct]

28.3.4.7.4.1 General [locale.moneypunct.general]

namespace std { class money_base { public: enum part { none, space, symbol, sign, value }; struct pattern { char field[4]; }; }; template<class charT, bool International = false> class moneypunct : public locale::facet, public money_base { public: using char_type = charT; using string_type = basic_string<charT>; explicit moneypunct(size_t refs = 0); charT decimal_point() const; charT thousands_sep() const; string grouping() const; string_type curr_symbol() const; string_type positive_sign() const; string_type negative_sign() const; int frac_digits() const; pattern pos_format() const; pattern neg_format() const; static locale::id id; static const bool intl = International; protected: ~moneypunct(); virtual charT do_decimal_point() const; virtual charT do_thousands_sep() const; virtual string do_grouping() const; virtual string_type do_curr_symbol() const; virtual string_type do_positive_sign() const; virtual string_type do_negative_sign() const; virtual int do_frac_digits() const; virtual pattern do_pos_format() const; virtual pattern do_neg_format() const; }; }
The moneypunct<> facet defines monetary formatting parameters used by money_get<> and money_put<>.
A monetary format is a sequence of four components, specified by a pattern value p, such that the part value static_cast<part>(p.field[i]) determines the component of the format234 In the field member of a pattern object, each value symbol, sign, value, and either space or none appears exactly once.
The value none, if present, is not first; the value space, if present, is neither first nor last.
Where none or space appears, whitespace is permitted in the format, except where none appears at the end, in which case no whitespace is permitted.
The value space indicates that at least one space is required at that position.
Where symbol appears, the sequence of characters returned by curr_symbol() is permitted, and can be required.
Where sign appears, the first (if any) of the sequence of characters returned by positive_sign() or negative_sign() (respectively as the monetary value is non-negative or negative) is required.
Any remaining characters of the sign sequence are required after all other format components.
Where value appears, the absolute numeric monetary value is required.
The format of the numeric monetary value is a decimal number:
value:
units fractional
decimal-point digits
fractional:
decimal-point digits
if frac_digits() returns a positive value, or
value:
units
otherwise.
The symbol decimal-point indicates the character returned by decimal_point().
The other symbols are defined as follows:
units:
digits
digits thousands-sep units
digits:
adigit digits
In the syntax specification, the symbol adigit is any of the values ct.widen(c) for c in the range '0' through '9' (inclusive) and ct is a reference of type const ctype<charT>& obtained as described in the definitions of money_get<> and money_put<>.
The symbol thousands-sep is the character returned by thousands_sep().
The space character used is the value ct.widen(' ').
Whitespace characters are those characters c for which ci.is(space, c) returns true.
The number of digits required after the decimal point (if any) is exactly the value returned by frac_digits().
The placement of thousands-separator characters (if any) is determined by the value returned by grouping(), defined identically as the member numpunct<>​::​do_grouping().
234)234)
An array of char, rather than an array of part, is specified for pattern​::​field purely for efficiency.

28.3.4.7.4.2 Members [locale.moneypunct.members]

charT decimal_point() const; charT thousands_sep() const; string grouping() const; string_type curr_symbol() const; string_type positive_sign() const; string_type negative_sign() const; int frac_digits() const; pattern pos_format() const; pattern neg_format() const;
Each of these functions F returns the result of calling the corresponding virtual member function do_F().

28.3.4.7.4.3 Virtual functions [locale.moneypunct.virtuals]

charT do_decimal_point() const;
Returns: The radix separator to use in case do_frac_digits() is greater than zero.235
charT do_thousands_sep() const;
Returns: The digit group separator to use in case do_grouping() specifies a digit grouping pattern.236
string do_grouping() const;
Returns: A pattern defined identically as, but not necessarily equal to, the result of numpunct<charT>​::​​do_grouping().237
string_type do_curr_symbol() const;
Returns: A string to use as the currency identifier symbol.
[Note 1: 
For specializations where the second template parameter is true, this is typically four characters long: a three-letter code as specified by ISO 4217[bib] followed by a space.
— end note]
string_type do_positive_sign() const; string_type do_negative_sign() const;
Returns: do_positive_sign() returns the string to use to indicate a positive monetary value;238 do_negative_sign() returns the string to use to indicate a negative value.
int do_frac_digits() const;
Returns: The number of digits after the decimal radix separator, if any.239
pattern do_pos_format() const; pattern do_neg_format() const;
Returns: The specializations required in Table 87 ([locale.category]), namely
  • moneypunct<char>,
  • moneypunct<wchar_t>,
  • moneypunct<char, true>, and
  • moneypunct<wchar_t, true>,
return an object of type pattern initialized to { symbol, sign, none, value }.240
235)235)
In common U.S. locales this is '.'.
236)236)
In common U.S. locales this is ','.
237)237)
To specify grouping by 3s, the value is "\003" not "3".
238)238)
This is usually the empty string.
239)239)
In common U.S. locales, this is 2.
240)240)
Note that the international symbol returned by do_curr_symbol() usually contains a space, itself; for example, "USD ".

28.3.4.7.5 Class template moneypunct_byname [locale.moneypunct.byname]

namespace std { template<class charT, bool Intl = false> class moneypunct_byname : public moneypunct<charT, Intl> { public: using pattern = money_base::pattern; using string_type = basic_string<charT>; explicit moneypunct_byname(const char*, size_t refs = 0); explicit moneypunct_byname(const string&, size_t refs = 0); protected: ~moneypunct_byname(); }; }

28.3.4.8 The message retrieval category [category.messages]

28.3.4.8.1 General [category.messages.general]

Class messages<charT> implements retrieval of strings from message catalogs.

28.3.4.8.2 Class template messages [locale.messages]

28.3.4.8.2.1 General [locale.messages.general]

namespace std { class messages_base { public: using catalog = unspecified signed integer type; }; template<class charT> class messages : public locale::facet, public messages_base { public: using char_type = charT; using string_type = basic_string<charT>; explicit messages(size_t refs = 0); catalog open(const string& fn, const locale&) const; string_type get(catalog c, int set, int msgid, const string_type& dfault) const; void close(catalog c) const; static locale::id id; protected: ~messages(); virtual catalog do_open(const string&, const locale&) const; virtual string_type do_get(catalog, int set, int msgid, const string_type& dfault) const; virtual void do_close(catalog) const; }; }
Values of type messages_base​::​catalog usable as arguments to members get and close can be obtained only by calling member open.

28.3.4.8.2.2 Members [locale.messages.members]

catalog open(const string& name, const locale& loc) const;
Returns: do_open(name, loc).
string_type get(catalog cat, int set, int msgid, const string_type& dfault) const;
Returns: do_get(cat, set, msgid, dfault).
void close(catalog cat) const;
Effects: Calls do_close(cat).

28.3.4.8.2.3 Virtual functions [locale.messages.virtuals]

catalog do_open(const string& name, const locale& loc) const;
Returns: A value that may be passed to get() to retrieve a message from the message catalog identified by the string name according to an implementation-defined mapping.
The result can be used until it is passed to close().
Returns a value less than 0 if no such catalog can be opened.
Remarks: The locale argument loc is used for character set code conversion when retrieving messages, if needed.
string_type do_get(catalog cat, int set, int msgid, const string_type& dfault) const;
Preconditions: cat is a catalog obtained from open() and not yet closed.
Returns: A message identified by arguments set, msgid, and dfault, according to an implementation-defined mapping.
If no such message can be found, returns dfault.
void do_close(catalog cat) const;
Preconditions: cat is a catalog obtained from open() and not yet closed.
Effects: Releases unspecified resources associated with cat.
Remarks: The limit on such resources, if any, is implementation-defined.

28.3.4.8.3 Class template messages_byname [locale.messages.byname]

namespace std { template<class charT> class messages_byname : public messages<charT> { public: using catalog = messages_base::catalog; using string_type = basic_string<charT>; explicit messages_byname(const char*, size_t refs = 0); explicit messages_byname(const string&, size_t refs = 0); protected: ~messages_byname(); }; }

28.3.5 C library locales [c.locales]

28.3.5.1 Header <clocale> synopsis [clocale.syn]

namespace std { struct lconv; char* setlocale(int category, const char* locale); lconv* localeconv(); } #define NULL see [support.types.nullptr] #define LC_ALL see below #define LC_COLLATE see below #define LC_CTYPE see below #define LC_MONETARY see below #define LC_NUMERIC see below #define LC_TIME see below
The contents and meaning of the header <clocale> are the same as the C standard library header <locale.h>.

28.3.5.2 Data races [clocale.data.races]

Calls to the function setlocale may introduce a data race ([res.on.data.races]) with other calls to setlocale or with calls to the functions listed in Table 98.
See also: ISO/IEC 9899:2018, 7.11
Table 98 — Potential setlocale data races [tab:setlocale.data.races]
fprintf
isprint
iswdigit
localeconv
tolower
fscanf
ispunct
iswgraph
mblen
toupper
isalnum
isspace
iswlower
mbstowcs
towlower
isalpha
isupper
iswprint
mbtowc
towupper
isblank
iswalnum
iswpunct
setlocale
wcscoll
iscntrl
iswalpha
iswspace
strcoll
wcstod
isdigit
iswblank
iswupper
strerror
wcstombs
isgraph
iswcntrl
iswxdigit
strtod
wcsxfrm
islower
iswctype
isxdigit
strxfrm
wctomb

28.4 Text encodings identification [text.encoding]

28.4.1 Header <text_encoding> synopsis [text.encoding.syn]

namespace std { struct text_encoding; // [text.encoding.hash], hash support template<class T> struct hash; template<> struct hash<text_encoding>; }

28.4.2 Class text_encoding [text.encoding.class]

28.4.2.1 Overview [text.encoding.overview]

The class text_encoding describes an interface for accessing the IANA Character Sets registry[bib].
namespace std { struct text_encoding { static constexpr size_t max_name_length = 63; // [text.encoding.id], enumeration text_encoding​::​id enum class id : int_least32_t { see below }; using enum id; constexpr text_encoding() = default; constexpr explicit text_encoding(string_view enc) noexcept; constexpr text_encoding(id i) noexcept; constexpr id mib() const noexcept; constexpr const char* name() const noexcept; // [text.encoding.aliases], class text_encoding​::​aliases_view struct aliases_view; constexpr aliases_view aliases() const noexcept; friend constexpr bool operator==(const text_encoding& a, const text_encoding& b) noexcept; friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept; static consteval text_encoding literal() noexcept; static text_encoding environment(); template<id i> static bool environment_is(); private: id mib_ = id::unknown; // exposition only char name_[max_name_length + 1] = {0}; // exposition only static constexpr bool comp-name(string_view a, string_view b); // exposition only }; }
Class text_encoding is a trivially copyable type ([basic.types.general]).

28.4.2.2 General [text.encoding.general]

A registered character encoding is a character encoding scheme in the IANA Character Sets registry.
[Note 1: 
The IANA Character Sets registry uses the term “character sets” to refer to character encodings.
— end note]
The primary name of a registered character encoding is the name of that encoding specified in the IANA Character Sets registry.
The set of known registered character encodings contains every registered character encoding specified in the IANA Character Sets registry except for the following:
Each known registered character encoding is identified by an enumerator in text_encoding​::​id, and has a set of zero or more aliases.
The set of aliases of a known registered character encoding is an implementation-defined superset of the aliases specified in the IANA Character Sets registry.
The set of aliases for US-ASCII includes “ASCII”.
No two aliases or primary names of distinct registered character encodings are equivalent when compared by text_encoding​::​comp-name.
How a text_encoding object is determined to be representative of a character encoding scheme implemented in the translation or execution environment is implementation-defined.
An object e of type text_encoding such that e.mib() == text_encoding​::​id​::​unknown is false and e.mib() == text_encoding​::​id​::​other is false maintains the following invariants:
  • *e.name() == '\0' is false, and
  • e.mib() == text_encoding(e.name()).mib() is true.
Recommended practice:
  • Implementations should not consider registered encodings to be interchangeable.
    [Example 1: 
    Shift_JIS and Windows-31J denote different encodings.
    — end example]
  • Implementations should not use the name of a registered encoding to describe another similar yet different non-registered encoding unless there is a precedent on that implementation.
    [Example 2: 
    Big5
    — end example]

28.4.2.3 Members [text.encoding.members]

constexpr explicit text_encoding(string_view enc) noexcept;
Preconditions:
  • enc represents a string in the ordinary literal encoding consisting only of elements of the basic character set ([lex.charset]).
  • enc.size() <= max_name_length is true.
  • enc.contains('\0') is false.
Postconditions:
  • If there exists a primary name or alias a of a known registered character encoding such that comp-name(a, enc) is true, mib_ has the value of the enumerator of id associated with that registered character encoding.
    Otherwise, mib_ == id​::​other is true.
  • enc.compare(name_) == 0 is true.
constexpr text_encoding(id i) noexcept;
Preconditions: i has the value of one of the enumerators of id.
Postconditions:
  • mib_ == i is true.
  • If (mib_ == id​::​unknown || mib_ == id​::​other) is true, strlen(name_) == 0 is true.
    Otherwise, ranges​::​contains(aliases(), string_view(name_)) is true.
constexpr id mib() const noexcept;
Returns: mib_.
constexpr const char* name() const noexcept;
Returns: name_.
Remarks: name() is an ntbs and accessing elements of name_ outside of the range is undefined behavior.
constexpr aliases_view aliases() const noexcept;
Let r denote an instance of aliases_view.
If *this represents a known registered character encoding, then:
  • r.front() is the primary name of the registered character encoding,
  • r contains the aliases of the registered character encoding, and
  • r does not contain duplicate values when compared with strcmp.
Otherwise, r is an empty range.
Each element in r is a non-null, non-empty ntbs encoded in the literal character encoding and comprising only characters from the basic character set.
Returns: r.
[Note 1: 
The order of aliases in r is unspecified.
— end note]
static consteval text_encoding literal() noexcept;
Mandates: CHAR_BIT == 8 is true.
Returns: A text_encoding object representing the ordinary character literal encoding ([lex.charset]).
static text_encoding environment();
Mandates: CHAR_BIT == 8 is true.
Returns: A text_encoding object representing the implementation-defined character encoding scheme of the environment.
On a POSIX implementation, this is the encoding scheme associated with the POSIX locale denoted by the empty string "".
[Note 2: 
This function is not affected by calls to setlocale.
— end note]
Recommended practice: Implementations should return a value that is not affected by calls to the POSIX function setenv and other functions which can modify the environment ([support.runtime]).
template<id i> static bool environment_is();
Mandates: CHAR_BIT == 8 is true.
Returns: environment() == i.
static constexpr bool comp-name(string_view a, string_view b);
Returns: true if the two strings a and b encoded in the ordinary literal encoding are equal, ignoring, from left-to-right,
  • all elements that are not digits or letters ([character.seq.general]),
  • character case, and
  • any sequence of one or more 0 characters not immediately preceded by a numeric prefix, where a numeric prefix is a sequence consisting of a digit in the range [1, 9] optionally followed by one or more elements which are not digits or letters,
and false otherwise.
[Note 3: 
This comparison is identical to the “Charset Alias Matching” algorithm described in the Unicode Technical Standard 22[bib].
— end note]
[Example 1: static_assert(comp-name("UTF-8", "utf8") == true); static_assert(comp-name("u.t.f-008", "utf8") == true); static_assert(comp-name("ut8", "utf8") == false); static_assert(comp-name("utf-80", "utf8") == false); — end example]

28.4.2.4 Comparison functions [text.encoding.cmp]

friend constexpr bool operator==(const text_encoding& a, const text_encoding& b) noexcept;
Returns: If a.mib_ == id​::​other && b.mib_ == id​::​other is true, then comp-name(a.name_,
b.name_)
.
Otherwise, a.mib_ == b.mib_.
friend constexpr bool operator==(const text_encoding& encoding, id i) noexcept;
Returns: encoding.mib_ == i.
Remarks: This operator induces an equivalence relation on its arguments if and only if i != id​::​other is true.

28.4.2.5 Class text_encoding​::​aliases_view [text.encoding.aliases]

struct text_encoding::aliases_view : ranges::view_interface<text_encoding::aliases_view> { constexpr implementation-defined begin() const; constexpr implementation-defined end() const; };
text_encoding​::​aliases_view models copyable, ranges​::​view, ranges​::​random_access_range, and ranges​::​borrowed_range.
[Note 1: 
text_encoding​::​aliases_view is not required to satisfy ranges​::​common_range, nor default_initializable.
— end note]
Both ranges​::​range_value_t<text_encoding​::​aliases_view> and ranges​::​range_reference_t<text_encoding​::​aliases_view> denote const char*.
ranges​::​iterator_t<text_encoding​::​aliases_view> is a constexpr iterator ([iterator.requirements.general]).

28.4.2.6 Enumeration text_encoding​::​id [text.encoding.id]

namespace std { enum class text_encoding::id : int_least32_t { other = 1, unknown = 2, ASCII = 3, ISOLatin1 = 4, ISOLatin2 = 5, ISOLatin3 = 6, ISOLatin4 = 7, ISOLatinCyrillic = 8, ISOLatinArabic = 9, ISOLatinGreek = 10, ISOLatinHebrew = 11, ISOLatin5 = 12, ISOLatin6 = 13, ISOTextComm = 14, HalfWidthKatakana = 15, JISEncoding = 16, ShiftJIS = 17, EUCPkdFmtJapanese = 18, EUCFixWidJapanese = 19, ISO4UnitedKingdom = 20, ISO11SwedishForNames = 21, ISO15Italian = 22, ISO17Spanish = 23, ISO21German = 24, ISO60DanishNorwegian = 25, ISO69French = 26, ISO10646UTF1 = 27, ISO646basic1983 = 28, INVARIANT = 29, ISO2IntlRefVersion = 30, NATSSEFI = 31, NATSSEFIADD = 32, ISO10Swedish = 35, KSC56011987 = 36, ISO2022KR = 37, EUCKR = 38, ISO2022JP = 39, ISO2022JP2 = 40, ISO13JISC6220jp = 41, ISO14JISC6220ro = 42, ISO16Portuguese = 43, ISO18Greek7Old = 44, ISO19LatinGreek = 45, ISO25French = 46, ISO27LatinGreek1 = 47, ISO5427Cyrillic = 48, ISO42JISC62261978 = 49, ISO47BSViewdata = 50, ISO49INIS = 51, ISO50INIS8 = 52, ISO51INISCyrillic = 53, ISO54271981 = 54, ISO5428Greek = 55, ISO57GB1988 = 56, ISO58GB231280 = 57, ISO61Norwegian2 = 58, ISO70VideotexSupp1 = 59, ISO84Portuguese2 = 60, ISO85Spanish2 = 61, ISO86Hungarian = 62, ISO87JISX0208 = 63, ISO88Greek7 = 64, ISO89ASMO449 = 65, ISO90 = 66, ISO91JISC62291984a = 67, ISO92JISC62991984b = 68, ISO93JIS62291984badd = 69, ISO94JIS62291984hand = 70, ISO95JIS62291984handadd = 71, ISO96JISC62291984kana = 72, ISO2033 = 73, ISO99NAPLPS = 74, ISO102T617bit = 75, ISO103T618bit = 76, ISO111ECMACyrillic = 77, ISO121Canadian1 = 78, ISO122Canadian2 = 79, ISO123CSAZ24341985gr = 80, ISO88596E = 81, ISO88596I = 82, ISO128T101G2 = 83, ISO88598E = 84, ISO88598I = 85, ISO139CSN369103 = 86, ISO141JUSIB1002 = 87, ISO143IECP271 = 88, ISO146Serbian = 89, ISO147Macedonian = 90, ISO150 = 91, ISO151Cuba = 92, ISO6937Add = 93, ISO153GOST1976874 = 94, ISO8859Supp = 95, ISO10367Box = 96, ISO158Lap = 97, ISO159JISX02121990 = 98, ISO646Danish = 99, USDK = 100, DKUS = 101, KSC5636 = 102, Unicode11UTF7 = 103, ISO2022CN = 104, ISO2022CNEXT = 105, UTF8 = 106, ISO885913 = 109, ISO885914 = 110, ISO885915 = 111, ISO885916 = 112, GBK = 113, GB18030 = 114, OSDEBCDICDF0415 = 115, OSDEBCDICDF03IRV = 116, OSDEBCDICDF041 = 117, ISO115481 = 118, KZ1048 = 119, UCS2 = 1000, UCS4 = 1001, UnicodeASCII = 1002, UnicodeLatin1 = 1003, UnicodeJapanese = 1004, UnicodeIBM1261 = 1005, UnicodeIBM1268 = 1006, UnicodeIBM1276 = 1007, UnicodeIBM1264 = 1008, UnicodeIBM1265 = 1009, Unicode11 = 1010, SCSU = 1011, UTF7 = 1012, UTF16BE = 1013, UTF16LE = 1014, UTF16 = 1015, CESU8 = 1016, UTF32 = 1017, UTF32BE = 1018, UTF32LE = 1019, BOCU1 = 1020, UTF7IMAP = 1021, Windows30Latin1 = 2000, Windows31Latin1 = 2001, Windows31Latin2 = 2002, Windows31Latin5 = 2003, HPRoman8 = 2004, AdobeStandardEncoding = 2005, VenturaUS = 2006, VenturaInternational = 2007, DECMCS = 2008, PC850Multilingual = 2009, PC8DanishNorwegian = 2012, PC862LatinHebrew = 2013, PC8Turkish = 2014, IBMSymbols = 2015, IBMThai = 2016, HPLegal = 2017, HPPiFont = 2018, HPMath8 = 2019, HPPSMath = 2020, HPDesktop = 2021, VenturaMath = 2022, MicrosoftPublishing = 2023, Windows31J = 2024, GB2312 = 2025, Big5 = 2026, Macintosh = 2027, IBM037 = 2028, IBM038 = 2029, IBM273 = 2030, IBM274 = 2031, IBM275 = 2032, IBM277 = 2033, IBM278 = 2034, IBM280 = 2035, IBM281 = 2036, IBM284 = 2037, IBM285 = 2038, IBM290 = 2039, IBM297 = 2040, IBM420 = 2041, IBM423 = 2042, IBM424 = 2043, PC8CodePage437 = 2011, IBM500 = 2044, IBM851 = 2045, PCp852 = 2010, IBM855 = 2046, IBM857 = 2047, IBM860 = 2048, IBM861 = 2049, IBM863 = 2050, IBM864 = 2051, IBM865 = 2052, IBM868 = 2053, IBM869 = 2054, IBM870 = 2055, IBM871 = 2056, IBM880 = 2057, IBM891 = 2058, IBM903 = 2059, IBM904 = 2060, IBM905 = 2061, IBM918 = 2062, IBM1026 = 2063, IBMEBCDICATDE = 2064, EBCDICATDEA = 2065, EBCDICCAFR = 2066, EBCDICDKNO = 2067, EBCDICDKNOA = 2068, EBCDICFISE = 2069, EBCDICFISEA = 2070, EBCDICFR = 2071, EBCDICIT = 2072, EBCDICPT = 2073, EBCDICES = 2074, EBCDICESA = 2075, EBCDICESS = 2076, EBCDICUK = 2077, EBCDICUS = 2078, Unknown8BiT = 2079, Mnemonic = 2080, Mnem = 2081, VISCII = 2082, VIQR = 2083, KOI8R = 2084, HZGB2312 = 2085, IBM866 = 2086, PC775Baltic = 2087, KOI8U = 2088, IBM00858 = 2089, IBM00924 = 2090, IBM01140 = 2091, IBM01141 = 2092, IBM01142 = 2093, IBM01143 = 2094, IBM01144 = 2095, IBM01145 = 2096, IBM01146 = 2097, IBM01147 = 2098, IBM01148 = 2099, IBM01149 = 2100, Big5HKSCS = 2101, IBM1047 = 2102, PTCP154 = 2103, Amiga1251 = 2104, KOI7switched = 2105, BRF = 2106, TSCII = 2107, CP51932 = 2108, windows874 = 2109, windows1250 = 2250, windows1251 = 2251, windows1252 = 2252, windows1253 = 2253, windows1254 = 2254, windows1255 = 2255, windows1256 = 2256, windows1257 = 2257, windows1258 = 2258, TIS620 = 2259, CP50220 = 2260 }; }
[Note 1: 
The text_encoding​::​id enumeration contains an enumerator for each known registered character encoding.
For each encoding, the corresponding enumerator is derived from the alias beginning with “cs”, as follows
  • csUnicode is mapped to text_encoding​::​id​::​UCS2,
  • csIBBM904 is mapped to text_encoding​::​id​::​IBM904, and
  • the “cs” prefix is removed from other names.
— end note]

28.4.2.7 Hash support [text.encoding.hash]

template<> struct hash<text_encoding>;
The specialization is enabled ([unord.hash]).

28.5 Formatting [format]

28.5.1 Header <format> synopsis [format.syn]

namespace std { // [format.context], class template basic_format_context template<class Out, class charT> class basic_format_context; using format_context = basic_format_context<unspecified, char>; using wformat_context = basic_format_context<unspecified, wchar_t>; // [format.args], class template basic_format_args template<class Context> class basic_format_args; using format_args = basic_format_args<format_context>; using wformat_args = basic_format_args<wformat_context>; // [format.fmt.string], class template basic_format_string template<class charT, class... Args> struct basic_format_string; template<class charT> struct runtime-format-string { // exposition only private: basic_string_view<charT> str; // exposition only public: runtime-format-string(basic_string_view<charT> s) noexcept : str(s) {} runtime-format-string(const runtime-format-string&) = delete; runtime-format-string& operator=(const runtime-format-string&) = delete; }; runtime-format-string<char> runtime_format(string_view fmt) noexcept { return fmt; } runtime-format-string<wchar_t> runtime_format(wstring_view fmt) noexcept { return fmt; } template<class... Args> using format_string = basic_format_string<char, type_identity_t<Args>...>; template<class... Args> using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>; // [format.functions], formatting functions template<class... Args> string format(format_string<Args...> fmt, Args&&... args); template<class... Args> wstring format(wformat_string<Args...> fmt, Args&&... args); template<class... Args> string format(const locale& loc, format_string<Args...> fmt, Args&&... args); template<class... Args> wstring format(const locale& loc, wformat_string<Args...> fmt, Args&&... args); string vformat(string_view fmt, format_args args); wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args); template<class Out, class... Args> Out format_to(Out out, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> Out format_to(Out out, wformat_string<Args...> fmt, Args&&... args); template<class Out, class... Args> Out format_to(Out out, const locale& loc, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> Out format_to(Out out, const locale& loc, wformat_string<Args...> fmt, Args&&... args); template<class Out> Out vformat_to(Out out, string_view fmt, format_args args); template<class Out> Out vformat_to(Out out, wstring_view fmt, wformat_args args); template<class Out> Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); template<class Out> Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args); template<class Out> struct format_to_n_result { Out out; iter_difference_t<Out> size; }; template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wformat_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wformat_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(format_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(wformat_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(const locale& loc, format_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(const locale& loc, wformat_string<Args...> fmt, Args&&... args); // [format.formatter], formatter template<class T, class charT = char> struct formatter; // [format.formatter.locking], formatter locking template<class T> constexpr bool enable_nonlocking_formatter_optimization = false; // [format.formattable], concept formattable template<class T, class charT> concept formattable = see below; template<class R, class charT> concept const-formattable-range = // exposition only ranges::input_range<const R> && formattable<ranges::range_reference_t<const R>, charT>; template<class R, class charT> using fmt-maybe-const = // exposition only conditional_t<const-formattable-range<R, charT>, const R, R>; // [format.parse.ctx], class template basic_format_parse_context template<class charT> class basic_format_parse_context; using format_parse_context = basic_format_parse_context<char>; using wformat_parse_context = basic_format_parse_context<wchar_t>; // [format.range], formatting of ranges // [format.range.fmtkind], variable template format_kind enum class range_format { disabled, map, set, sequence, string, debug_string }; template<class R> constexpr unspecified format_kind = unspecified; template<ranges::input_range R> requires same_as<R, remove_cvref_t<R>> constexpr range_format format_kind<R> = see below; // [format.range.formatter], class template range_formatter template<class T, class charT = char> requires same_as<remove_cvref_t<T>, T> && formattable<T, charT> class range_formatter; // [format.range.fmtdef], class template range-default-formatter template<range_format K, ranges::input_range R, class charT> struct range-default-formatter; // exposition only // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr], specializations for maps, sets, and strings template<ranges::input_range R, class charT> requires (format_kind<R> != range_format::disabled) && formattable<ranges::range_reference_t<R>, charT> struct formatter<R, charT> : range-default-formatter<format_kind<R>, R, charT> { }; template<ranges::input_range R> requires (format_kind<R> != range_format::disabled) constexpr bool enable_nonlocking_formatter_optimization<R> = false; // [format.arguments], arguments // [format.arg], class template basic_format_arg template<class Context> class basic_format_arg; // [format.arg.store], class template format-arg-store template<class Context, class... Args> class format-arg-store; // exposition only template<class Context = format_context, class... Args> format-arg-store<Context, Args...> make_format_args(Args&... fmt_args); template<class... Args> format-arg-store<wformat_context, Args...> make_wformat_args(Args&... args); // [format.error], class format_error class format_error; }
The class template format_to_n_result has the template parameters, data members, and special members specified above.
It has no base classes or members other than those specified.

28.5.2 Format string [format.string]

28.5.2.1 General [format.string.general]

A format string for arguments args is a (possibly empty) sequence of replacement fields, escape sequences, and characters other than { and }.
Let charT be the character type of the format string.
Each character that is not part of a replacement field or an escape sequence is copied unchanged to the output.
An escape sequence is one of {{ or }}.
It is replaced with { or }, respectively, in the output.
The syntax of replacement fields is as follows:
replacement-field:
{ arg-id format-specifier }
arg-id:
0
positive-integer
positive-integer:
nonzero-digit
positive-integer digit
nonnegative-integer:
digit
nonnegative-integer digit
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
digit: one of
0 1 2 3 4 5 6 7 8 9
format-specifier:
: format-spec
format-spec:
as specified by the formatter specialization for the argument type; cannot start with }
The arg-id field specifies the index of the argument in args whose value is to be formatted and inserted into the output instead of the replacement field.
If there is no argument with the index arg-id in args, the string is not a format string for args.
The optional format-specifier field explicitly specifies a format for the replacement value.
[Example 1: string s = format("{0}-{{", 8); // value of s is "8-{" — end example]
If all arg-ids in a format string are omitted (including those in the format-spec, as interpreted by the corresponding formatter specialization), argument indices 0, 1, 2, … will automatically be used in that order.
If some arg-ids are omitted and some are present, the string is not a format string.
[Note 1: 
A format string cannot contain a mixture of automatic and manual indexing.
— end note]
[Example 2: string s0 = format("{} to {}", "a", "b"); // OK, automatic indexing string s1 = format("{1} to {0}", "a", "b"); // OK, manual indexing string s2 = format("{0} to {}", "a", "b"); // not a format string (mixing automatic and manual indexing), // ill-formed string s3 = format("{} to {1}", "a", "b"); // not a format string (mixing automatic and manual indexing), // ill-formed — end example]
The format-spec field contains format specifications that define how the value should be presented.
Each type can define its own interpretation of the format-spec field.
If format-spec does not conform to the format specifications for the argument type referred to by arg-id, the string is not a format string for args.
[Example 3: 
  • For arithmetic, pointer, and string types the format-spec is interpreted as a std-format-spec as described in ([format.string.std]).
  • For chrono types the format-spec is interpreted as a chrono-format-spec as described in ([time.format]).
  • For user-defined formatter specializations, the behavior of the parse member function determines how the format-spec is interpreted.
— end example]

28.5.2.2 Standard format specifiers [format.string.std]

Each formatter specialization described in [format.formatter.spec] for fundamental and string types interprets format-spec as a std-format-spec.
[Note 1: 
The format specification can be used to specify such details as minimum field width, alignment, padding, and decimal precision.
Some of the formatting options are only supported for arithmetic types.
— end note]
The syntax of format specifications is as follows:
std-format-spec:
fill-and-align sign # 0 width precision L type
fill-and-align:
fill align
fill:
any character other than { or }
align: one of
< > ^
sign: one of
+ - space
width:
positive-integer
{ arg-id }
precision:
. nonnegative-integer
. { arg-id }
type: one of
a A b B c d e E f F g G o p P s x X ?
Field widths are specified in field width units; the number of column positions required to display a sequence of characters in a terminal.
The minimum field width is the number of field width units a replacement field minimally requires of the formatted sequence of characters produced for a format argument.
The estimated field width is the number of field width units that are required for the formatted sequence of characters produced for a format argument independent of the effects of the width option.
The padding width is the greater of 0 and the difference of the minimum field width and the estimated field width.
[Note 2: 
The POSIX wcswidth function is an example of a function that, given a string, returns the number of column positions required by a terminal to display the string.
— end note]
The fill character is the character denoted by the fill option or, if the fill option is absent, the space character.
For a format specification in UTF-8, UTF-16, or UTF-32, the fill character corresponds to a single Unicode scalar value.
[Note 3: 
The presence of a fill option is signaled by the character following it, which must be one of the alignment options.
If the second character of std-format-spec is not a valid alignment option, then it is assumed that the fill and align options are both absent.
— end note]
The align option applies to all argument types.
The meaning of the various alignment options is as specified in Table 99.
[Example 1: char c = 120; string s0 = format("{:6}", 42); // value of s0 is "    42" string s1 = format("{:6}", 'x'); // value of s1 is "x     " string s2 = format("{:*<6}", 'x'); // value of s2 is "x*****" string s3 = format("{:*>6}", 'x'); // value of s3 is "*****x" string s4 = format("{:*^6}", 'x'); // value of s4 is "**x***" string s5 = format("{:6d}", c); // value of s5 is "   120" string s6 = format("{:6}", true); // value of s6 is "true  " string s7 = format("{:*<6.3}", "123456"); // value of s7 is "123***" string s8 = format("{:02}", 1234); // value of s8 is "1234" string s9 = format("{:*<}", "12"); // value of s9 is "12" string sA = format("{:*<6}", "12345678"); // value of sA is "12345678" string sB = format("{:🤡^6}", "x"); // value of sB is "🤡🤡x🤡🤡🤡" string sC = format("{:*^6}", "🤡🤡🤡"); // value of sC is "🤡🤡🤡" — end example]
[Note 4: 
The fill, align, and 0 options have no effect when the minimum field width is not greater than the estimated field width because padding width is 0 in that case.
Since fill characters are assumed to have a field width of 1, use of a character with a different field width can produce misaligned output.
The 🤡 (U+1f921 clown face) character has a field width of 2.
The examples above that include that character illustrate the effect of the field width when that character is used as a fill character as opposed to when it is used as a formatting argument.
— end note]
Table 99 — Meaning of align options [tab:format.align]
Option
Meaning
<
Forces the formatted argument to be aligned to the start of the field by inserting n fill characters after the formatted argument where n is the padding width.
This is the default for non-arithmetic non-pointer types, charT, and bool, unless an integer presentation type is specified.
>
Forces the formatted argument to be aligned to the end of the field by inserting n fill characters before the formatted argument where n is the padding width.
This is the default for arithmetic types other than charT and bool, pointer types, or when an integer presentation type is specified.
^
Forces the formatted argument to be centered within the field by inserting fill characters before and fill characters after the formatted argument, where n is the padding width.
The sign option is only valid for arithmetic types other than charT and bool or when an integer presentation type is specified.
The meaning of the various options is as specified in Table 100.
Table 100 — Meaning of sign options [tab:format.sign]
Option
Meaning
+
Indicates that a sign should be used for both non-negative and negative numbers.
The + sign is inserted before the output of to_chars for non-negative numbers other than negative zero.
[Note 5: 
For negative numbers and negative zero the output of to_chars will already contain the sign so no additional transformation is performed.
— end note]
-
Indicates that a sign should be used for negative numbers and negative zero only (this is the default behavior).
space
Indicates that a leading space should be used for non-negative numbers other than negative zero, and a minus sign for negative numbers and negative zero.
The sign option applies to floating-point infinity and NaN.
[Example 2: double inf = numeric_limits<double>::infinity(); double nan = numeric_limits<double>::quiet_NaN(); string s0 = format("{0:},{0:+},{0:-},{0: }", 1); // value of s0 is "1,+1,1, 1" string s1 = format("{0:},{0:+},{0:-},{0: }", -1); // value of s1 is "-1,-1,-1,-1" string s2 = format("{0:},{0:+},{0:-},{0: }", inf); // value of s2 is "inf,+inf,inf, inf" string s3 = format("{0:},{0:+},{0:-},{0: }", nan); // value of s3 is "nan,+nan,nan, nan" — end example]
The # option causes the alternate form to be used for the conversion.
This option is valid for arithmetic types other than charT and bool or when an integer presentation type is specified, and not otherwise.
For integral types, the alternate form inserts the base prefix (if any) specified in Table 102 into the output after the sign character (possibly space) if there is one, or before the output of to_chars otherwise.
For floating-point types, the alternate form causes the result of the conversion of finite values to always contain a decimal-point character, even if no digits follow it.
Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.
In addition, for g and G conversions, trailing zeros are not removed from the result.
The 0 option is valid for arithmetic types other than charT and bool, pointer types, or when an integer presentation type is specified.
For formatting arguments that have a value other than an infinity or a NaN, this option pads the formatted argument by inserting the 0 character n times following the sign or base prefix indicators (if any) where n is 0 if the align option is present and is the padding width otherwise.
[Example 3: char c = 120; string s1 = format("{:+06d}", c); // value of s1 is "+00120" string s2 = format("{:#06x}", 0xa); // value of s2 is "0x000a" string s3 = format("{:<06}", -42); // value of s3 is "-42   " (0 has no effect) string s4 = format("{:06}", inf); // value of s4 is "   inf" (0 has no effect) — end example]
The width option specifies the minimum field width.
If the width option is absent, the minimum field width is 0.
If { arg-id } is used in a width or precision option, the value of the corresponding formatting argument is used as the value of the option.
The option is valid only if the corresponding formatting argument is of standard signed or unsigned integer type.
If its value is negative, an exception of type format_error is thrown.
If positive-integer is used in a width option, the value of the positive-integer is interpreted as a decimal integer and used as the value of the option.
For the purposes of width computation, a string is assumed to be in a locale-independent, implementation-defined encoding.
Implementations should use either UTF-8, UTF-16, or UTF-32, on platforms capable of displaying Unicode text in a terminal.
[Note 6: 
This is the case for Windows®-based241 and many POSIX-based operating systems.
— end note]
For a sequence of characters in UTF-8, UTF-16, or UTF-32, an implementation should use as its field width the sum of the field widths of the first code point of each extended grapheme cluster.
Extended grapheme clusters are defined by UAX #29 of the Unicode Standard.
The following code points have a field width of 2:
  • any code point with the East_Asian_Width="W" or East_Asian_Width="F" property as described by UAX #44 of the Unicode Standard
  • U+4dc0U+4dff (Yijing Hexagram Symbols)
  • U+1f300U+1f5ff (Miscellaneous Symbols and Pictographs)
  • U+1f900U+1f9ff (Supplemental Symbols and Pictographs)
The field width of all other code points is 1.
For a sequence of characters in neither UTF-8, UTF-16, nor UTF-32, the field width is unspecified.
The precision option is valid for floating-point and string types.
For floating-point types, the value of this option specifies the precision to be used for the floating-point presentation type.
For string types, this option specifies the longest prefix of the formatted argument to be included in the replacement field such that the field width of the prefix is no greater than the value of this option.
If nonnegative-integer is used in a precision option, the value of the decimal integer is used as the value of the option.
When the L option is used, the form used for the conversion is called the locale-specific form.
The L option is only valid for arithmetic types, and its effect depends upon the type.
  • For integral types, the locale-specific form causes the context's locale to be used to insert the appropriate digit group separator characters.
  • For floating-point types, the locale-specific form causes the context's locale to be used to insert the appropriate digit group and radix separator characters.
  • For the textual representation of bool, the locale-specific form causes the context's locale to be used to insert the appropriate string as if obtained with numpunct​::​truename or numpunct​::​falsename.
The type determines how the data should be presented.
The available string presentation types are specified in Table 101.
Table 101 — Meaning of type options for strings [tab:format.type.string]
Type
Meaning
none, s
Copies the string to the output.
?
Copies the escaped string ([format.string.escaped]) to the output.
The meaning of some non-string presentation types is defined in terms of a call to to_chars.
In such cases, let [first, last) be a range large enough to hold the to_chars output and value be the formatting argument value.
Formatting is done as if by calling to_chars as specified and copying the output through the output iterator of the format context.
[Note 7: 
Additional padding and adjustments are performed prior to copying the output through the output iterator as specified by the format specifiers.
— end note]
The available integer presentation types for integral types other than bool and charT are specified in Table 102.
[Example 4: string s0 = format("{}", 42); // value of s0 is "42" string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42); // value of s1 is "101010 42 52 2a" string s2 = format("{0:#x} {0:#X}", 42); // value of s2 is "0x2a 0X2A" string s3 = format("{:L}", 1234); // value of s3 can be "1,234" // (depending on the locale) — end example]
Table 102 — Meaning of type options for integer types [tab:format.type.int]
Type
Meaning
b
to_chars(first, last, value, 2); the base prefix is 0b.
B
The same as b, except that the base prefix is 0B.
c
Copies the character static_cast<charT>(value) to the output.
Throws format_error if value is not in the range of representable values for charT.
d
to_chars(first, last, value).
o
to_chars(first, last, value, 8); the base prefix is 0 if value is nonzero and is empty otherwise.
x
to_chars(first, last, value, 16); the base prefix is 0x.
X
The same as x, except that it uses uppercase letters for digits above 9 and the base prefix is 0X.
none
The same as d.
[Note 8: 
If the formatting argument type is charT or bool, the default is instead c or s, respectively.
— end note]
The available charT presentation types are specified in Table 103.
Table 103 — Meaning of type options for charT[tab:format.type.char]
Type
Meaning
none, c
Copies the character to the output.
b, B, d, o, x, X
As specified in Table 102 with value converted to the unsigned version of the underlying type.
?
Copies the escaped character ([format.string.escaped]) to the output.
The available bool presentation types are specified in Table 104.
Table 104 — Meaning of type options for bool[tab:format.type.bool]
Type
Meaning
none, s
Copies textual representation, either true or false, to the output.
b, B, d, o, x, X
As specified in Table 102 for the value static_cast<unsigned char>(value).
The available floating-point presentation types and their meanings for values other than infinity and NaN are specified in Table 105.
For lower-case presentation types, infinity and NaN are formatted as inf and nan, respectively.
For upper-case presentation types, infinity and NaN are formatted as INF and NAN, respectively.
[Note 9: 
In either case, a sign is included if indicated by the sign option.
— end note]
Table 105 — Meaning of type options for floating-point types [tab:format.type.float]
Type
Meaning
a
If precision is specified, equivalent to to_chars(first, last, value, chars_format::hex, precision) where precision is the specified formatting precision; equivalent to to_chars(first, last, value, chars_format::hex) otherwise.
A
The same as a, except that it uses uppercase letters for digits above 9 and P to indicate the exponent.
e
Equivalent to to_chars(first, last, value, chars_format::scientific, precision) where precision is the specified formatting precision, or 6 if precision is not specified.
E
The same as e, except that it uses E to indicate exponent.
f, F
Equivalent to to_chars(first, last, value, chars_format::fixed, precision) where precision is the specified formatting precision, or 6 if precision is not specified.
g
Equivalent to to_chars(first, last, value, chars_format::general, precision) where precision is the specified formatting precision, or 6 if precision is not specified.
G
The same as g, except that it uses E to indicate exponent.
none
If precision is specified, equivalent to to_chars(first, last, value, chars_format::general, precision) where precision is the specified formatting precision; equivalent to to_chars(first, last, value) otherwise.
The available pointer presentation types and their mapping to to_chars are specified in Table 106.
[Note 10: 
Pointer presentation types also apply to nullptr_t.
— end note]
Table 106 — Meaning of type options for pointer types [tab:format.type.ptr]
Type
Meaning
none, p
If uintptr_t is defined, to_chars(first, last, reinterpret_cast<uintptr_t>(value), 16) with the prefix 0x inserted immediately before the output of to_chars; otherwise, implementation-defined.
P
The same as p, except that it uses uppercase letters for digits above 9 and the base prefix is 0X.
241)241)
Windows® is a registered trademark of Microsoft Corporation.
This information is given for the convenience of users of this document and does not constitute an endorsement by ISO or IEC of this product.

28.5.3 Error reporting [format.err.report]

Formatting functions throw format_error if an argument fmt is passed that is not a format string for args.
They propagate exceptions thrown by operations of formatter specializations and iterators.
Failure to allocate storage is reported by throwing an exception as described in [res.on.exception.handling].

28.5.4 Class template basic_format_string [format.fmt.string]

namespace std { template<class charT, class... Args> struct basic_format_string { private: basic_string_view<charT> str; // exposition only public: template<class T> consteval basic_format_string(const T& s); basic_format_string(runtime-format-string<charT> s) noexcept : str(s.str) {} constexpr basic_string_view<charT> get() const noexcept { return str; } }; }
template<class T> consteval basic_format_string(const T& s);
Constraints: const T& models convertible_to<basic_string_view<charT>>.
Effects: Direct-non-list-initializes str with s.
Remarks: A call to this function is not a core constant expression ([expr.const]) unless there exist args of types Args such that str is a format string for args.

28.5.5 Formatting functions [format.functions]

In the description of the functions, operator + is used for some of the iterator categories for which it does not have to be defined.
In these cases the semantics of a + n are the same as in [algorithms.requirements].
template<class... Args> string format(format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat(fmt.str, make_format_args(args...));
template<class... Args> wstring format(wformat_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat(fmt.str, make_wformat_args(args...));
template<class... Args> string format(const locale& loc, format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat(loc, fmt.str, make_format_args(args...));
template<class... Args> wstring format(const locale& loc, wformat_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat(loc, fmt.str, make_wformat_args(args...));
string vformat(string_view fmt, format_args args); wstring vformat(wstring_view fmt, wformat_args args); string vformat(const locale& loc, string_view fmt, format_args args); wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
Returns: A string object holding the character representation of formatting arguments provided by args formatted according to specifications given in fmt.
If present, loc is used for locale-specific formatting.
Throws: As specified in [format.err.report].
template<class Out, class... Args> Out format_to(Out out, format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat_to(std::move(out), fmt.str, make_format_args(args...));
template<class Out, class... Args> Out format_to(Out out, wformat_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat_to(std::move(out), fmt.str, make_wformat_args(args...));
template<class Out, class... Args> Out format_to(Out out, const locale& loc, format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat_to(std::move(out), loc, fmt.str, make_format_args(args...));
template<class Out, class... Args> Out format_to(Out out, const locale& loc, wformat_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: return vformat_to(std::move(out), loc, fmt.str, make_wformat_args(args...));
template<class Out> Out vformat_to(Out out, string_view fmt, format_args args); template<class Out> Out vformat_to(Out out, wstring_view fmt, wformat_args args); template<class Out> Out vformat_to(Out out, const locale& loc, string_view fmt, format_args args); template<class Out> Out vformat_to(Out out, const locale& loc, wstring_view fmt, wformat_args args);
Let charT be decltype(fmt)​::​value_type.
Constraints: Out satisfies output_iterator<const charT&>.
Preconditions: Out models output_iterator<const charT&>.
Effects: Places the character representation of formatting the arguments provided by args, formatted according to the specifications given in fmt, into the range [out, out + N), where N is the number of characters in that character representation.
If present, loc is used for locale-specific formatting.
Returns: out + N.
Throws: As specified in [format.err.report].
template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wformat_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, format_string<Args...> fmt, Args&&... args); template<class Out, class... Args> format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wformat_string<Args...> fmt, Args&&... args);
Let
  • charT be decltype(fmt.str)​::​value_type,
  • N be formatted_size(fmt, args...) for the functions without a loc parameter and formatted_size(loc, fmt, args...) for the functions with a loc parameter, and
  • M be clamp(n, 0, N).
Constraints: Out satisfies output_iterator<const charT&>.
Preconditions: Out models output_iterator<const charT&>, and formatter<>, charT> meets the BasicFormatter requirements ([formatter.requirements]) for each in Args.
Effects: Places the first M characters of the character representation of formatting the arguments provided by args, formatted according to the specifications given in fmt, into the range [out, out + M).
If present, loc is used for locale-specific formatting.
Returns: {out + M, N}.
Throws: As specified in [format.err.report].
template<class... Args> size_t formatted_size(format_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(wformat_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(const locale& loc, format_string<Args...> fmt, Args&&... args); template<class... Args> size_t formatted_size(const locale& loc, wformat_string<Args...> fmt, Args&&... args);
Let charT be decltype(fmt.str)​::​value_type.
Preconditions: formatter<>, charT> meets the BasicFormatter requirements ([formatter.requirements]) for each in Args.
Returns: The number of characters in the character representation of formatting arguments args formatted according to specifications given in fmt.
If present, loc is used for locale-specific formatting.
Throws: As specified in [format.err.report].

28.5.6 Formatter [format.formatter]

28.5.6.1 Formatter requirements [formatter.requirements]

A type F meets the BasicFormatter requirements if it meets the requirements, and the expressions shown in Table 107 are valid and have the indicated semantics.
A type F meets the Formatter requirements if it meets the BasicFormatter requirements and the expressions shown in Table 108 are valid and have the indicated semantics.
Given character type charT, output iterator type Out, and formatting argument type T, in Table 107 and Table 108:
  • f is a value of type (possibly const) F,
  • g is an lvalue of type F,
  • u is an lvalue of type T,
  • t is a value of a type convertible to (possibly const) T,
  • PC is basic_format_parse_context<charT>,
  • FC is basic_format_context<Out, charT>,
  • pc is an lvalue of type PC, and
  • fc is an lvalue of type FC.
pc.begin() points to the beginning of the format-spec ([format.string]) of the replacement field being formatted in the format string.
If format-spec is not present or empty then either pc.begin() == pc.end() or *pc.begin() == '}'.
Table 107BasicFormatter requirements [tab:formatter.basic]
Expression
Return type
Requirement
g.parse(pc)
PC​::​iterator
Parses format-spec ([format.string]) for type T in the range [pc.begin(), pc.end()) until the first unmatched character.
Throws format_error unless the whole range is parsed or the unmatched character is }.
[Note 1: 
This allows formatters to emit meaningful error messages.
— end note]
Stores the parsed format specifiers in *this and returns an iterator past the end of the parsed range.
f.format(u, fc)
FC​::​iterator
Formats u according to the specifiers stored in *this, writes the output to fc.out(), and returns an iterator past the end of the output range.
The output shall only depend on u, fc.locale(), fc.arg(n) for any value n of type size_t, and the range [pc.begin(), pc.end()) from the last call to f.parse(pc).
Table 108Formatter requirements [tab:formatter]
Expression
Return type
Requirement
f.format(t, fc)
FC​::​iterator
Formats t according to the specifiers stored in *this, writes the output to fc.out(), and returns an iterator past the end of the output range.
The output shall only depend on t, fc.locale(), fc.arg(n) for any value n of type size_t, and the range [pc.begin(), pc.end()) from the last call to f.parse(pc).
f.format(u, fc)
FC​::​iterator
As above, but does not modify u.

28.5.6.2 Formatter locking [format.formatter.locking]

template<class T> constexpr bool enable_nonlocking_formatter_optimization = false;
Remarks: Pursuant to [namespace.std], users may specialize enable_nonlocking_formatter_optimization for cv-unqualified program-defined types.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const bool.

28.5.6.3 Concept formattable [format.formattable]

Let fmt-iter-for<charT> be an unspecified type that models output_iterator<const charT&> ([iterator.concept.output]).
template<class T, class Context, class Formatter = typename Context::template formatter_type<remove_const_t<T>>> concept formattable-with = // exposition only semiregular<Formatter> && requires(Formatter& f, const Formatter& cf, T&& t, Context fc, basic_format_parse_context<typename Context::char_type> pc) { { f.parse(pc) } -> same_as<typename decltype(pc)::iterator>; { cf.format(t, fc) } -> same_as<typename Context::iterator>; }; template<class T, class charT> concept formattable = formattable-with<remove_reference_t<T>, basic_format_context<fmt-iter-for<charT>, charT>>;
A type T and a character type charT model formattable if formatter<remove_cvref_t<T>, charT> meets the BasicFormatter requirements ([formatter.requirements]) and, if remove_reference_t<T> is const-qualified, the Formatter requirements.

28.5.6.4 Formatter specializations [format.formatter.spec]

The functions defined in [format.functions] use specializations of the class template formatter to format individual arguments.
Let charT be either char or wchar_t.
Each specialization of formatter is either enabled or disabled, as described below.
A debug-enabled specialization of formatter additionally provides a public, constexpr, non-static member function set_debug_format() which modifies the state of the formatter to be as if the type of the std-format-spec parsed by the last call to parse were ?.
Each header that declares the template formatter provides the following enabled specializations:
  • The debug-enabled specializations template<> struct formatter<char, char>; template<> struct formatter<char, wchar_t>; template<> struct formatter<wchar_t, wchar_t>;
  • For each charT, the debug-enabled string type specializations template<> struct formatter<charT*, charT>; template<> struct formatter<const charT*, charT>; template<size_t N> struct formatter<charT[N], charT>; template<class traits, class Allocator> struct formatter<basic_string<charT, traits, Allocator>, charT>; template<class traits> struct formatter<basic_string_view<charT, traits>, charT>;
  • For each charT, for each cv-unqualified arithmetic type ArithmeticT other than char, wchar_t, char8_t, char16_t, or char32_t, a specialization template<> struct formatter<ArithmeticT, charT>;
  • For each charT, the pointer type specializations template<> struct formatter<nullptr_t, charT>; template<> struct formatter<void*, charT>; template<> struct formatter<const void*, charT>;
The parse member functions of these formatters interpret the format specification as a std-format-spec as described in [format.string.std].
Unless specified otherwise, for each type T for which a formatter specialization is provided by the library, each of the headers provides the following specialization: template<> inline constexpr bool enable_nonlocking_formatter_optimization<T> = true;
[Note 1: 
Specializations such as formatter<wchar_t, char> that would require implicit multibyte / wide string or character conversion are disabled.
— end note]
The header <format> provides the following disabled specializations:
  • The string type specializations template<> struct formatter<char*, wchar_t>; template<> struct formatter<const char*, wchar_t>; template<size_t N> struct formatter<char[N], wchar_t>; template<class traits, class Allocator> struct formatter<basic_string<char, traits, Allocator>, wchar_t>; template<class traits> struct formatter<basic_string_view<char, traits>, wchar_t>;
For any types T and charT for which neither the library nor the user provides an explicit or partial specialization of the class template formatter, formatter<T, charT> is disabled.
If the library provides an explicit or partial specialization of formatter<T, charT>, that specialization is enabled and meets the Formatter requirements except as noted otherwise.
If F is a disabled specialization of formatter, these values are false:
  • is_default_constructible_v<F>,
  • is_copy_constructible_v<F>,
  • is_move_constructible_v<F>,
  • is_copy_assignable_v<F>, and
  • is_move_assignable_v<F>.
An enabled specialization formatter<T, charT> meets the BasicFormatter requirements ([formatter.requirements]).
[Example 1: #include <format> #include <string> enum color { red, green, blue }; const char* color_names[] = { "red", "green", "blue" }; template<> struct std::formatter<color> : std::formatter<const char*> { auto format(color c, format_context& ctx) const { return formatter<const char*>::format(color_names[c], ctx); } }; struct err {}; std::string s0 = std::format("{}", 42); // OK, library-provided formatter std::string s1 = std::format("{}", L"foo"); // error: disabled formatter std::string s2 = std::format("{}", red); // OK, user-provided formatter std::string s3 = std::format("{}", err{}); // error: disabled formatter — end example]

28.5.6.5 Formatting escaped characters and strings [format.string.escaped]

A character or string can be formatted as escaped to make it more suitable for debugging or for logging.
The escaped string E representation of a string S is constructed by encoding a sequence of characters as follows.
The associated character encoding CE for charT (Table 12) is used to both interpret S and construct E.
  • U+0022 quotation mark (") is appended to E.
  • For each code unit sequence X in S that either encodes a single character, is a shift sequence, or is a sequence of ill-formed code units, processing is in order as follows:
    • If X encodes a single character C, then:
      • If C is one of the characters in Table 109, then the two characters shown as the corresponding escape sequence are appended to E.
      • Otherwise, if C is not U+0020 space and
        • CE is UTF-8, UTF-16, or UTF-32 and C corresponds to a Unicode scalar value whose Unicode property General_Category has a value in the groups Separator (Z) or Other (C), as described by UAX #44 of the Unicode Standard, or
        • CE is UTF-8, UTF-16, or UTF-32 and C corresponds to a Unicode scalar value with the Unicode property Grapheme_Extend=Yes as described by UAX #44 of the Unicode Standard and C is not immediately preceded in S by a character P appended to E without translation to an escape sequence, or
        • CE is neither UTF-8, UTF-16, nor UTF-32 and C is one of an implementation-defined set of separator or non-printable characters
        then the sequence \u{hex-digit-sequence} is appended to E, where hex-digit-sequence is the shortest hexadecimal representation of C using lower-case hexadecimal digits.
      • Otherwise, C is appended to E.
    • Otherwise, if X is a shift sequence, the effect on E and further decoding of S is unspecified.
      Recommended practice: A shift sequence should be represented in E such that the original code unit sequence of S can be reconstructed.
    • Otherwise (X is a sequence of ill-formed code units), each code unit U is appended to E in order as the sequence \x{hex-digit-sequence}, where hex-digit-sequence is the shortest hexadecimal representation of U using lower-case hexadecimal digits.
  • Finally, U+0022 quotation mark (") is appended to E.
Table 109 — Mapping of characters to escape sequences [tab:format.escape.sequences]
Character
Escape sequence
U+0009 character tabulation
\t
U+000a line feed
\n
U+000d carriage return
\r
U+0022 quotation mark
\"
U+005c reverse solidus
\\
The escaped string representation of a character C is equivalent to the escaped string representation of a string of C, except that:
  • the result starts and ends with U+0027 apostrophe (') instead of U+0022 quotation mark ("), and
  • if C is U+0027 apostrophe, the two characters \' are appended to E, and
  • if C is U+0022 quotation mark, then C is appended unchanged.
[Example 1: string s0 = format("[{}]", "h\tllo"); // s0 has value: [h    llo] string s1 = format("[{:?}]", "h\tllo"); // s1 has value: ["h\tllo"] string s2 = format("[{:?}]", "Спасибо, Виктор ♥!"); // s2 has value: ["Спасибо, Виктор ♥!"] string s3 = format("[{:?}, {:?}]", '\'', '"'); // s3 has value: ['\'', '"'] // The following examples assume use of the UTF-8 encoding string s4 = format("[{:?}]", string("\0 \n \t \x02 \x1b", 9)); // s4 has value: ["\u{0} \n \t \u{2} \u{1b}"] string s5 = format("[{:?}]", "\xc3\x28"); // invalid UTF-8, s5 has value: ["\x{c3}("] string s6 = format("[{:?}]", "🤷🏻‍♂️"); // s6 has value: ["🤷\u{200d}♂"] string s7 = format("[{:?}]", "\u0301"); // s7 has value: ["\u{301}"] string s8 = format("[{:?}]", "\\\u0301"); // s8 has value: ["\\\u{301}"] string s9 = format("[{:?}]", "e\u0301\u0323"); // s9 has value: ["ẹ́"] — end example]

28.5.6.6 Class template basic_format_parse_context [format.parse.ctx]

namespace std { template<class charT> class basic_format_parse_context { public: using char_type = charT; using const_iterator = typename basic_string_view<charT>::const_iterator; using iterator = const_iterator; private: iterator begin_; // exposition only iterator end_; // exposition only enum indexing { unknown, manual, automatic }; // exposition only indexing indexing_; // exposition only size_t next_arg_id_; // exposition only size_t num_args_; // exposition only public: constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt) noexcept; basic_format_parse_context(const basic_format_parse_context&) = delete; basic_format_parse_context& operator=(const basic_format_parse_context&) = delete; constexpr const_iterator begin() const noexcept; constexpr const_iterator end() const noexcept; constexpr void advance_to(const_iterator it); constexpr size_t next_arg_id(); constexpr void check_arg_id(size_t id); template<class... Ts> constexpr void check_dynamic_spec(size_t id) noexcept; constexpr void check_dynamic_spec_integral(size_t id) noexcept; constexpr void check_dynamic_spec_string(size_t id) noexcept; }; }
An instance of basic_format_parse_context holds the format string parsing state, consisting of the format string range being parsed and the argument counter for automatic indexing.
If a program declares an explicit or partial specialization of basic_format_parse_context, the program is ill-formed, no diagnostic required.
constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt) noexcept;
Effects: Initializes begin_ with fmt.begin(), end_ with fmt.end(), indexing_ with unknown, next_arg_id_ with 0, and num_args_ with 0.
[Note 1: 
Any call to next_arg_id, check_arg_id, or check_dynamic_spec on an instance of basic_format_parse_context initialized using this constructor is not a core constant expression.
— end note]
constexpr const_iterator begin() const noexcept;
Returns: begin_.
constexpr const_iterator end() const noexcept;
Returns: end_.
constexpr void advance_to(const_iterator it);
Preconditions: end() is reachable from it.
Effects: Equivalent to: begin_ = it;
constexpr size_t next_arg_id();
Effects: If indexing_ != manual is true, equivalent to: if (indexing_ == unknown) indexing_ = automatic; return next_arg_id_++;
Throws: format_error if indexing_ == manual is true.
[Note 2: 
This indicates mixing of automatic and manual argument indexing.
— end note]
Remarks: Let cur-arg-id be the value of next_arg_id_ prior to this call.
Call expressions where cur-arg-id >= num_args_ is true are not core constant expressions ([expr.const]).
constexpr void check_arg_id(size_t id);
Effects: If indexing_ != automatic is true, equivalent to: if (indexing_ == unknown) indexing_ = manual;
Throws: format_error if indexing_ == automatic is true.
[Note 3: 
This indicates mixing of automatic and manual argument indexing.
— end note]
Remarks: A call to this function is a core constant expression ([expr.const]) only if id < num_args_ is true.
template<class... Ts> constexpr void check_dynamic_spec(size_t id) noexcept;
Mandates: sizeof...(Ts)  ≥ 1.
The types in Ts... are unique.
Each type in Ts... is one of bool, char_type, int, unsigned int, long long int, unsigned long long int, float, double, long double, const char_type*, basic_string_view<char_type>, or const void*.
Remarks: A call to this function is a core constant expression only if
  • id < num_args_ is true and
  • the type of the corresponding format argument (after conversion to basic_format_arg<Context>) is one of the types in Ts....
constexpr void check_dynamic_spec_integral(size_t id) noexcept;
Effects: Equivalent to: check_dynamic_spec<int, unsigned int, long long int, unsigned long long int>(id);
constexpr void check_dynamic_spec_string(size_t id) noexcept;
Effects: Equivalent to: check_dynamic_spec<const char_type*, basic_string_view<char_type>>(id);

28.5.6.7 Class template basic_format_context [format.context]

namespace std { template<class Out, class charT> class basic_format_context { basic_format_args<basic_format_context> args_; // exposition only Out out_; // exposition only basic_format_context(const basic_format_context&) = delete; basic_format_context& operator=(const basic_format_context&) = delete; public: using iterator = Out; using char_type = charT; template<class T> using formatter_type = formatter<T, charT>; basic_format_arg<basic_format_context> arg(size_t id) const noexcept; std::locale locale(); iterator out(); void advance_to(iterator it); }; }
An instance of basic_format_context holds formatting state consisting of the formatting arguments and the output iterator.
If a program declares an explicit or partial specialization of basic_format_context, the program is ill-formed, no diagnostic required.
Out shall model output_iterator<const charT&>.
format_context is an alias for a specialization of basic_format_context with an output iterator that appends to string, such as back_insert_iterator<string>.
Similarly, wformat_context is an alias for a specialization of basic_format_context with an output iterator that appends to wstring.
Recommended practice: For a given type charT, implementations should provide a single instantiation of basic_format_context for appending to basic_string<charT>, vector<charT>, or any other container with contiguous storage by wrapping those in temporary objects with a uniform interface (such as a span<charT>) and polymorphic reallocation.
basic_format_arg<basic_format_context> arg(size_t id) const noexcept;
Returns: args_.get(id).
std::locale locale();
Returns: The locale passed to the formatting function if the latter takes one, and std​::​locale() otherwise.
iterator out();
Effects: Equivalent to: return std​::​move(out_);
void advance_to(iterator it);
Effects: Equivalent to: out_ = std​::​move(it);
[Example 1: struct S { int value; }; template<> struct std::formatter<S> { size_t width_arg_id = 0; // Parses a width argument id in the format { digit }. constexpr auto parse(format_parse_context& ctx) { auto iter = ctx.begin(); auto is_digit = [](auto c) { return c >= '0' && c <= '9'; }; auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; }; if (get_char() != '{') return iter; ++iter; char c = get_char(); if (!is_digit(c) || (++iter, get_char()) != '}') throw format_error("invalid format"); width_arg_id = c - '0'; ctx.check_arg_id(width_arg_id); return ++iter; } // Formats an S with width given by the argument width_arg_id. auto format(S s, format_context& ctx) const { int width = ctx.arg(width_arg_id).visit([](auto value) -> int { if constexpr (!is_integral_v<decltype(value)>) throw format_error("width is not integral"); else if (value < 0 || value > numeric_limits<int>::max()) throw format_error("invalid width"); else return value; }); return format_to(ctx.out(), "{0:x>{1}}", s.value, width); } }; std::string s = std::format("{0:{1}}", S{42}, 10); // value of s is "xxxxxxxx42" — end example]

28.5.7 Formatting of ranges [format.range]

28.5.7.1 Variable template format_kind [format.range.fmtkind]

template<ranges::input_range R> requires same_as<R, remove_cvref_t<R>> constexpr range_format format_kind<R> = see below;
A program that instantiates the primary template of format_kind is ill-formed.
For a type R, format_kind<R> is defined as follows:
  • If same_as<remove_cvref_t<ranges​::​range_reference_t<R>>, R> is true, format_kind<R> is range_format​::​disabled.
    [Note 1: 
    This prevents constraint recursion for ranges whose reference type is the same range type.
    For example, std​::​filesystem​::​path is a range of std​::​filesystem​::​path.
    — end note]
  • Otherwise, if the qualified-id R​::​key_type is valid and denotes a type:
    • If the qualified-id R​::​mapped_type is valid and denotes a type, let U be remove_cvref_t<ranges​::​range_reference_t<R>>.
      If either U is a specialization of pair or U is a specialization of tuple and tuple_size_v<U> == 2, format_kind<R> is range_format​::​map.
    • Otherwise, format_kind<R> is range_format​::​set.
  • Otherwise, format_kind<R> is range_format​::​sequence.
Remarks: Pursuant to [namespace.std], users may specialize format_kind for cv-unqualified program-defined types that model ranges​::​input_range.
Such specializations shall be usable in constant expressions ([expr.const]) and have type const range_format.

28.5.7.2 Class template range_formatter [format.range.formatter]

namespace std { template<class T, class charT = char> requires same_as<remove_cvref_t<T>, T> && formattable<T, charT> class range_formatter { formatter<T, charT> underlying_; // exposition only basic_string_view<charT> separator_ = STATICALLY-WIDEN<charT>(", "); // exposition only basic_string_view<charT> opening-bracket_ = STATICALLY-WIDEN<charT>("["); // exposition only basic_string_view<charT> closing-bracket_ = STATICALLY-WIDEN<charT>("]"); // exposition only public: constexpr void set_separator(basic_string_view<charT> sep) noexcept; constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept; constexpr formatter<T, charT>& underlying() noexcept { return underlying_; } constexpr const formatter<T, charT>& underlying() const noexcept { return underlying_; } template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<ranges::input_range R, class FormatContext> requires formattable<ranges::range_reference_t<R>, charT> && same_as<remove_cvref_t<ranges::range_reference_t<R>>, T> typename FormatContext::iterator format(R&& r, FormatContext& ctx) const; }; }
The class template range_formatter is a utility for implementing formatter specializations for range types.
range_formatter interprets format-spec as a range-format-spec.
The syntax of format specifications is as follows:
range-format-spec:
range-fill-and-align width n range-type range-underlying-spec
range-fill-and-align:
range-fill align
range-fill:
any character other than { or } or :
range-type:
m
s
?s
range-underlying-spec:
: format-spec
For range_formatter<T, charT>, the format-spec in a range-underlying-spec, if any, is interpreted by formatter<T, charT>.
The range-fill-and-align is interpreted the same way as a fill-and-align ([format.string.std]).
The productions align and width are described in [format.string].
The n option causes the range to be formatted without the opening and closing brackets.
[Note 1: 
This is equivalent to invoking set_brackets({}, {}).
— end note]
The range-type specifier changes the way a range is formatted, with certain options only valid with certain argument types.
The meaning of the various type options is as specified in Table 110.
Table 110 — Meaning of range-type options [tab:formatter.range.type]
Option
Requirements
Meaning
m
T shall be either a specialization of pair or a specialization of tuple such that tuple_size_v<T> is 2.
Indicates that the opening bracket should be "{", the closing bracket should be "}", the separator should be ", ", and each range element should be formatted as if m were specified for its tuple-type.
[Note 2: 
If the n option is provided in addition to the m option, both the opening and closing brackets are still empty.
— end note]
s
T shall be charT.
Indicates that the range should be formatted as a string.
?s
T shall be charT.
Indicates that the range should be formatted as an escaped string ([format.string.escaped]).
If the range-type is s or ?s, then there shall be no n option and no range-underlying-spec.
constexpr void set_separator(basic_string_view<charT> sep) noexcept;
Effects: Equivalent to: separator_ = sep;
constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept;
Effects: Equivalent to: opening-bracket_ = opening; closing-bracket_ = closing;
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Parses the format specifiers as a range-format-spec and stores the parsed specifiers in *this.
Calls underlying_.parse(ctx) to parse format-spec in range-format-spec or, if the latter is not present, an empty format-spec.
The values of opening-bracket_, closing-bracket_, and separator_ are modified if and only if required by the range-type or the n option, if present.
If:
  • the range-type is neither s nor ?s,
  • underlying_.set_debug_format() is a valid expression, and
  • there is no range-underlying-spec,
then calls underlying_.set_debug_format().
Returns: An iterator past the end of the range-format-spec.
template<ranges::input_range R, class FormatContext> requires formattable<ranges::range_reference_t<R>, charT> && same_as<remove_cvref_t<ranges::range_reference_t<R>>, T> typename FormatContext::iterator format(R&& r, FormatContext& ctx) const;
Effects: Writes the following into ctx.out(), adjusted according to the range-format-spec:
  • If the range-type was s, then as if by formatting basic_string<charT>(from_range, r).
  • Otherwise, if the range-type was ?s, then as if by formatting basic_string<charT>(from_range, r) as an escaped string ([format.string.escaped]).
  • Otherwise,
Returns: An iterator past the end of the output range.

28.5.7.3 Class template range-default-formatter [format.range.fmtdef]

namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::sequence, R, charT> { // exposition only private: using maybe-const-r = fmt-maybe-const<R, charT>; // exposition only range_formatter<remove_cvref_t<ranges::range_reference_t<maybe-const-r>>, charT> underlying_; // exposition only public: constexpr void set_separator(basic_string_view<charT> sep) noexcept; constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept; template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-r& elems, FormatContext& ctx) const; }; }
constexpr void set_separator(basic_string_view<charT> sep) noexcept;
Effects: Equivalent to: underlying_.set_separator(sep);
constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept;
Effects: Equivalent to: underlying_.set_brackets(opening, closing);
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-r& elems, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(elems, ctx);

28.5.7.4 Specialization of range-default-formatter for maps [format.range.fmtmap]

namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::map, R, charT> { private: using maybe-const-map = fmt-maybe-const<R, charT>; // exposition only using element-type = // exposition only remove_cvref_t<ranges::range_reference_t<maybe-const-map>>; range_formatter<element-type, charT> underlying_; // exposition only public: constexpr range-default-formatter(); template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-map& r, FormatContext& ctx) const; }; }
constexpr range-default-formatter();
Mandates: Either:
  • element-type is a specialization of pair, or
  • element-type is a specialization of tuple and tuple_size_v<element-type> == 2.
Effects: Equivalent to: underlying_.set_brackets(STATICALLY-WIDEN<charT>("{"), STATICALLY-WIDEN<charT>("}")); underlying_.underlying().set_brackets({}, {}); underlying_.underlying().set_separator(STATICALLY-WIDEN<charT>(": "));
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-map& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r, ctx);

28.5.7.5 Specialization of range-default-formatter for sets [format.range.fmtset]

namespace std { template<ranges::input_range R, class charT> struct range-default-formatter<range_format::set, R, charT> { private: using maybe-const-set = fmt-maybe-const<R, charT>; // exposition only range_formatter<remove_cvref_t<ranges::range_reference_t<maybe-const-set>>, charT> underlying_; // exposition only public: constexpr range-default-formatter(); template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(maybe-const-set& r, FormatContext& ctx) const; }; }
constexpr range-default-formatter();
Effects: Equivalent to: underlying_.set_brackets(STATICALLY-WIDEN<charT>("{"), STATICALLY-WIDEN<charT>("}"));
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: return underlying_.parse(ctx);
template<class FormatContext> typename FormatContext::iterator format(maybe-const-set& r, FormatContext& ctx) const;
Effects: Equivalent to: return underlying_.format(r, ctx);

28.5.7.6 Specialization of range-default-formatter for strings [format.range.fmtstr]

namespace std { template<range_format K, ranges::input_range R, class charT> requires (K == range_format::string || K == range_format::debug_string) struct range-default-formatter<K, R, charT> { private: formatter<basic_string<charT>, charT> underlying_; // exposition only public: template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(see below& str, FormatContext& ctx) const; }; }
Mandates: same_as<remove_cvref_t<range_reference_t<R>>, charT> is true.
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Equivalent to: auto i = underlying_.parse(ctx); if constexpr (K == range_format::debug_string) { underlying_.set_debug_format(); } return i;
template<class FormatContext> typename FormatContext::iterator format(see below& r, FormatContext& ctx) const;
The type of r is const R& if ranges​::​input_range<const R> is true and R& otherwise.
Effects: Let s be a basic_string<charT> such that ranges​::​equal(s, r) is true.
Equivalent to: return underlying_.format(s, ctx);

28.5.8 Arguments [format.arguments]

28.5.8.1 Class template basic_format_arg [format.arg]

namespace std { template<class Context> class basic_format_arg { public: class handle; private: using char_type = typename Context::char_type; // exposition only variant<monostate, bool, char_type, int, unsigned int, long long int, unsigned long long int, float, double, long double, const char_type*, basic_string_view<char_type>, const void*, handle> value; // exposition only template<class T> explicit basic_format_arg(T& v) noexcept; // exposition only public: basic_format_arg() noexcept; explicit operator bool() const noexcept; template<class Visitor> decltype(auto) visit(this basic_format_arg arg, Visitor&& vis); template<class R, class Visitor> R visit(this basic_format_arg arg, Visitor&& vis); }; }
An instance of basic_format_arg provides access to a formatting argument for user-defined formatters.
The behavior of a program that adds specializations of basic_format_arg is undefined.
basic_format_arg() noexcept;
Postconditions: !(*this).
template<class T> explicit basic_format_arg(T& v) noexcept;
Constraints: T satisfies formattable-with<Context>.
Preconditions: If decay_t<T> is char_type* or const char_type*, static_cast<const char_
type*>(v)
points to a NTCTS ([defns.ntcts]).
Effects: Let TD be remove_const_t<T>.
  • If TD is bool or char_type, initializes value with v;
  • otherwise, if TD is char and char_type is wchar_t, initializes value with static_cast<wchar_t>(static_cast<unsigned char>(v));
  • otherwise, if TD is a signed integer type ([basic.fundamental]) and sizeof(TD) <= sizeof(int), initializes value with static_cast<int>(v);
  • otherwise, if TD is an unsigned integer type and sizeof(TD) <= sizeof(unsigned int), initializes value with static_cast<unsigned int>(v);
  • otherwise, if TD is a signed integer type and sizeof(TD) <= sizeof(long long int), initializes value with static_cast<long long int>(v);
  • otherwise, if TD is an unsigned integer type and sizeof(TD) <= sizeof(unsigned long long int), initializes value with static_cast<unsigned long long int>(v);
  • otherwise, if TD is a standard floating-point type, initializes value with v;
  • otherwise, if TD is a specialization of basic_string_view or basic_string and TD​::​value_type is char_type, initializes value with basic_string_view<char_type>(v.data(), v.size());
  • otherwise, if decay_t<TD> is char_type* or const char_type*, initializes value with static_cast<const char_type*>(v);
  • otherwise, if is_void_v<remove_pointer_t<TD>> is true or is_null_pointer_v<TD> is true, initializes value with static_cast<const void*>(v);
  • otherwise, initializes value with handle(v).
[Note 1: 
Constructing basic_format_arg from a pointer to a member is ill-formed unless the user provides an enabled specialization of formatter for that pointer to member type.
— end note]
explicit operator bool() const noexcept;
Returns: !holds_alternative<monostate>(value).
template<class Visitor> decltype(auto) visit(this basic_format_arg arg, Visitor&& vis);
Effects: Equivalent to: return arg.value.visit(std​::​forward<Visitor>(vis));
template<class R, class Visitor> R visit(this basic_format_arg arg, Visitor&& vis);
Effects: Equivalent to: return arg.value.visit<R>(std​::​forward<Visitor>(vis));
The class handle allows formatting an object of a user-defined type.
namespace std { template<class Context> class basic_format_arg<Context>::handle { const void* ptr_; // exposition only void (*format_)(basic_format_parse_context<char_type>&, Context&, const void*); // exposition only template<class T> explicit handle(T& val) noexcept; // exposition only public: void format(basic_format_parse_context<char_type>&, Context& ctx) const; }; }
template<class T> explicit handle(T& val) noexcept;
Let
Mandates: TQ satisfies formattable-with<Context>.
Effects: Initializes ptr_ with addressof(val) and format_ with [](basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx, const void* ptr) { typename Context::template formatter_type<TD> f; parse_ctx.advance_to(f.parse(parse_ctx)); format_ctx.advance_to(f.format(*const_cast<TQ*>(static_cast<const TD*>(ptr)), format_ctx)); }
void format(basic_format_parse_context<char_type>& parse_ctx, Context& format_ctx) const;
Effects: Equivalent to: format_(parse_ctx, format_ctx, ptr_);

28.5.8.2 Class template format-arg-store [format.arg.store]

namespace std { template<class Context, class... Args> class format-arg-store { // exposition only array<basic_format_arg<Context>, sizeof...(Args)> args; // exposition only }; }
An instance of format-arg-store stores formatting arguments.
template<class Context = format_context, class... Args> format-arg-store<Context, Args...> make_format_args(Args&... fmt_args);
Preconditions: The type typename Context​::​template formatter_type<remove_const_t<>>
meets the BasicFormatter requirements ([formatter.requirements]) for each in Args.
Returns: An object of type format-arg-store<Context, Args...> whose args data member is initialized with {basic_format_arg<Context>(fmt_args)...}.
template<class... Args> format-arg-store<wformat_context, Args...> make_wformat_args(Args&... args);
Effects: Equivalent to: return make_format_args<wformat_context>(args...);

28.5.8.3 Class template basic_format_args [format.args]

namespace std { template<class Context> class basic_format_args { size_t size_; // exposition only const basic_format_arg<Context>* data_; // exposition only public: template<class... Args> basic_format_args(const format-arg-store<Context, Args...>& store) noexcept; basic_format_arg<Context> get(size_t i) const noexcept; }; template<class Context, class... Args> basic_format_args(format-arg-store<Context, Args...>) -> basic_format_args<Context>; }
An instance of basic_format_args provides access to formatting arguments.
Implementations should optimize the representation of basic_format_args for a small number of formatting arguments.
[Note 1: 
For example, by storing indices of type alternatives separately from values and packing the former.
— end note]
template<class... Args> basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
Effects: Initializes size_ with sizeof...(Args) and data_ with store.args.data().
basic_format_arg<Context> get(size_t i) const noexcept;
Returns: i < size_ ? data_[i] : basic_format_arg<Context>().

28.5.9 Tuple formatter [format.tuple]

For each of pair and tuple, the library provides the following formatter specialization where pair-or-tuple is the name of the template:
namespace std { template<class charT, formattable<charT>... Ts> struct formatter<pair-or-tuple<Ts...>, charT> { private: tuple<formatter<remove_cvref_t<Ts>, charT>...> underlying_; // exposition only basic_string_view<charT> separator_ = STATICALLY-WIDEN<charT>(", "); // exposition only basic_string_view<charT> opening-bracket_ = STATICALLY-WIDEN<charT>("("); // exposition only basic_string_view<charT> closing-bracket_ = STATICALLY-WIDEN<charT>(")"); // exposition only public: constexpr void set_separator(basic_string_view<charT> sep) noexcept; constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept; template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx); template<class FormatContext> typename FormatContext::iterator format(see below& elems, FormatContext& ctx) const; }; template<class... Ts> constexpr bool enable_nonlocking_formatter_optimization<pair-or-tuple<Ts...>> = (enable_nonlocking_formatter_optimization<Ts> && ...); }
The parse member functions of these formatters interpret the format specification as a tuple-format-spec according to the following syntax:
tuple-format-spec:
tuple-fill-and-align width tuple-type
tuple-fill-and-align:
tuple-fill align
tuple-fill:
any character other than { or } or :
tuple-type:
m
n
The tuple-fill-and-align is interpreted the same way as a fill-and-align ([format.string.std]).
The productions align and width are described in [format.string].
The tuple-type specifier changes the way a pair or tuple is formatted, with certain options only valid with certain argument types.
The meaning of the various type options is as specified in Table 111.
Table 111 — Meaning of tuple-type options [tab:formatter.tuple.type]
Option
Requirements
Meaning
m
sizeof...(Ts) == 2
Equivalent to: set_separator(STATICALLY-WIDEN<charT>(": ")); set_brackets({}, {});
n
none
Equivalent to: set_brackets({}, {});
none
none
No effects
constexpr void set_separator(basic_string_view<charT> sep) noexcept;
Effects: Equivalent to: separator_ = sep;
constexpr void set_brackets(basic_string_view<charT> opening, basic_string_view<charT> closing) noexcept;
Effects: Equivalent to: opening-bracket_ = opening; closing-bracket_ = closing;
template<class ParseContext> constexpr typename ParseContext::iterator parse(ParseContext& ctx);
Effects: Parses the format specifiers as a tuple-format-spec and stores the parsed specifiers in *this.
The values of opening-bracket_, closing-bracket_, and separator_ are modified if and only if required by the tuple-type, if present.
For each element e in underlying_, calls e.parse(ctx) to parse an empty format-spec and, if e.set_debug_format() is a valid expression, calls e.set_debug_format().
Returns: An iterator past the end of the tuple-format-spec.
template<class FormatContext> typename FormatContext::iterator format(see below& elems, FormatContext& ctx) const;
The type of elems is:
  • If (formattable<const Ts, charT> && ...) is true, const pair-or-tuple<Ts...>&.
  • Otherwise pair-or-tuple<Ts...>&.
Effects: Writes the following into ctx.out(), adjusted according to the tuple-format-spec:
  • opening-bracket_,
  • for each index I in the [0, sizeof...(Ts)):
    • if I != 0, separator_,
    • the result of writing get<I>(elems) via get<I>(underlying_), and
  • closing-bracket_.
Returns: An iterator past the end of the output range.

28.5.10 Class format_error [format.error]

namespace std { class format_error : public runtime_error { public: explicit format_error(const string& what_arg); explicit format_error(const char* what_arg); }; }
The class format_error defines the type of objects thrown as exceptions to report errors from the formatting library.
format_error(const string& what_arg);
Postconditions: strcmp(what(), what_arg.c_str()) == 0.
format_error(const char* what_arg);
Postconditions: strcmp(what(), what_arg) == 0.

28.6 Regular expressions library [re]

28.6.1 General [re.general]

Subclause [re] describes components that C++ programs may use to perform operations involving regular expression matching and searching.
The following subclauses describe a basic regular expression class template and its traits that can handle char-like ([strings.general]) template arguments, two specializations of this class template that handle sequences of char and wchar_t, a class template that holds the result of a regular expression match, a series of algorithms that allow a character sequence to be operated upon by a regular expression, and two iterator types for enumerating regular expression matches, as summarized in Table 112.
Table 112 — Regular expressions library summary [tab:re.summary]
Subclause
Header
Requirements
Constants
<regex>
Exception type
Traits
Regular expression template
Submatches
Match results
Algorithms
Iterators
Grammar
The ECMAScript Language Specification described in Standard Ecma-262 is called ECMA-262 in this Clause.

28.6.2 Requirements [re.req]

This subclause defines requirements on classes representing regular expression traits.
[Note 1: 
The class template regex_traits, defined in [re.traits], meets these requirements.
— end note]
The class template basic_regex, defined in [re.regex], needs a set of related types and functions to complete the definition of its semantics.
These types and functions are provided as a set of member typedef-names and functions in the template parameter traits used by the basic_regex class template.
This subclause defines the semantics of these members.
To specialize class template basic_regex for a character container CharT and its related regular expression traits class Traits, use basic_regex<CharT, Traits>.
In the following requirements,
  • X denotes a traits class defining types and functions for the character container type charT;
  • u is an object of type X;
  • v is an object of type const X;
  • p is a value of type const charT*;
  • I1 and I2 are input iterators ([input.iterators]);
  • F1 and F2 are forward iterators ([forward.iterators]);
  • c is a value of type const charT;
  • s is an object of type X​::​string_type;
  • cs is an object of type const X​::​string_type;
  • b is a value of type bool;
  • I is a value of type int;
  • cl is an object of type X​::​char_class_type; and
  • loc is an object of type X​::​locale_type.
A traits class X meets the regular expression traits requirements if the following types and expressions are well-formed and have the specified semantics.
typename X::char_type
Result: charT, the character container type used in the implementation of class template basic_regex.
typename X::string_type
Result: basic_string<charT>
typename X::locale_type
Result: A copy constructible type that represents the locale used by the traits class.
typename X::char_class_type
Result: A bitmask type ([bitmask.types]) representing a particular character classification.
X::length(p)
Result: size_t
Returns: The smallest i such that p[i] == 0.
Complexity: Linear in i.
v.translate(c)
Result: X​::​char_type
Returns: A character such that for any character d that is to be considered equivalent to c then v.translate(c) == v.translate(d).
v.translate_nocase(c)
Result: X​::​char_type
Returns: For all characters C that are to be considered equivalent to c when comparisons are to be performed without regard to case, then v.translate_nocase(c) == v.translate_nocase(C).
v.transform(F1, F2)
Result: X​::​string_type
Returns: A sort key for the character sequence designated by the iterator range [F1, F2) such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2) then v.transform(G1, G2) < v.transform(H1, H2).
v.transform_primary(F1, F2)
Result: X​::​string_type
Returns: A sort key for the character sequence designated by the iterator range [F1, F2) such that if the character sequence [G1, G2) sorts before the character sequence [H1, H2) when character case is not considered then v.transform_primary(G1, G2) < v.transform_primary(H1, H2).
v.lookup_collatename(F1, F2)
Result: X​::​string_type
Returns: A sequence of characters that represents the collating element consisting of the character sequence designated by the iterator range [F1, F2).
Returns an empty string if the character sequence is not a valid collating element.
v.lookup_classname(F1, F2, b)
Result: X​::​char_class_type
Returns: Converts the character sequence designated by the iterator range [F1, F2) into a value of a bitmask type that can subsequently be passed to isctype.
Values returned from lookup_classname can be bitwise or'ed together; the resulting value represents membership in either of the corresponding character classes.
If b is true, the returned bitmask is suitable for matching characters without regard to their case.
Returns 0 if the character sequence is not the name of a character class recognized by X.
The value returned shall be independent of the case of the characters in the sequence.
v.isctype(c, cl)
Result: bool
Returns: Returns true if character c is a member of one of the character classes designated by cl, false otherwise.
v.value(c, I)
Result: int
Returns: Returns the value represented by the digit c in base I if the character c is a valid digit in base I; otherwise returns -1.
[Note 2: 
The value of I will only be 8, 10, or 16.
— end note]
u.imbue(loc)
Result: X​::​locale_type
Effects: Imbues u with the locale loc and returns the previous locale used by u if any.
v.getloc()
Result: X​::​locale_type
Returns: Returns the current locale used by v, if any.
[Note 3: 
Class template regex_traits meets the requirements for a regular expression traits class when it is specialized for char or wchar_t.
This class template is described in the header <regex>, and is described in [re.traits].
— end note]

28.6.3 Header <regex> synopsis [re.syn]

#include <compare> // see [compare.syn] #include <initializer_list> // see [initializer.list.syn] namespace std { // [re.const], regex constants namespace regex_constants { using syntax_option_type = T1; using match_flag_type = T2; using error_type = T3; } // [re.badexp], class regex_error class regex_error; // [re.traits], class template regex_traits template<class charT> struct regex_traits; // [re.regex], class template basic_regex template<class charT, class traits = regex_traits<charT>> class basic_regex; using regex = basic_regex<char>; using wregex = basic_regex<wchar_t>; // [re.regex.swap], basic_regex swap template<class charT, class traits> void swap(basic_regex<charT, traits>& e1, basic_regex<charT, traits>& e2); // [re.submatch], class template sub_match template<class BidirectionalIterator> class sub_match; using csub_match = sub_match<const char*>; using wcsub_match = sub_match<const wchar_t*>; using ssub_match = sub_match<string::const_iterator>; using wssub_match = sub_match<wstring::const_iterator>; // [re.submatch.op], sub_match non-member operators template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); template<class BiIter, class ST, class SA> bool operator==( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); template<class BiIter, class ST, class SA> auto operator<=>( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs); template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs); template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs); template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs); template<class charT, class ST, class BiIter> basic_ostream<charT, ST>& operator<<(basic_ostream<charT, ST>& os, const sub_match<BiIter>& m); // [re.results], class template match_results template<class BidirectionalIterator, class Allocator = allocator<sub_match<BidirectionalIterator>>> class match_results; using cmatch = match_results<const char*>; using wcmatch = match_results<const wchar_t*>; using smatch = match_results<string::const_iterator>; using wsmatch = match_results<wstring::const_iterator>; // match_results comparisons template<class BidirectionalIterator, class Allocator> bool operator==(const match_results<BidirectionalIterator, Allocator>& m1, const match_results<BidirectionalIterator, Allocator>& m2); // [re.results.swap], match_results swap template<class BidirectionalIterator, class Allocator> void swap(match_results<BidirectionalIterator, Allocator>& m1, match_results<BidirectionalIterator, Allocator>& m2); // [re.alg.match], function template regex_match template<class BidirectionalIterator, class Allocator, class charT, class traits> bool regex_match(BidirectionalIterator first, BidirectionalIterator last, match_results<BidirectionalIterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class BidirectionalIterator, class charT, class traits> bool regex_match(BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class charT, class Allocator, class traits> bool regex_match(const charT* str, match_results<const charT*, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class Allocator, class charT, class traits> bool regex_match(const basic_string<charT, ST, SA>& s, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class Allocator, class charT, class traits> bool regex_match(const basic_string<charT, ST, SA>&&, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>&, const basic_regex<charT, traits>&, regex_constants::match_flag_type = regex_constants::match_default) = delete; template<class charT, class traits> bool regex_match(const charT* str, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class charT, class traits> bool regex_match(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); // [re.alg.search], function template regex_search template<class BidirectionalIterator, class Allocator, class charT, class traits> bool regex_search(BidirectionalIterator first, BidirectionalIterator last, match_results<BidirectionalIterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class BidirectionalIterator, class charT, class traits> bool regex_search(BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class charT, class Allocator, class traits> bool regex_search(const charT* str, match_results<const charT*, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class charT, class traits> bool regex_search(const charT* str, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class charT, class traits> bool regex_search(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class Allocator, class charT, class traits> bool regex_search(const basic_string<charT, ST, SA>& s, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default); template<class ST, class SA, class Allocator, class charT, class traits> bool regex_search(const basic_string<charT, ST, SA>&&, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>&, const basic_regex<charT, traits>&, regex_constants::match_flag_type = regex_constants::match_default) = delete; // [re.alg.replace], function template regex_replace template<class OutputIterator, class BidirectionalIterator, class traits, class charT, class ST, class SA> OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, const basic_string<charT, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class OutputIterator, class BidirectionalIterator, class traits, class charT> OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT, class ST, class SA, class FST, class FSA> basic_string<charT, ST, SA> regex_replace(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, const basic_string<charT, FST, FSA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT, class ST, class SA> basic_string<charT, ST, SA> regex_replace(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT, class ST, class SA> basic_string<charT> regex_replace(const charT* s, const basic_regex<charT, traits>& e, const basic_string<charT, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT> basic_string<charT> regex_replace(const charT* s, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default); // [re.regiter], class template regex_iterator template<class BidirectionalIterator, class charT = typename iterator_traits<BidirectionalIterator>::value_type, class traits = regex_traits<charT>> class regex_iterator; using cregex_iterator = regex_iterator<const char*>; using wcregex_iterator = regex_iterator<const wchar_t*>; using sregex_iterator = regex_iterator<string::const_iterator>; using wsregex_iterator = regex_iterator<wstring::const_iterator>; // [re.tokiter], class template regex_token_iterator template<class BidirectionalIterator, class charT = typename iterator_traits<BidirectionalIterator>::value_type, class traits = regex_traits<charT>> class regex_token_iterator; using cregex_token_iterator = regex_token_iterator<const char*>; using wcregex_token_iterator = regex_token_iterator<const wchar_t*>; using sregex_token_iterator = regex_token_iterator<string::const_iterator>; using wsregex_token_iterator = regex_token_iterator<wstring::const_iterator>; namespace pmr { template<class BidirectionalIterator> using match_results = std::match_results<BidirectionalIterator, polymorphic_allocator<sub_match<BidirectionalIterator>>>; using cmatch = match_results<const char*>; using wcmatch = match_results<const wchar_t*>; using smatch = match_results<string::const_iterator>; using wsmatch = match_results<wstring::const_iterator>; } }

28.6.4 Namespace std​::​regex_constants [re.const]

28.6.4.1 General [re.const.general]

The namespace std​::​regex_constants holds symbolic constants used by the regular expression library.
This namespace provides three types, syntax_option_type, match_flag_type, and error_type, along with several constants of these types.

28.6.4.2 Bitmask type syntax_option_type [re.synopt]

namespace std::regex_constants { using syntax_option_type = T1; inline constexpr syntax_option_type icase = unspecified; inline constexpr syntax_option_type nosubs = unspecified; inline constexpr syntax_option_type optimize = unspecified; inline constexpr syntax_option_type collate = unspecified; inline constexpr syntax_option_type ECMAScript = unspecified; inline constexpr syntax_option_type basic = unspecified; inline constexpr syntax_option_type extended = unspecified; inline constexpr syntax_option_type awk = unspecified; inline constexpr syntax_option_type grep = unspecified; inline constexpr syntax_option_type egrep = unspecified; inline constexpr syntax_option_type multiline = unspecified; }
The type syntax_option_type is an implementation-defined bitmask type ([bitmask.types]).
Setting its elements has the effects listed in Table 113.
A valid value of type syntax_option_type shall have at most one of the grammar elements ECMAScript, basic, extended, awk, grep, egrep, set.
If no grammar element is set, the default grammar is ECMAScript.
Table 113syntax_option_type effects [tab:re.synopt]
Element
Effect(s) if set
icase
Specifies that matching of regular expressions against a character container sequence shall be performed without regard to case.
nosubs
Specifies that no sub-expressions shall be considered to be marked, so that when a regular expression is matched against a character container sequence, no sub-expression matches shall be stored in the supplied match_results object.
optimize
Specifies that the regular expression engine should pay more attention to the speed with which regular expressions are matched, and less to the speed with which regular expression objects are constructed.
Otherwise it has no detectable effect on the program output.
collate
Specifies that character ranges of the form "[a-b]" shall be locale sensitive.
ECMAScript
Specifies that the grammar recognized by the regular expression engine shall be that used by ECMAScript in ECMA-262, as modified in [re.grammar].

See also: ECMA-262 15.10
basic
Specifies that the grammar recognized by the regular expression engine shall be that used by basic regular expressions in POSIX.
See also: POSIX, Base Definitions and Headers, Section 9.3
extended
Specifies that the grammar recognized by the regular expression engine shall be that used by extended regular expressions in POSIX.
See also: POSIX, Base Definitions and Headers, Section 9.4
awk
Specifies that the grammar recognized by the regular expression engine shall be that used by the utility awk in POSIX.
grep
Specifies that the grammar recognized by the regular expression engine shall be that used by the utility grep in POSIX.
egrep
Specifies that the grammar recognized by the regular expression engine shall be that used by the utility grep when given the -E option in POSIX.
multiline
Specifies that ^ shall match the beginning of a line and $ shall match the end of a line, if the ECMAScript engine is selected.

28.6.4.3 Bitmask type match_flag_type [re.matchflag]

namespace std::regex_constants { using match_flag_type = T2; inline constexpr match_flag_type match_default = {}; inline constexpr match_flag_type match_not_bol = unspecified; inline constexpr match_flag_type match_not_eol = unspecified; inline constexpr match_flag_type match_not_bow = unspecified; inline constexpr match_flag_type match_not_eow = unspecified; inline constexpr match_flag_type match_any = unspecified; inline constexpr match_flag_type match_not_null = unspecified; inline constexpr match_flag_type match_continuous = unspecified; inline constexpr match_flag_type match_prev_avail = unspecified; inline constexpr match_flag_type format_default = {}; inline constexpr match_flag_type format_sed = unspecified; inline constexpr match_flag_type format_no_copy = unspecified; inline constexpr match_flag_type format_first_only = unspecified; }
The type match_flag_type is an implementation-defined bitmask type ([bitmask.types]).
The constants of that type, except for match_default and format_default, are bitmask elements.
The match_default and format_default constants are empty bitmasks.
Matching a regular expression against a sequence of characters [first, last) proceeds according to the rules of the grammar specified for the regular expression object, modified according to the effects listed in Table 114 for any bitmask elements set.
Table 114regex_constants​::​match_flag_type effects [tab:re.matchflag]
Element
Effect(s) if set
match_not_bol
The first character in the sequence [first, last) shall be treated as though it is not at the beginning of a line, so the character ^ in the regular expression shall not match [first, first).
match_not_eol
The last character in the sequence [first, last) shall be treated as though it is not at the end of a line, so the character "$" in the regular expression shall not match [last, last).
match_not_bow
The expression "\\b" shall not match the sub-sequence [first, first).
match_not_eow
The expression "\\b" shall not match the sub-sequence [last, last).
match_any
If more than one match is possible then any match is an acceptable result.
match_not_null
The expression shall not match an empty sequence.
match_continuous
The expression shall only match a sub-sequence that begins at first.
match_prev_avail
--first is a valid iterator position.
When this flag is set the flags match_not_bol and match_not_bow shall be ignored by the regular expression algorithms ([re.alg]) and iterators ([re.iter]).
format_default
When a regular expression match is to be replaced by a new string, the new string shall be constructed using the rules used by the ECMAScript replace function in ECMA-262, part 15.5.4.11 String.prototype.replace.
In addition, during search and replace operations all non-overlapping occurrences of the regular expression shall be located and replaced, and sections of the input that did not match the expression shall be copied unchanged to the output string.
format_sed
When a regular expression match is to be replaced by a new string, the new string shall be constructed using the rules used by the sed utility in POSIX.
format_no_copy
During a search and replace operation, sections of the character container sequence being searched that do not match the regular expression shall not be copied to the output string.
format_first_only
When specified during a search and replace operation, only the first occurrence of the regular expression shall be replaced.

28.6.4.4 Implementation-defined error_type [re.err]

namespace std::regex_constants { using error_type = T3; inline constexpr error_type error_collate = unspecified; inline constexpr error_type error_ctype = unspecified; inline constexpr error_type error_escape = unspecified; inline constexpr error_type error_backref = unspecified; inline constexpr error_type error_brack = unspecified; inline constexpr error_type error_paren = unspecified; inline constexpr error_type error_brace = unspecified; inline constexpr error_type error_badbrace = unspecified; inline constexpr error_type error_range = unspecified; inline constexpr error_type error_space = unspecified; inline constexpr error_type error_badrepeat = unspecified; inline constexpr error_type error_complexity = unspecified; inline constexpr error_type error_stack = unspecified; }
The type error_type is an implementation-defined enumerated type ([enumerated.types]).
Values of type error_type represent the error conditions described in Table 115:
Table 115error_type values in the C locale [tab:re.err]
Value
Error condition
error_collate
The expression contains an invalid collating element name.
error_ctype
The expression contains an invalid character class name.
error_escape
The expression contains an invalid escaped character, or a trailing escape.
error_backref
The expression contains an invalid back reference.
error_brack
The expression contains mismatched [ and ].
error_paren
The expression contains mismatched ( and ).
error_brace
The expression contains mismatched { and }
error_badbrace
The expression contains an invalid range in a {} expression.
error_range
The expression contains an invalid character range, such as [b-a] in most encodings.
error_space
There is insufficient memory to convert the expression into a finite state machine.
error_badrepeat
One of *?+{ is not preceded by a valid regular expression.
error_complexity
The complexity of an attempted match against a regular expression exceeds a pre-set level.
error_stack
There is insufficient memory to determine whether the regular expression matches the specified character sequence.

28.6.5 Class regex_error [re.badexp]

namespace std { class regex_error : public runtime_error { public: explicit regex_error(regex_constants::error_type ecode); regex_constants::error_type code() const; }; }
The class regex_error defines the type of objects thrown as exceptions to report errors from the regular expression library.
regex_error(regex_constants::error_type ecode);
Postconditions: ecode == code().
regex_constants::error_type code() const;
Returns: The error code that was passed to the constructor.

28.6.6 Class template regex_traits [re.traits]

namespace std { template<class charT> struct regex_traits { using char_type = charT; using string_type = basic_string<char_type>; using locale_type = locale; using char_class_type = bitmask_type; regex_traits(); static size_t length(const char_type* p); charT translate(charT c) const; charT translate_nocase(charT c) const; template<class ForwardIterator> string_type transform(ForwardIterator first, ForwardIterator last) const; template<class ForwardIterator> string_type transform_primary( ForwardIterator first, ForwardIterator last) const; template<class ForwardIterator> string_type lookup_collatename( ForwardIterator first, ForwardIterator last) const; template<class ForwardIterator> char_class_type lookup_classname( ForwardIterator first, ForwardIterator last, bool icase = false) const; bool isctype(charT c, char_class_type f) const; int value(charT ch, int radix) const; locale_type imbue(locale_type l); locale_type getloc() const; }; }
The specializations regex_traits<char> and regex_traits<wchar_t> meet the requirements for a regular expression traits class ([re.req]).
using char_class_type = bitmask_type;
The type char_class_type is used to represent a character classification and is capable of holding an implementation specific set returned by lookup_classname.
static size_t length(const char_type* p);
Returns: char_traits<charT>​::​length(p).
charT translate(charT c) const;
Returns: c.
charT translate_nocase(charT c) const;
Returns: use_facet<ctype<charT>>(getloc()).tolower(c).
template<class ForwardIterator> string_type transform(ForwardIterator first, ForwardIterator last) const;
Effects: As if by: string_type str(first, last); return use_facet<collate<charT>>( getloc()).transform(str.data(), str.data() + str.length());
template<class ForwardIterator> string_type transform_primary(ForwardIterator first, ForwardIterator last) const;
Effects: If typeid(use_facet<collate<charT>>) == typeid(collate_byname<charT>) and the form of the sort key returned by collate_byname<charT>​::​transform(first, last) is known and can be converted into a primary sort key then returns that key, otherwise returns an empty string.
template<class ForwardIterator> string_type lookup_collatename(ForwardIterator first, ForwardIterator last) const;
Returns: A sequence of one or more characters that represents the collating element consisting of the character sequence designated by the iterator range [first, last).
Returns an empty string if the character sequence is not a valid collating element.
template<class ForwardIterator> char_class_type lookup_classname( ForwardIterator first, ForwardIterator last, bool icase = false) const;
Returns: An unspecified value that represents the character classification named by the character sequence designated by the iterator range [first, last).
If the parameter icase is true then the returned mask identifies the character classification without regard to the case of the characters being matched, otherwise it does honor the case of the characters being matched.242
The value returned shall be independent of the case of the characters in the character sequence.
If the name is not recognized then returns char_class_type().
Remarks: For regex_traits<char>, at least the narrow character names in Table 116 shall be recognized.
For regex_traits<wchar_t>, at least the wide character names in Table 116 shall be recognized.
bool isctype(charT c, char_class_type f) const;
Effects: Determines if the character c is a member of the character classification represented by f.
Returns: Given the following function declaration: // for exposition only template<class C> ctype_base::mask convert(typename regex_traits<C>::char_class_type f); that returns a value in which each ctype_base​::​mask value corresponding to a value in f named in Table 116 is set, then the result is determined as if by: ctype_base::mask m = convert<charT>(f); const ctype<charT>& ct = use_facet<ctype<charT>>(getloc()); if (ct.is(m, c)) { return true; } else if (c == ct.widen('_')) { charT w[1] = { ct.widen('w') }; char_class_type x = lookup_classname(w, w+1); return (f&x) == x; } else { return false; }
[Example 1: regex_traits<char> t; string d("d"); string u("upper"); regex_traits<char>::char_class_type f; f = t.lookup_classname(d.begin(), d.end()); f |= t.lookup_classname(u.begin(), u.end()); ctype_base::mask m = convert<char>(f); // m == ctype_base​::​digit|ctype_base​::​upper — end example]
[Example 2: regex_traits<char> t; string w("w"); regex_traits<char>::char_class_type f; f = t.lookup_classname(w.begin(), w.end()); t.isctype('A', f); // returns true t.isctype('_', f); // returns true t.isctype(' ', f); // returns false — end example]
int value(charT ch, int radix) const;
Preconditions: The value of radix is 8, 10, or 16.
Returns: The value represented by the digit ch in base radix if the character ch is a valid digit in base radix; otherwise returns -1.
locale_type imbue(locale_type loc);
Effects: Imbues *this with a copy of the locale loc.
[Note 1: 
Calling imbue with a different locale than the one currently in use invalidates all cached data held by *this.
— end note]
Postconditions: getloc() == loc.
Returns: If no locale has been previously imbued then a copy of the global locale in effect at the time of construction of *this, otherwise a copy of the last argument passed to imbue.
locale_type getloc() const;
Returns: If no locale has been imbued then a copy of the global locale in effect at the time of construction of *this, otherwise a copy of the last argument passed to imbue.
Table 116 — Character class names and corresponding ctype masks [tab:re.traits.classnames]
Narrow character name
Wide character name
Corresponding ctype_base​::​mask value
"alnum"
L"alnum"
ctype_base​::​alnum
"alpha"
L"alpha"
ctype_base​::​alpha
"blank"
L"blank"
ctype_base​::​blank
"cntrl"
L"cntrl"
ctype_base​::​cntrl
"digit"
L"digit"
ctype_base​::​digit
"d"
L"d"
ctype_base​::​digit
"graph"
L"graph"
ctype_base​::​graph
"lower"
L"lower"
ctype_base​::​lower
"print"
L"print"
ctype_base​::​print
"punct"
L"punct"
ctype_base​::​punct
"space"
L"space"
ctype_base​::​space
"s"
L"s"
ctype_base​::​space
"upper"
L"upper"
ctype_base​::​upper
"w"
L"w"
ctype_base​::​alnum
"xdigit"
L"xdigit"
ctype_base​::​xdigit
242)242)
For example, if the parameter icase is true then [[:lower:]] is the same as [[:alpha:]].

28.6.7 Class template basic_regex [re.regex]

28.6.7.1 General [re.regex.general]

For a char-like type charT, specializations of class template basic_regex represent regular expressions constructed from character sequences of charT characters.
In the rest of [re.regex], charT denotes a given char-like type.
Storage for a regular expression is allocated and freed as necessary by the member functions of class basic_regex.
Objects of type specialization of basic_regex are responsible for converting the sequence of charT objects to an internal representation.
It is not specified what form this representation takes, nor how it is accessed by algorithms that operate on regular expressions.
[Note 1: 
Implementations will typically declare some function templates as friends of basic_regex to achieve this.
— end note]
The functions described in [re.regex] report errors by throwing exceptions of type regex_error.
namespace std { template<class charT, class traits = regex_traits<charT>> class basic_regex { public: // types using value_type = charT; using traits_type = traits; using string_type = typename traits::string_type; using flag_type = regex_constants::syntax_option_type; using locale_type = typename traits::locale_type; // [re.synopt], constants static constexpr flag_type icase = regex_constants::icase; static constexpr flag_type nosubs = regex_constants::nosubs; static constexpr flag_type optimize = regex_constants::optimize; static constexpr flag_type collate = regex_constants::collate; static constexpr flag_type ECMAScript = regex_constants::ECMAScript; static constexpr flag_type basic = regex_constants::basic; static constexpr flag_type extended = regex_constants::extended; static constexpr flag_type awk = regex_constants::awk; static constexpr flag_type grep = regex_constants::grep; static constexpr flag_type egrep = regex_constants::egrep; static constexpr flag_type multiline = regex_constants::multiline; // [re.regex.construct], construct/copy/destroy basic_regex(); explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript); basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); basic_regex(const basic_regex&); basic_regex(basic_regex&&) noexcept; template<class ST, class SA> explicit basic_regex(const basic_string<charT, ST, SA>& s, flag_type f = regex_constants::ECMAScript); template<class ForwardIterator> basic_regex(ForwardIterator first, ForwardIterator last, flag_type f = regex_constants::ECMAScript); basic_regex(initializer_list<charT> il, flag_type f = regex_constants::ECMAScript); ~basic_regex(); // [re.regex.assign], assign basic_regex& operator=(const basic_regex& e); basic_regex& operator=(basic_regex&& e) noexcept; basic_regex& operator=(const charT* p); basic_regex& operator=(initializer_list<charT> il); template<class ST, class SA> basic_regex& operator=(const basic_string<charT, ST, SA>& s); basic_regex& assign(const basic_regex& e); basic_regex& assign(basic_regex&& e) noexcept; basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript); basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript); template<class ST, class SA> basic_regex& assign(const basic_string<charT, ST, SA>& s, flag_type f = regex_constants::ECMAScript); template<class InputIterator> basic_regex& assign(InputIterator first, InputIterator last, flag_type f = regex_constants::ECMAScript); basic_regex& assign(initializer_list<charT>, flag_type f = regex_constants::ECMAScript); // [re.regex.operations], const operations unsigned mark_count() const; flag_type flags() const; // [re.regex.locale], locale locale_type imbue(locale_type loc); locale_type getloc() const; // [re.regex.swap], swap void swap(basic_regex&); }; template<class ForwardIterator> basic_regex(ForwardIterator, ForwardIterator, regex_constants::syntax_option_type = regex_constants::ECMAScript) -> basic_regex<typename iterator_traits<ForwardIterator>::value_type>; }

28.6.7.2 Constructors [re.regex.construct]

basic_regex();
Postconditions: *this does not match any character sequence.
explicit basic_regex(const charT* p, flag_type f = regex_constants::ECMAScript);
Preconditions: [p, p + char_traits<charT>​::​length(p)) is a valid range.
Effects: The object's internal finite state machine is constructed from the regular expression contained in the sequence of characters [p, p + char_traits<charT>​::​​length(p)), and interpreted according to the flags f.
Postconditions: flags() returns f.
mark_count() returns the number of marked sub-expressions within the expression.
Throws: regex_error if [p, p + char_traits<charT>​::​length(p)) is not a valid regular expression.
basic_regex(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript);
Preconditions: [p, p + len) is a valid range.
Effects: The object's internal finite state machine is constructed from the regular expression contained in the sequence of characters [p, p + len), and interpreted according the flags specified in f.
Postconditions: flags() returns f.
mark_count() returns the number of marked sub-expressions within the expression.
Throws: regex_error if [p, p + len) is not a valid regular expression.
basic_regex(const basic_regex& e);
Postconditions: flags() and mark_count() return e.flags() and e.mark_count(), respectively.
basic_regex(basic_regex&& e) noexcept;
Postconditions: flags() and mark_count() return the values that e.flags() and e.mark_count(), respectively, had before construction.
template<class ST, class SA> explicit basic_regex(const basic_string<charT, ST, SA>& s, flag_type f = regex_constants::ECMAScript);
Effects: The object's internal finite state machine is constructed from the regular expression contained in the string s, and interpreted according to the flags specified in f.
Postconditions: flags() returns f.
mark_count() returns the number of marked sub-expressions within the expression.
Throws: regex_error if s is not a valid regular expression.
template<class ForwardIterator> basic_regex(ForwardIterator first, ForwardIterator last, flag_type f = regex_constants::ECMAScript);
Effects: The object's internal finite state machine is constructed from the regular expression contained in the sequence of characters [first, last), and interpreted according to the flags specified in f.
Postconditions: flags() returns f.
mark_count() returns the number of marked sub-expressions within the expression.
Throws: regex_error if the sequence [first, last) is not a valid regular expression.
basic_regex(initializer_list<charT> il, flag_type f = regex_constants::ECMAScript);
Effects: Same as basic_regex(il.begin(), il.end(), f).

28.6.7.3 Assignment [re.regex.assign]

basic_regex& operator=(const basic_regex& e);
Postconditions: flags() and mark_count() return e.flags() and e.mark_count(), respectively.
basic_regex& operator=(basic_regex&& e) noexcept;
Postconditions: flags() and mark_count() return the values that e.flags() and e.mark_count(), respectively, had before assignment.
e is in a valid state with unspecified value.
basic_regex& operator=(const charT* p);
Effects: Equivalent to: return assign(p);
basic_regex& operator=(initializer_list<charT> il);
Effects: Equivalent to: return assign(il.begin(), il.end());
template<class ST, class SA> basic_regex& operator=(const basic_string<charT, ST, SA>& s);
Effects: Equivalent to: return assign(s);
basic_regex& assign(const basic_regex& e);
Effects: Equivalent to: return *this = e;
basic_regex& assign(basic_regex&& e) noexcept;
Effects: Equivalent to: return *this = std​::​move(e);
basic_regex& assign(const charT* p, flag_type f = regex_constants::ECMAScript);
Effects: Equivalent to: return assign(string_type(p), f);
basic_regex& assign(const charT* p, size_t len, flag_type f = regex_constants::ECMAScript);
Effects: Equivalent to: return assign(string_type(p, len), f);
template<class ST, class SA> basic_regex& assign(const basic_string<charT, ST, SA>& s, flag_type f = regex_constants::ECMAScript);
Effects: Assigns the regular expression contained in the string s, interpreted according the flags specified in f.
If an exception is thrown, *this is unchanged.
Postconditions: If no exception is thrown, flags() returns f and mark_count() returns the number of marked sub-expressions within the expression.
Returns: *this.
Throws: regex_error if s is not a valid regular expression.
template<class InputIterator> basic_regex& assign(InputIterator first, InputIterator last, flag_type f = regex_constants::ECMAScript);
Effects: Equivalent to: return assign(string_type(first, last), f);
basic_regex& assign(initializer_list<charT> il, flag_type f = regex_constants::ECMAScript);
Effects: Equivalent to: return assign(il.begin(), il.end(), f);

28.6.7.4 Constant operations [re.regex.operations]

unsigned mark_count() const;
Effects: Returns the number of marked sub-expressions within the regular expression.
flag_type flags() const;
Effects: Returns a copy of the regular expression syntax flags that were passed to the object's constructor or to the last call to assign.

28.6.7.5 Locale [re.regex.locale]

locale_type imbue(locale_type loc);
Effects: Returns the result of traits_inst.imbue(loc) where traits_inst is a (default-initialized) instance of the template type argument traits stored within the object.
After a call to imbue the basic_regex object does not match any character sequence.
locale_type getloc() const;
Effects: Returns the result of traits_inst.getloc() where traits_inst is a (default-initialized) instance of the template parameter traits stored within the object.

28.6.7.6 Swap [re.regex.swap]

void swap(basic_regex& e);
Effects: Swaps the contents of the two regular expressions.
Postconditions: *this contains the regular expression that was in e, e contains the regular expression that was in *this.
Complexity: Constant time.

28.6.7.7 Non-member functions [re.regex.nonmemb]

template<class charT, class traits> void swap(basic_regex<charT, traits>& lhs, basic_regex<charT, traits>& rhs);
Effects: Calls lhs.swap(rhs).

28.6.8 Class template sub_match [re.submatch]

28.6.8.1 General [re.submatch.general]

Class template sub_match denotes the sequence of characters matched by a particular marked sub-expression.
namespace std { template<class BidirectionalIterator> class sub_match : public pair<BidirectionalIterator, BidirectionalIterator> { public: using value_type = typename iterator_traits<BidirectionalIterator>::value_type; using difference_type = typename iterator_traits<BidirectionalIterator>::difference_type; using iterator = BidirectionalIterator; using string_type = basic_string<value_type>; bool matched; constexpr sub_match(); difference_type length() const; operator string_type() const; string_type str() const; int compare(const sub_match& s) const; int compare(const string_type& s) const; int compare(const value_type* s) const; void swap(sub_match& s) noexcept(see below); }; }

28.6.8.2 Members [re.submatch.members]

constexpr sub_match();
Effects: Value-initializes the pair base class subobject and the member matched.
difference_type length() const;
Returns: matched ? distance(first, second) : 0.
operator string_type() const;
Returns: matched ? string_type(first, second) : string_type().
string_type str() const;
Returns: matched ? string_type(first, second) : string_type().
int compare(const sub_match& s) const;
Returns: str().compare(s.str()).
int compare(const string_type& s) const;
Returns: str().compare(s).
int compare(const value_type* s) const;
Returns: str().compare(s).
void swap(sub_match& s) noexcept(see below);
Preconditions: BidirectionalIterator meets the Cpp17Swappable requirements ([swappable.requirements]).
Effects: Equivalent to: this->pair<BidirectionalIterator, BidirectionalIterator>::swap(s); std::swap(matched, s.matched);
Remarks: The exception specification is equivalent to is_nothrow_swappable_v<BidirectionalIterator>.

28.6.8.3 Non-member operators [re.submatch.op]

Let SM-CAT(I) be compare_three_way_result_t<basic_string<typename iterator_traits<I>::value_type>>
template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
Returns: lhs.compare(rhs) == 0.
template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
Returns: static_cast<SM-CAT(BiIter)>(lhs.compare(rhs) <=> 0).
template<class BiIter, class ST, class SA> bool operator==( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
Returns: lhs.compare(typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) == 0
template<class BiIter, class ST, class SA> auto operator<=>( const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
Returns: static_cast<SM-CAT(BiIter)>(lhs.compare( typename sub_match<BiIter>::string_type(rhs.data(), rhs.size())) <=> 0 )
template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs);
Returns: lhs.compare(rhs) == 0.
template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type* rhs);
Returns: static_cast<SM-CAT(BiIter)>(lhs.compare(rhs) <=> 0).
template<class BiIter> bool operator==(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs);
Returns: lhs.compare(typename sub_match<BiIter>​::​string_type(1, rhs)) == 0.
template<class BiIter> auto operator<=>(const sub_match<BiIter>& lhs, const typename iterator_traits<BiIter>::value_type& rhs);
Returns: static_cast<SM-CAT(BiIter)>(lhs.compare( typename sub_match<BiIter>::string_type(1, rhs)) <=> 0 )
template<class charT, class ST, class BiIter> basic_ostream<charT, ST>& operator<<(basic_ostream<charT, ST>& os, const sub_match<BiIter>& m);
Returns: os << m.str().

28.6.9 Class template match_results [re.results]

28.6.9.1 General [re.results.general]

Class template match_results denotes a collection of character sequences representing the result of a regular expression match.
Storage for the collection is allocated and freed as necessary by the member functions of class template match_results.
The class template match_results meets the requirements of an allocator-aware container ([container.alloc.reqmts]) and of a sequence container ([container.requirements.general], [sequence.reqmts]) except that only copy assignment, move assignment, and operations defined for const-qualified sequence containers are supported and that the semantics of the comparison operator functions are different from those required for a container.
A default-constructed match_results object has no fully established result state.
A match result is ready when, as a consequence of a completed regular expression match modifying such an object, its result state becomes fully established.
The effects of calling most member functions from a match_results object that is not ready are undefined.
The sub_match object stored at index 0 represents sub-expression 0, i.e., the whole match.
In this case the sub_match member matched is always true.
The sub_match object stored at index n denotes what matched the marked sub-expression n within the matched expression.
If the sub-expression n participated in a regular expression match then the sub_match member matched evaluates to true, and members first and second denote the range of characters [first, second) which formed that match.
Otherwise matched is false, and members first and second point to the end of the sequence that was searched.
[Note 1: 
The sub_match objects representing different sub-expressions that did not participate in a regular expression match need not be distinct.
— end note]
namespace std { template<class BidirectionalIterator, class Allocator = allocator<sub_match<BidirectionalIterator>>> class match_results { public: using value_type = sub_match<BidirectionalIterator>; using const_reference = const value_type&; using reference = value_type&; using const_iterator = implementation-defined; using iterator = const_iterator; using difference_type = typename iterator_traits<BidirectionalIterator>::difference_type; using size_type = typename allocator_traits<Allocator>::size_type; using allocator_type = Allocator; using char_type = typename iterator_traits<BidirectionalIterator>::value_type; using string_type = basic_string<char_type>; // [re.results.const], construct/copy/destroy match_results() : match_results(Allocator()) {} explicit match_results(const Allocator& a); match_results(const match_results& m); match_results(const match_results& m, const Allocator& a); match_results(match_results&& m) noexcept; match_results(match_results&& m, const Allocator& a); match_results& operator=(const match_results& m); match_results& operator=(match_results&& m); ~match_results(); // [re.results.state], state bool ready() const; // [re.results.size], size size_type size() const; size_type max_size() const; bool empty() const; // [re.results.acc], element access difference_type length(size_type sub = 0) const; difference_type position(size_type sub = 0) const; string_type str(size_type sub = 0) const; const_reference operator[](size_type n) const; const_reference prefix() const; const_reference suffix() const; const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; // [re.results.form], format template<class OutputIter> OutputIter format(OutputIter out, const char_type* fmt_first, const char_type* fmt_last, regex_constants::match_flag_type flags = regex_constants::format_default) const; template<class OutputIter, class ST, class SA> OutputIter format(OutputIter out, const basic_string<char_type, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; template<class ST, class SA> basic_string<char_type, ST, SA> format(const basic_string<char_type, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; string_type format(const char_type* fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const; // [re.results.all], allocator allocator_type get_allocator() const; // [re.results.swap], swap void swap(match_results& that); }; }

28.6.9.2 Constructors [re.results.const]

Table 117 lists the postconditions of match_results copy/move constructors and copy/move assignment operators.
For move operations, the results of the expressions depending on the parameter m denote the values they had before the respective function calls.
explicit match_results(const Allocator& a);
Effects: The stored Allocator value is constructed from a.
Postconditions: ready() returns false.
size() returns 0.
match_results(const match_results& m); match_results(const match_results& m, const Allocator& a);
Effects: For the first form, the stored Allocator value is obtained as specified in [container.reqmts].
For the second form, the stored Allocator value is constructed from a.
Postconditions: As specified in Table 117.
match_results(match_results&& m) noexcept; match_results(match_results&& m, const Allocator& a);
Effects: For the first form, the stored Allocator value is move constructed from m.get_allocator().
For the second form, the stored Allocator value is constructed from a.
Postconditions: As specified in Table 117.
Throws: The second form throws nothing if a == m.get_allocator() is true.
match_results& operator=(const match_results& m);
Postconditions: As specified in Table 117.
match_results& operator=(match_results&& m);
Postconditions: As specified in Table 117.
Table 117match_results copy/move operation postconditions [tab:re.results.const]
Element
Value
ready()
m.ready()
size()
m.size()
str(n)
m.str(n) for all non-negative integers n < m.size()
prefix()
m.prefix()
suffix()
m.suffix()
(*this)[n]
m[n] for all non-negative integers n < m.size()
length(n)
m.length(n) for all non-negative integers n < m.size()
position(n)
m.position(n) for all non-negative integers n < m.size()

28.6.9.3 State [re.results.state]

bool ready() const;
Returns: true if *this has a fully established result state, otherwise false.

28.6.9.4 Size [re.results.size]

size_type size() const;
Returns: One plus the number of marked sub-expressions in the regular expression that was matched if *this represents the result of a successful match.
Otherwise returns 0.
[Note 1: 
The state of a match_results object can be modified only by passing that object to regex_match or regex_search.
Subclauses [re.alg.match] and [re.alg.search] specify the effects of those algorithms on their match_results arguments.
— end note]
size_type max_size() const;
Returns: The maximum number of sub_match elements that can be stored in *this.
bool empty() const;
Returns: size() == 0.

28.6.9.5 Element access [re.results.acc]

difference_type length(size_type sub = 0) const;
Preconditions: ready() == true.
Returns: (*this)[sub].length().
difference_type position(size_type sub = 0) const;
Preconditions: ready() == true.
Returns: The distance from the start of the target sequence to (*this)[sub].first.
string_type str(size_type sub = 0) const;
Preconditions: ready() == true.
Returns: string_type((*this)[sub]).
const_reference operator[](size_type n) const;
Preconditions: ready() == true.
Returns: A reference to the sub_match object representing the character sequence that matched marked sub-expression n.
If n == 0 then returns a reference to a sub_match object representing the character sequence that matched the whole regular expression.
If n >= size() then returns a sub_match object representing an unmatched sub-expression.
const_reference prefix() const;
Preconditions: ready() == true.
Returns: A reference to the sub_match object representing the character sequence from the start of the string being matched/searched to the start of the match found.
const_reference suffix() const;
Preconditions: ready() == true.
Returns: A reference to the sub_match object representing the character sequence from the end of the match found to the end of the string being matched/searched.
const_iterator begin() const; const_iterator cbegin() const;
Returns: A starting iterator that enumerates over all the sub-expressions stored in *this.
const_iterator end() const; const_iterator cend() const;
Returns: A terminating iterator that enumerates over all the sub-expressions stored in *this.

28.6.9.6 Formatting [re.results.form]

template<class OutputIter> OutputIter format( OutputIter out, const char_type* fmt_first, const char_type* fmt_last, regex_constants::match_flag_type flags = regex_constants::format_default) const;
Preconditions: ready() == true and OutputIter meets the requirements for a Cpp17OutputIterator ([output.iterators]).
Effects: Copies the character sequence [fmt_first, fmt_last) to OutputIter out.
Replaces each format specifier or escape sequence in the copied range with either the character(s) it represents or the sequence of characters within *this to which it refers.
The bitmasks specified in flags determine which format specifiers and escape sequences are recognized.
Returns: out.
template<class OutputIter, class ST, class SA> OutputIter format( OutputIter out, const basic_string<char_type, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const;
Effects: Equivalent to: return format(out, fmt.data(), fmt.data() + fmt.size(), flags);
template<class ST, class SA> basic_string<char_type, ST, SA> format( const basic_string<char_type, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const;
Preconditions: ready() == true.
Effects: Constructs an empty string result of type basic_string<char_type, ST, SA> and calls: format(back_inserter(result), fmt, flags);
Returns: result.
string_type format( const char_type* fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const;
Preconditions: ready() == true.
Effects: Constructs an empty string result of type string_type and calls: format(back_inserter(result), fmt, fmt + char_traits<char_type>::length(fmt), flags);
Returns: result.

28.6.9.7 Allocator [re.results.all]

allocator_type get_allocator() const;
Returns: A copy of the Allocator that was passed to the object's constructor or, if that allocator has been replaced, a copy of the most recent replacement.

28.6.9.8 Swap [re.results.swap]

void swap(match_results& that);
Effects: Swaps the contents of the two sequences.
Postconditions: *this contains the sequence of matched sub-expressions that were in that, that contains the sequence of matched sub-expressions that were in *this.
Complexity: Constant time.
template<class BidirectionalIterator, class Allocator> void swap(match_results<BidirectionalIterator, Allocator>& m1, match_results<BidirectionalIterator, Allocator>& m2);
Effects: As if by m1.swap(m2).

28.6.9.9 Non-member functions [re.results.nonmember]

template<class BidirectionalIterator, class Allocator> bool operator==(const match_results<BidirectionalIterator, Allocator>& m1, const match_results<BidirectionalIterator, Allocator>& m2);
Returns: true if neither match result is ready, false if one match result is ready and the other is not.
If both match results are ready, returns true only if
  • m1.empty() && m2.empty(), or
  • !m1.empty() && !m2.empty(), and the following conditions are satisfied:
    • m1.prefix() == m2.prefix(),
    • m1.size() == m2.size() && equal(m1.begin(), m1.end(), m2.begin()), and
    • m1.suffix() == m2.suffix().
[Note 1: 
The algorithm equal is defined in [algorithms].
— end note]

28.6.10 Regular expression algorithms [re.alg]

28.6.10.1 Exceptions [re.except]

The algorithms described in subclause [re.alg] may throw an exception of type regex_error.
If such an exception e is thrown, e.code() shall return either regex_constants​::​error_complexity or regex_constants​::​error_stack.

28.6.10.2 regex_match [re.alg.match]

template<class BidirectionalIterator, class Allocator, class charT, class traits> bool regex_match(BidirectionalIterator first, BidirectionalIterator last, match_results<BidirectionalIterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Preconditions: BidirectionalIterator models bidirectional_iterator ([iterator.concept.bidir]).
Effects: Determines whether there is a match between the regular expression e, and all of the character sequence [first, last).
The parameter flags is used to control how the expression is matched against the character sequence.
When determining if there is a match, only potential matches that match the entire character sequence are considered.
Returns true if such a match exists, false otherwise.
[Example 1: std::regex re("Get|GetValue"); std::cmatch m; regex_search("GetValue", m, re); // returns true, and m[0] contains "Get" regex_match ("GetValue", m, re); // returns true, and m[0] contains "GetValue" regex_search("GetValues", m, re); // returns true, and m[0] contains "Get" regex_match ("GetValues", m, re); // returns false — end example]
Postconditions: m.ready() == true in all cases.
If the function returns false, then the effect on parameter m is unspecified except that m.size() returns 0 and m.empty() returns true.
Otherwise the effects on parameter m are given in Table 118.
Table 118 — Effects of regex_match algorithm [tab:re.alg.match]
Element
Value
m.size()
1 + e.mark_count()
m.empty()
false
m.prefix().first
first
m.prefix().second
first
m.prefix().matched
false
m.suffix().first
last
m.suffix().second
last
m.suffix().matched
false
m[0].first
first
m[0].second
last
m[0].matched
true
m[n].first
For all integers 0 < n < m.size(), the start of the sequence that matched sub-expression n.
Alternatively, if sub-expression n did not participate in the match, then last.
m[n].second
For all integers 0 < n < m.size(), the end of the sequence that matched sub-expression n.
Alternatively, if sub-expression n did not participate in the match, then last.
m[n].matched
For all integers 0 < n < m.size(), true if sub-expression n participated in the match, false otherwise.
template<class BidirectionalIterator, class charT, class traits> bool regex_match(BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Effects: Behaves “as if” by constructing an instance of match_results<BidirectionalIterator> what, and then returning the result of regex_match(first, last, what, e, flags).
template<class charT, class Allocator, class traits> bool regex_match(const charT* str, match_results<const charT*, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_match(str, str + char_traits<charT>​::​length(str), m, e, flags).
template<class ST, class SA, class Allocator, class charT, class traits> bool regex_match(const basic_string<charT, ST, SA>& s, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_match(s.begin(), s.end(), m, e, flags).
template<class charT, class traits> bool regex_match(const charT* str, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_match(str, str + char_traits<charT>​::​length(str), e, flags)
template<class ST, class SA, class charT, class traits> bool regex_match(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_match(s.begin(), s.end(), e, flags).

28.6.10.3 regex_search [re.alg.search]

Preconditions: BidirectionalIterator models bidirectional_iterator ([iterator.concept.bidir]).
Effects: Determines whether there is some sub-sequence within [first, last) that matches the regular expression e.
The parameter flags is used to control how the expression is matched against the character sequence.
Returns true if such a sequence exists, false otherwise.
Postconditions: m.ready() == true in all cases.
If the function returns false, then the effect on parameter m is unspecified except that m.size() returns 0 and m.empty() returns true.
Otherwise the effects on parameter m are given in Table 119.
Table 119 — Effects of regex_search algorithm [tab:re.alg.search]
Element
Value
m.size()
1 + e.mark_count()
m.empty()
false
m.prefix().first
first
m.prefix().second
m[0].first
m.prefix().matched
m.prefix().first != m.prefix().second
m.suffix().first
m[0].second
m.suffix().second
last
m.suffix().matched
m.suffix().first != m.suffix().second
m[0].first
The start of the sequence of characters that matched the regular expression
m[0].second
The end of the sequence of characters that matched the regular expression
m[0].matched
true
m[n].first
For all integers 0 < n < m.size(), the start of the sequence that matched sub-expression n.
Alternatively, if sub-expression n did not participate in the match, then last.
m[n].second
For all integers 0 < n < m.size(), the end of the sequence that matched sub-expression n.
Alternatively, if sub-expression n did not participate in the match, then last.
m[n].matched
For all integers 0 < n < m.size(), true if sub-expression n participated in the match, false otherwise.
template<class charT, class Allocator, class traits> bool regex_search(const charT* str, match_results<const charT*, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_search(str, str + char_traits<charT>​::​length(str), m, e, flags).
template<class ST, class SA, class Allocator, class charT, class traits> bool regex_search(const basic_string<charT, ST, SA>& s, match_results<typename basic_string<charT, ST, SA>::const_iterator, Allocator>& m, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_search(s.begin(), s.end(), m, e, flags).
template<class BidirectionalIterator, class charT, class traits> bool regex_search(BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Effects: Behaves “as if” by constructing an object what of type match_results<BidirectionalIterator> and returning regex_search(first, last, what, e, flags).
template<class charT, class traits> bool regex_search(const charT* str, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_search(str, str + char_traits<charT>​::​length(str), e, flags).
template<class ST, class SA, class charT, class traits> bool regex_search(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, regex_constants::match_flag_type flags = regex_constants::match_default);
Returns: regex_search(s.begin(), s.end(), e, flags).

28.6.10.4 regex_replace [re.alg.replace]

template<class OutputIterator, class BidirectionalIterator, class traits, class charT, class ST, class SA> OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, const basic_string<charT, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class OutputIterator, class BidirectionalIterator, class traits, class charT> OutputIterator regex_replace(OutputIterator out, BidirectionalIterator first, BidirectionalIterator last, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default);
Effects: Constructs a regex_iterator object i as if by regex_iterator<BidirectionalIterator, charT, traits> i(first, last, e, flags) and uses i to enumerate through all of the matches m of type match_results<BidirectionalIterator> that occur within the sequence [first, last).
If no such matches are found and !(flags & regex_constants​::​format_no_copy), then calls out = copy(first, last, out)
If any matches are found then, for each such match:
  • If !(flags & regex_constants​::​format_no_copy), calls out = copy(m.prefix().first, m.prefix().second, out)
  • Then calls out = m.format(out, fmt, flags) for the first form of the function and out = m.format(out, fmt, fmt + char_traits<charT>::length(fmt), flags) for the second.
Finally, if such a match is found and !(flags & regex_constants​::​format_no_copy), calls out = copy(last_m.suffix().first, last_m.suffix().second, out) where last_m is a copy of the last match found.
If flags & regex_constants​::​format_first_only is nonzero, then only the first match found is replaced.
Returns: out.
template<class traits, class charT, class ST, class SA, class FST, class FSA> basic_string<charT, ST, SA> regex_replace(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, const basic_string<charT, FST, FSA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT, class ST, class SA> basic_string<charT, ST, SA> regex_replace(const basic_string<charT, ST, SA>& s, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default);
Effects: Constructs an empty string result of type basic_string<charT, ST, SA> and calls: regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags);
Returns: result.
template<class traits, class charT, class ST, class SA> basic_string<charT> regex_replace(const charT* s, const basic_regex<charT, traits>& e, const basic_string<charT, ST, SA>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template<class traits, class charT> basic_string<charT> regex_replace(const charT* s, const basic_regex<charT, traits>& e, const charT* fmt, regex_constants::match_flag_type flags = regex_constants::match_default);
Effects: Constructs an empty string result of type basic_string<charT> and calls: regex_replace(back_inserter(result), s, s + char_traits<charT>::length(s), e, fmt, flags);
Returns: result.

28.6.11 Regular expression iterators [re.iter]

28.6.11.1 Class template regex_iterator [re.regiter]

28.6.11.1.1 General [re.regiter.general]

The class template regex_iterator is an iterator adaptor.
It represents a new view of an existing iterator sequence, by enumerating all the occurrences of a regular expression within that sequence.
A regex_iterator uses regex_search to find successive regular expression matches within the sequence from which it was constructed.
After the iterator is constructed, and every time operator++ is used, the iterator finds and stores a value of match_results<BidirectionalIterator>.
If the end of the sequence is reached (regex_search returns false), the iterator becomes equal to the end-of-sequence iterator value.
The default constructor constructs an end-of-sequence iterator object, which is the only legitimate iterator to be used for the end condition.
The result of operator* on an end-of-sequence iterator is not defined.
For any other iterator value a const match_results<BidirectionalIterator>& is returned.
The result of operator-> on an end-of-sequence iterator is not defined.
For any other iterator value a const match_results<BidirectionalIterator>* is returned.
It is impossible to store things into regex_iterators.
Two end-of-sequence iterators are always equal.
An end-of-sequence iterator is not equal to a non-end-of-sequence iterator.
Two non-end-of-sequence iterators are equal when they are constructed from the same arguments.
namespace std { template<class BidirectionalIterator, class charT = typename iterator_traits<BidirectionalIterator>::value_type, class traits = regex_traits<charT>> class regex_iterator { public: using regex_type = basic_regex<charT, traits>; using iterator_category = forward_iterator_tag; using iterator_concept = input_iterator_tag; using value_type = match_results<BidirectionalIterator>; using difference_type = ptrdiff_t; using pointer = const value_type*; using reference = const value_type&; regex_iterator(); regex_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, regex_constants::match_flag_type m = regex_constants::match_default); regex_iterator(BidirectionalIterator, BidirectionalIterator, const regex_type&&, regex_constants::match_flag_type = regex_constants::match_default) = delete; regex_iterator(const regex_iterator&); regex_iterator& operator=(const regex_iterator&); bool operator==(const regex_iterator&) const; bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } const value_type& operator*() const; const value_type* operator->() const; regex_iterator& operator++(); regex_iterator operator++(int); private: BidirectionalIterator begin; // exposition only BidirectionalIterator end; // exposition only const regex_type* pregex; // exposition only regex_constants::match_flag_type flags; // exposition only match_results<BidirectionalIterator> match; // exposition only }; }
An object of type regex_iterator that is not an end-of-sequence iterator holds a zero-length match if match[0].matched == true and match[0].first == match[0].second.
[Note 1: 
For example, this can occur when the part of the regular expression that matched consists only of an assertion (such as '^', '$', '\b', '\B').
— end note]

28.6.11.1.2 Constructors [re.regiter.cnstr]

regex_iterator();
Effects: Constructs an end-of-sequence iterator.
regex_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, regex_constants::match_flag_type m = regex_constants::match_default);
Effects: Initializes begin and end to a and b, respectively, sets pregex to addressof(re), sets flags to m, then calls regex_search(begin, end, match, *pregex, flags).
If this call returns false the constructor sets *this to the end-of-sequence iterator.

28.6.11.1.3 Comparisons [re.regiter.comp]

bool operator==(const regex_iterator& right) const;
Returns: true if *this and right are both end-of-sequence iterators or if the following conditions all hold:
  • begin == right.begin,
  • end == right.end,
  • pregex == right.pregex,
  • flags == right.flags, and
  • match[0] == right.match[0];
otherwise false.

28.6.11.1.4 Indirection [re.regiter.deref]

const value_type& operator*() const;
Returns: match.
const value_type* operator->() const;
Returns: addressof(match).

28.6.11.1.5 Increment [re.regiter.incr]

regex_iterator& operator++();
Effects: Constructs a local variable start of type BidirectionalIterator and initializes it with the value of match[0].second.
If the iterator holds a zero-length match and start == end the operator sets *this to the end-of-sequence iterator and returns *this.
Otherwise, if the iterator holds a zero-length match, the operator calls: regex_search(start, end, match, *pregex, flags | regex_constants::match_not_null | regex_constants::match_continuous)
If the call returns true the operator returns *this.
Otherwise the operator increments start and continues as if the most recent match was not a zero-length match.
If the most recent match was not a zero-length match, the operator sets flags to flags | regex_constants​::​match_prev_avail and calls regex_search(start, end, match, *pregex, flags).
If the call returns false the iterator sets *this to the end-of-sequence iterator.
The iterator then returns *this.
In all cases in which the call to regex_search returns true, match.prefix().first shall be equal to the previous value of match[0].second, and for each index i in the half-open range [0, match.size()) for which match[i].matched is true, match.position(i) shall return distance(begin, match[i].​first).
[Note 1: 
This means that match.position(i) gives the offset from the beginning of the target sequence, which is often not the same as the offset from the sequence passed in the call to regex_search.
— end note]
It is unspecified how the implementation makes these adjustments.
[Note 2: 
This means that an implementation can call an implementation-specific search function, in which case a program-defined specialization of regex_search will not be called.
— end note]
regex_iterator operator++(int);
Effects: As if by: regex_iterator tmp = *this; ++(*this); return tmp;

28.6.11.2 Class template regex_token_iterator [re.tokiter]

28.6.11.2.1 General [re.tokiter.general]

The class template regex_token_iterator is an iterator adaptor; that is to say it represents a new view of an existing iterator sequence, by enumerating all the occurrences of a regular expression within that sequence, and presenting one or more sub-expressions for each match found.
Each position enumerated by the iterator is a sub_match class template instance that represents what matched a particular sub-expression within the regular expression.
When class regex_token_iterator is used to enumerate a single sub-expression with index the iterator performs field splitting: that is to say it enumerates one sub-expression for each section of the character container sequence that does not match the regular expression specified.
After it is constructed, the iterator finds and stores a value regex_iterator<BidirectionalIterator> position and sets the internal count N to zero.
It also maintains a sequence subs which contains a list of the sub-expressions which will be enumerated.
Every time operator++ is used the count N is incremented; if N exceeds or equals subs.size(), then the iterator increments member position and sets count N to zero.
If the end of sequence is reached (position is equal to the end of sequence iterator), the iterator becomes equal to the end-of-sequence iterator value, unless the sub-expression being enumerated has index , in which case the iterator enumerates one last sub-expression that contains all the characters from the end of the last regular expression match to the end of the input sequence being enumerated, provided that this would not be an empty sub-expression.
The default constructor constructs an end-of-sequence iterator object, which is the only legitimate iterator to be used for the end condition.
The result of operator* on an end-of-sequence iterator is not defined.
For any other iterator value a const sub_match<BidirectionalIterator>& is returned.
The result of operator-> on an end-of-sequence iterator is not defined.
For any other iterator value a const sub_match<BidirectionalIterator>* is returned.
It is impossible to store things into regex_token_iterators.
Two end-of-sequence iterators are always equal.
An end-of-sequence iterator is not equal to a non-end-of-sequence iterator.
Two non-end-of-sequence iterators are equal when they are constructed from the same arguments.
namespace std { template<class BidirectionalIterator, class charT = typename iterator_traits<BidirectionalIterator>::value_type, class traits = regex_traits<charT>> class regex_token_iterator { public: using regex_type = basic_regex<charT, traits>; using iterator_category = forward_iterator_tag; using iterator_concept = input_iterator_tag; using value_type = sub_match<BidirectionalIterator>; using difference_type = ptrdiff_t; using pointer = const value_type*; using reference = const value_type&; regex_token_iterator(); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const vector<int>& submatches, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, initializer_list<int> submatches, regex_constants::match_flag_type m = regex_constants::match_default); template<size_t N> regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const int (&submatches)[N], regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) = delete; regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, const vector<int>& submatches, regex_constants::match_flag_type m = regex_constants::match_default) = delete; regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, initializer_list<int> submatches, regex_constants::match_flag_type m = regex_constants::match_default) = delete; template<size_t N> regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type&& re, const int (&submatches)[N], regex_constants::match_flag_type m = regex_constants::match_default) = delete; regex_token_iterator(const regex_token_iterator&); regex_token_iterator& operator=(const regex_token_iterator&); bool operator==(const regex_token_iterator&) const; bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } const value_type& operator*() const; const value_type* operator->() const; regex_token_iterator& operator++(); regex_token_iterator operator++(int); private: using position_iterator = regex_iterator<BidirectionalIterator, charT, traits>; // exposition only position_iterator position; // exposition only const value_type* result; // exposition only value_type suffix; // exposition only size_t N; // exposition only vector<int> subs; // exposition only }; }
A suffix iterator is a regex_token_iterator object that points to a final sequence of characters at the end of the target sequence.
In a suffix iterator the member result holds a pointer to the data member suffix, the value of the member suffix.match is true, suffix.first points to the beginning of the final sequence, and suffix.second points to the end of the final sequence.
[Note 1: 
For a suffix iterator, data member suffix.first is the same as the end of the last match found, and suffix​.second is the same as the end of the target sequence.
— end note]
The current match is (*position).prefix() if subs[N] == -1, or (*position)[subs[N]] for any other value of subs[N].

28.6.11.2.2 Constructors [re.tokiter.cnstr]

regex_token_iterator();
Effects: Constructs the end-of-sequence iterator.
regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const vector<int>& submatches, regex_constants::match_flag_type m = regex_constants::match_default); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, initializer_list<int> submatches, regex_constants::match_flag_type m = regex_constants::match_default); template<size_t N> regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, const int (&submatches)[N], regex_constants::match_flag_type m = regex_constants::match_default);
Preconditions: Each of the initialization values of submatches is >= -1.
Effects: The first constructor initializes the member subs to hold the single value submatch.
The second, third, and fourth constructors initialize the member subs to hold a copy of the sequence of integer values pointed to by the iterator range [begin(submatches), end(submatches)).
Each constructor then sets N to 0, and position to position_iterator(a, b, re, m).
If position is not an end-of-sequence iterator the constructor sets result to the address of the current match.
Otherwise if any of the values stored in subs is equal to the constructor sets *this to a suffix iterator that points to the range [a, b), otherwise the constructor sets *this to an end-of-sequence iterator.

28.6.11.2.3 Comparisons [re.tokiter.comp]

bool operator==(const regex_token_iterator& right) const;
Returns: true if *this and right are both end-of-sequence iterators, or if *this and right are both suffix iterators and suffix == right.suffix; otherwise returns false if *this or right is an end-of-sequence iterator or a suffix iterator.
Otherwise returns true if position == right.position, N == right.N, and subs == right.subs.
Otherwise returns false.

28.6.11.2.4 Indirection [re.tokiter.deref]

const value_type& operator*() const;
Returns: *result.
const value_type* operator->() const;
Returns: result.

28.6.11.2.5 Increment [re.tokiter.incr]

regex_token_iterator& operator++();
Effects: Constructs a local variable prev of type position_iterator, initialized with the value of position.
If *this is a suffix iterator, sets *this to an end-of-sequence iterator.
Otherwise, if N + 1 < subs.size(), increments N and sets result to the address of the current match.
Otherwise, sets N to 0 and increments position.
If position is not an end-of-sequence iterator the operator sets result to the address of the current match.
Otherwise, if any of the values stored in subs is equal to and prev->suffix().length() is not 0 the operator sets *this to a suffix iterator that points to the range [prev->suffix().first, prev->suffix().second).
Otherwise, sets *this to an end-of-sequence iterator.
Returns: *this
regex_token_iterator& operator++(int);
Effects: Constructs a copy tmp of *this, then calls ++(*this).
Returns: tmp.

28.6.12 Modified ECMAScript regular expression grammar [re.grammar]

The regular expression grammar recognized by basic_regex objects constructed with the ECMAScript flag is that specified by ECMA-262, except as specified below.
Objects of type specialization of basic_regex store within themselves a default-constructed instance of their traits template parameter, henceforth referred to as traits_inst.
This traits_inst object is used to support localization of the regular expression; basic_regex member functions shall not call any locale dependent C or C++ API, including the formatted string input functions.
Instead they shall call the appropriate traits member function to achieve the required effect.
The following productions within the ECMAScript grammar are modified as follows:
ClassAtom::
-
ClassAtomNoDash
ClassAtomExClass
ClassAtomCollatingElement
ClassAtomEquivalence
IdentityEscape::
SourceCharacter but not c
The following new productions are then added:
ClassAtomExClass::
[: ClassName :]
ClassAtomCollatingElement::
[. ClassName .]
ClassAtomEquivalence::
[= ClassName =]
ClassName::
ClassNameCharacter
ClassNameCharacter ClassName
ClassNameCharacter::
SourceCharacter but not one of . or = or :
The productions ClassAtomExClass, ClassAtomCollatingElement and ClassAtomEquivalence provide functionality equivalent to that of the same features in regular expressions in POSIX.
The regular expression grammar may be modified by any regex_constants​::​syntax_option_type flags specified when constructing an object of type specialization of basic_regex according to the rules in Table 113.
A ClassName production, when used in ClassAtomExClass, is not valid if traits_inst.lookup_classname returns zero for that name.
The names recognized as valid ClassNames are determined by the type of the traits class, but at least the following names shall be recognized: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit, d, s, w.
In addition the following expressions shall be equivalent:
\d and [[:digit:]] \D and [^[:digit:]] \s and [[:space:]] \S and [^[:space:]] \w and [_[:alnum:]] \W and [^_[:alnum:]]
A ClassName production when used in a ClassAtomCollatingElement production is not valid if the value returned by traits_inst.lookup_collatename for that name is an empty string.
The results from multiple calls to traits_inst.lookup_classname can be bitwise or'ed together and subsequently passed to traits_inst.isctype.
A ClassName production when used in a ClassAtomEquivalence production is not valid if the value returned by traits_inst.lookup_collatename for that name is an empty string or if the value returned by traits_inst​.transform_primary for the result of the call to traits_inst.lookup_collatename is an empty string.
When the sequence of characters being transformed to a finite state machine contains an invalid class name the translator shall throw an exception object of type regex_error.
If the CV of a UnicodeEscapeSequence is greater than the largest value that can be held in an object of type charT the translator shall throw an exception object of type regex_error.
[Note 1: 
This means that values of the form "\uxxxx" that do not fit in a character are invalid.
— end note]
Where the regular expression grammar requires the conversion of a sequence of characters to an integral value, this is accomplished by calling traits_inst.value.
The behavior of the internal finite state machine representation when used to match a sequence of characters is as described in ECMA-262.
The behavior is modified according to any match_flag_type flags ([re.matchflag]) specified when using the regular expression object in one of the regular expression algorithms ([re.alg]).
The behavior is also localized by interaction with the traits class template parameter as follows:
  • During matching of a regular expression finite state machine against a sequence of characters, two characters c and d are compared using the following rules:
    • if (flags() & regex_constants​::​icase) the two characters are equal if traits_inst.translate_nocase(c) == traits_inst.translate_nocase(d);
    • otherwise, if flags() & regex_constants​::​collate the two characters are equal if traits_inst​.translate(c) == traits_inst​.translate(d);
    • otherwise, the two characters are equal if c == d.
  • During matching of a regular expression finite state machine against a sequence of characters, comparison of a collating element range c1-c2 against a character c is conducted as follows: if flags() & regex_constants​::​collate is false then the character c is matched if c1 <= c && c <= c2, otherwise c is matched in accordance with the following algorithm:
    string_type str1 = string_type(1, flags() & icase ? traits_inst.translate_nocase(c1) : traits_inst.translate(c1)); string_type str2 = string_type(1, flags() & icase ? traits_inst.translate_nocase(c2) : traits_inst.translate(c2)); string_type str = string_type(1, flags() & icase ? traits_inst.translate_nocase(c) : traits_inst.translate(c)); return traits_inst.transform(str1.begin(), str1.end()) <= traits_inst.transform(str.begin(), str.end()) && traits_inst.transform(str.begin(), str.end()) <= traits_inst.transform(str2.begin(), str2.end());
  • During matching of a regular expression finite state machine against a sequence of characters, testing whether a collating element is a member of a primary equivalence class is conducted by first converting the collating element and the equivalence class to sort keys using traits​::​transform_primary, and then comparing the sort keys for equality.
  • During matching of a regular expression finite state machine against a sequence of characters, a character c is a member of a character class designated by an iterator range [first, last) if traits_inst.isctype(c, traits_inst.lookup_classname(first, last, flags() & icase)) is true.
See also: ECMA-262 15.10

28.7 Null-terminated sequence utilities [text.c.strings]

28.7.1 Header <cctype> synopsis [cctype.syn]

namespace std { int isalnum(int c); int isalpha(int c); int isblank(int c); int iscntrl(int c); int isdigit(int c); int isgraph(int c); int islower(int c); int isprint(int c); int ispunct(int c); int isspace(int c); int isupper(int c); int isxdigit(int c); int tolower(int c); int toupper(int c); }
The contents and meaning of the header <cctype> are the same as the C standard library header <ctype.h>.
See also: ISO/IEC 9899:2018, 7.4

28.7.2 Header <cwctype> synopsis [cwctype.syn]

namespace std { using wint_t = see below; using wctrans_t = see below; using wctype_t = see below; int iswalnum(wint_t wc); int iswalpha(wint_t wc); int iswblank(wint_t wc); int iswcntrl(wint_t wc); int iswdigit(wint_t wc); int iswgraph(wint_t wc); int iswlower(wint_t wc); int iswprint(wint_t wc); int iswpunct(wint_t wc); int iswspace(wint_t wc); int iswupper(wint_t wc); int iswxdigit(wint_t wc); int iswctype(wint_t wc, wctype_t desc); wctype_t wctype(const char* property); wint_t towlower(wint_t wc); wint_t towupper(wint_t wc); wint_t towctrans(wint_t wc, wctrans_t desc); wctrans_t wctrans(const char* property); } #define WEOF see below
The contents and meaning of the header <cwctype> are the same as the C standard library header <wctype.h>.
See also: ISO/IEC 9899:2018, 7.30

28.7.3 Header <cwchar> synopsis [cwchar.syn]

namespace std { using size_t = see [support.types.layout]; // freestanding using mbstate_t = see below; // freestanding using wint_t = see below; // freestanding struct tm; int fwprintf(FILE* stream, const wchar_t* format, ...); int fwscanf(FILE* stream, const wchar_t* format, ...); int swprintf(wchar_t* s, size_t n, const wchar_t* format, ...); int swscanf(const wchar_t* s, const wchar_t* format, ...); int vfwprintf(FILE* stream, const wchar_t* format, va_list arg); int vfwscanf(FILE* stream, const wchar_t* format, va_list arg); int vswprintf(wchar_t* s, size_t n, const wchar_t* format, va_list arg); int vswscanf(const wchar_t* s, const wchar_t* format, va_list arg); int vwprintf(const wchar_t* format, va_list arg); int vwscanf(const wchar_t* format, va_list arg); int wprintf(const wchar_t* format, ...); int wscanf(const wchar_t* format, ...); wint_t fgetwc(FILE* stream); wchar_t* fgetws(wchar_t* s, int n, FILE* stream); wint_t fputwc(wchar_t c, FILE* stream); int fputws(const wchar_t* s, FILE* stream); int fwide(FILE* stream, int mode); wint_t getwc(FILE* stream); wint_t getwchar(); wint_t putwc(wchar_t c, FILE* stream); wint_t putwchar(wchar_t c); wint_t ungetwc(wint_t c, FILE* stream); double wcstod(const wchar_t* nptr, wchar_t** endptr); float wcstof(const wchar_t* nptr, wchar_t** endptr); long double wcstold(const wchar_t* nptr, wchar_t** endptr); long int wcstol(const wchar_t* nptr, wchar_t** endptr, int base); long long int wcstoll(const wchar_t* nptr, wchar_t** endptr, int base); unsigned long int wcstoul(const wchar_t* nptr, wchar_t** endptr, int base); unsigned long long int wcstoull(const wchar_t* nptr, wchar_t** endptr, int base); wchar_t* wcscpy(wchar_t* s1, const wchar_t* s2); // freestanding wchar_t* wcsncpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding wchar_t* wmemcpy(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding wchar_t* wmemmove(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding wchar_t* wcscat(wchar_t* s1, const wchar_t* s2); // freestanding wchar_t* wcsncat(wchar_t* s1, const wchar_t* s2, size_t n); // freestanding int wcscmp(const wchar_t* s1, const wchar_t* s2); // freestanding int wcscoll(const wchar_t* s1, const wchar_t* s2); int wcsncmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding size_t wcsxfrm(wchar_t* s1, const wchar_t* s2, size_t n); int wmemcmp(const wchar_t* s1, const wchar_t* s2, size_t n); // freestanding const wchar_t* wcschr(const wchar_t* s, wchar_t c); // freestanding; see [library.c] wchar_t* wcschr(wchar_t* s, wchar_t c); // freestanding; see [library.c] size_t wcscspn(const wchar_t* s1, const wchar_t* s2); // freestanding const wchar_t* wcspbrk(const wchar_t* s1, const wchar_t* s2); // freestanding; see [library.c] wchar_t* wcspbrk(wchar_t* s1, const wchar_t* s2); // freestanding; see [library.c] const wchar_t* wcsrchr(const wchar_t* s, wchar_t c); // freestanding; see [library.c] wchar_t* wcsrchr(wchar_t* s, wchar_t c); // freestanding; see [library.c] size_t wcsspn(const wchar_t* s1, const wchar_t* s2); // freestanding const wchar_t* wcsstr(const wchar_t* s1, const wchar_t* s2); // freestanding; see [library.c] wchar_t* wcsstr(wchar_t* s1, const wchar_t* s2); // freestanding; see [library.c] wchar_t* wcstok(wchar_t* s1, const wchar_t* s2, wchar_t** ptr); // freestanding const wchar_t* wmemchr(const wchar_t* s, wchar_t c, size_t n); // freestanding; see [library.c] wchar_t* wmemchr(wchar_t* s, wchar_t c, size_t n); // freestanding; see [library.c] size_t wcslen(const wchar_t* s); // freestanding wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n); // freestanding size_t wcsftime(wchar_t* s, size_t maxsize, const wchar_t* format, const tm* timeptr); wint_t btowc(int c); int wctob(wint_t c); // [c.mb.wcs], multibyte / wide string and character conversion functions int mbsinit(const mbstate_t* ps); size_t mbrlen(const char* s, size_t n, mbstate_t* ps); size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps); } #define NULL see [support.types.nullptr] // freestanding #define WCHAR_MAX see below // freestanding #define WCHAR_MIN see below // freestanding #define WEOF see below // freestanding
The contents and meaning of the header <cwchar> are the same as the C standard library header <wchar.h>, except that it does not declare a type wchar_t.
[Note 1: 
The functions wcschr, wcspbrk, wcsrchr, wcsstr, and wmemchr have different signatures in this document, but they have the same behavior as in the C standard library ([library.c]).
— end note]
See also: ISO/IEC 9899:2018, 7.29

28.7.4 Header <cuchar> synopsis [cuchar.syn]

namespace std { using mbstate_t = see below; using size_t = see [support.types.layout]; size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps); size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps); size_t mbrtoc16(char16_t* pc16, const char* s, size_t n, mbstate_t* ps); size_t c16rtomb(char* s, char16_t c16, mbstate_t* ps); size_t mbrtoc32(char32_t* pc32, const char* s, size_t n, mbstate_t* ps); size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps); }
The contents and meaning of the header <cuchar> are the same as the C standard library header <uchar.h>, except that it declares the additional mbrtoc8 and c8rtomb functions and does not declare types char16_t nor char32_t.
See also: ISO/IEC 9899:2018, 7.28

28.7.5 Multibyte / wide string and character conversion functions [c.mb.wcs]

[Note 1: 
The headers <cstdlib>, <cuchar>, and <cwchar> declare the functions described in this subclause.
— end note]
int mbsinit(const mbstate_t* ps); int mblen(const char* s, size_t n); size_t mbstowcs(wchar_t* pwcs, const char* s, size_t n); size_t wcstombs(char* s, const wchar_t* pwcs, size_t n);
Effects: These functions have the semantics specified in the C standard library.
See also: ISO/IEC 9899:2018, 7.22.7.1, 7.22.8, 7.29.6.2.1
int mbtowc(wchar_t* pwc, const char* s, size_t n); int wctomb(char* s, wchar_t wchar);
Effects: These functions have the semantics specified in the C standard library.
Remarks: Calls to these functions may introduce a data race ([res.on.data.races]) with other calls to the same function.
See also: ISO/IEC 9899:2018, 7.22.7
size_t mbrlen(const char* s, size_t n, mbstate_t* ps); size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps); size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps); size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps); size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps);
Effects: These functions have the semantics specified in the C standard library.
Remarks: Calling these functions with an mbstate_t* argument that is a null pointer value may introduce a data race ([res.on.data.races]) with other calls to the same function with an mbstate_t* argument that is a null pointer value.
See also: ISO/IEC 9899:2018, 7.29.6.3
size_t mbrtoc8(char8_t* pc8, const char* s, size_t n, mbstate_t* ps);
Effects: If s is a null pointer, equivalent to mbrtoc8(nullptr, "", 1, ps).
Otherwise, the function inspects at most n bytes beginning with the byte pointed to by s to determine the number of bytes needed to complete the next multibyte character (including any shift sequences).
If the function determines that the next multibyte character is complete and valid, it determines the values of the corresponding UTF-8 code units and then, if pc8 is not a null pointer, stores the value of the first (or only) such code unit in the object pointed to by pc8.
Subsequent calls will store successive UTF-8 code units without consuming any additional input until all the code units have been stored.
If the corresponding Unicode character is U+0000 null, the resulting state described is the initial conversion state.
Returns: The first of the following that applies (given the current conversion state):
  • 0, if the next n or fewer bytes complete the multibyte character that corresponds to the U+0000 null Unicode character (which is the value stored).
  • between 1 and n (inclusive), if the next n or fewer bytes complete a valid multibyte character (whose first (or only) code unit is stored); the value returned is the number of bytes that complete the multibyte character.
  • (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).
  • (size_t)(-2), if the next n bytes contribute to an incomplete (but potentially valid) multibyte character, and all n bytes have been processed (no value is stored).
  • (size_t)(-1), if an encoding error occurs, in which case the next n or fewer bytes do not contribute to a complete and valid multibyte character (no value is stored); the value of the macro EILSEQ is stored in errno, and the conversion state is unspecified.
size_t c8rtomb(char* s, char8_t c8, mbstate_t* ps);
Effects: If s is a null pointer, equivalent to c8rtomb(buf, u8'\0', ps) where buf is an internal buffer.
Otherwise, if c8 completes a sequence of valid UTF-8 code units, determines the number of bytes needed to represent the multibyte character (including any shift sequences), and stores the multibyte character representation in the array whose first element is pointed to by s.
At most MB_CUR_MAX bytes are stored.
If the multibyte character is a null character, a null byte is stored, preceded by any shift sequence needed to restore the initial shift state; the resulting state described is the initial conversion state.
Returns: The number of bytes stored in the array object (including any shift sequences).
If c8 does not contribute to a sequence of char8_t corresponding to a valid multibyte character, the value of the macro EILSEQ is stored in errno, (size_t) (-1) is returned, and the conversion state is unspecified.
Remarks: Calls to c8rtomb with a null pointer argument for s may introduce a data race ([res.on.data.races]) with other calls to c8rtomb with a null pointer argument for s.

29 Numerics library [numerics]

29.1 General [numerics.general]

This Clause describes components that C++ programs may use to perform seminumerical operations.
The following subclauses describe components for complex number types, random number generation, numeric (n-at-a-time) arrays, generalized numeric algorithms, and mathematical constants and functions for floating-point types, as summarized in Table 120.
Table 120 — Numerics library summary [tab:numerics.summary]
Subclause
Header
Requirements
Floating-point environment
<cfenv>
Complex numbers
<complex>
Random number generation
<random>
Numeric arrays
<valarray>
Mathematical functions for floating-point types
<cmath>, <cstdlib>
Numbers
<numbers>
Linear algebra
<linalg>
Data-parallel types
<simd>

29.2 Numeric type requirements [numeric.requirements]

The complex and valarray components are parameterized by the type of information they contain and manipulate.
A C++ program shall instantiate these components only with a numeric type.
If any operation on T throws an exception the effects are undefined.
In addition, many member and related functions of valarray<T> can be successfully instantiated and will exhibit well-defined behavior if and only if T meets additional requirements specified for each such member or related function.
[Example 1: 
It is valid to instantiate valarray<complex>, but operator>() will not be successfully instantiated for valarray<complex> operands, since complex does not have any ordering operators.
— end example]
243)243)
In other words, value types.
These include arithmetic types, pointers, the library class complex, and instantiations of valarray for value types.

29.3 The floating-point environment [cfenv]

29.3.1 Header <cfenv> synopsis [cfenv.syn]

#define FE_ALL_EXCEPT see below #define FE_DIVBYZERO see below // optional #define FE_INEXACT see below // optional #define FE_INVALID see below // optional #define FE_OVERFLOW see below // optional #define FE_UNDERFLOW see below // optional #define FE_DOWNWARD see below // optional #define FE_TONEAREST see below // optional #define FE_TOWARDZERO see below // optional #define FE_UPWARD see below // optional #define FE_DFL_ENV see below namespace std { // types using fenv_t = object type; using fexcept_t = object type; // functions int feclearexcept(int except); int fegetexceptflag(fexcept_t* pflag, int except); int feraiseexcept(int except); int fesetexceptflag(const fexcept_t* pflag, int except); int fetestexcept(int except); int fegetround(); int fesetround(int mode); int fegetenv(fenv_t* penv); int feholdexcept(fenv_t* penv); int fesetenv(const fenv_t* penv); int feupdateenv(const fenv_t* penv); }
The contents and meaning of the header <cfenv> are the same as the C standard library header <fenv.h>.
[Note 1: 
This document does not require an implementation to support the FENV_ACCESS pragma; it is implementation-defined ([cpp.pragma]) whether the pragma is supported.
As a consequence, it is implementation-defined whether these functions can be used to test floating-point status flags, set floating-point control modes, or run under non-default mode settings.
If the pragma is used to enable control over the floating-point environment, this document does not specify the effect on floating-point evaluation in constant expressions.
— end note]
See also: ISO/IEC 9899:2018, 7.6

29.3.2 Threads [cfenv.thread]

The floating-point environment has thread storage duration.
The initial state for a thread's floating-point environment is the state of the floating-point environment of the thread that constructs the corresponding thread object ([thread.thread.class]) or jthread object ([thread.jthread.class]) at the time it constructed the object.
[Note 1: 
That is, the child thread gets the floating-point state of the parent thread at the time of the child's creation.
— end note]
A separate floating-point environment is maintained for each thread.
Each function accesses the environment corresponding to its calling thread.

29.4 Complex numbers [complex.numbers]

29.4.1 General [complex.numbers.general]

The header <complex> defines a class template, and numerous functions for representing and manipulating complex numbers.
The effect of instantiating the template complex for any type that is not a cv-unqualified floating-point type ([basic.fundamental]) is unspecified.
Specializations of complex for cv-unqualified floating-point types are trivially copyable literal types ([basic.types.general]).
If the result of a function is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
If z is an lvalue of type cv complex<T> then:
  • the expression reinterpret_cast<cv T(&)[2]>(z) is well-formed,
  • reinterpret_cast<cv T(&)[2]>(z)[0] designates the real part of z, and
  • reinterpret_cast<cv T(&)[2]>(z)[1] designates the imaginary part of z.
Moreover, if a is an expression of type cv complex<T>* and the expression a[i] is well-defined for an integer expression i, then:
  • reinterpret_cast<cv T*>(a)[2*i] designates the real part of a[i], and
  • reinterpret_cast<cv T*>(a)[2*i + 1] designates the imaginary part of a[i].

29.4.2 Header <complex> synopsis [complex.syn]

namespace std { // [complex], class template complex template<class T> class complex; // [complex.ops], operators template<class T> constexpr complex<T> operator+(const complex<T>&, const complex<T>&); template<class T> constexpr complex<T> operator+(const complex<T>&, const T&); template<class T> constexpr complex<T> operator+(const T&, const complex<T>&); template<class T> constexpr complex<T> operator-(const complex<T>&, const complex<T>&); template<class T> constexpr complex<T> operator-(const complex<T>&, const T&); template<class T> constexpr complex<T> operator-(const T&, const complex<T>&); template<class T> constexpr complex<T> operator*(const complex<T>&, const complex<T>&); template<class T> constexpr complex<T> operator*(const complex<T>&, const T&); template<class T> constexpr complex<T> operator*(const T&, const complex<T>&); template<class T> constexpr complex<T> operator/(const complex<T>&, const complex<T>&); template<class T> constexpr complex<T> operator/(const complex<T>&, const T&); template<class T> constexpr complex<T> operator/(const T&, const complex<T>&); template<class T> constexpr complex<T> operator+(const complex<T>&); template<class T> constexpr complex<T> operator-(const complex<T>&); template<class T> constexpr bool operator==(const complex<T>&, const complex<T>&); template<class T> constexpr bool operator==(const complex<T>&, const T&); template<class T, class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, complex<T>&); template<class T, class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const complex<T>&); // [complex.value.ops], values template<class T> constexpr T real(const complex<T>&); template<class T> constexpr T imag(const complex<T>&); template<class T> constexpr T abs(const complex<T>&); template<class T> constexpr T arg(const complex<T>&); template<class T> constexpr T norm(const complex<T>&); template<class T> constexpr complex<T> conj(const complex<T>&); template<class T> constexpr complex<T> proj(const complex<T>&); template<class T> constexpr complex<T> polar(const T&, const T& = T()); // [complex.transcendentals], transcendentals template<class T> constexpr complex<T> acos(const complex<T>&); template<class T> constexpr complex<T> asin(const complex<T>&); template<class T> constexpr complex<T> atan(const complex<T>&); template<class T> constexpr complex<T> acosh(const complex<T>&); template<class T> constexpr complex<T> asinh(const complex<T>&); template<class T> constexpr complex<T> atanh(const complex<T>&); template<class T> constexpr complex<T> cos (const complex<T>&); template<class T> constexpr complex<T> cosh (const complex<T>&); template<class T> constexpr complex<T> exp (const complex<T>&); template<class T> constexpr complex<T> log (const complex<T>&); template<class T> constexpr complex<T> log10(const complex<T>&); template<class T> constexpr complex<T> pow (const complex<T>&, const T&); template<class T> constexpr complex<T> pow (const complex<T>&, const complex<T>&); template<class T> constexpr complex<T> pow (const T&, const complex<T>&); template<class T> constexpr complex<T> sin (const complex<T>&); template<class T> constexpr complex<T> sinh (const complex<T>&); template<class T> constexpr complex<T> sqrt (const complex<T>&); template<class T> constexpr complex<T> tan (const complex<T>&); template<class T> constexpr complex<T> tanh (const complex<T>&); // [complex.tuple], tuple interface template<class T> struct tuple_size; template<size_t I, class T> struct tuple_element; template<class T> struct tuple_size<complex<T>>; template<size_t I, class T> struct tuple_element<I, complex<T>>; template<size_t I, class T> constexpr T& get(complex<T>&) noexcept; template<size_t I, class T> constexpr T&& get(complex<T>&&) noexcept; template<size_t I, class T> constexpr const T& get(const complex<T>&) noexcept; template<size_t I, class T> constexpr const T&& get(const complex<T>&&) noexcept; // [complex.literals], complex literals inline namespace literals { inline namespace complex_literals { constexpr complex<long double> operator""il(long double); constexpr complex<long double> operator""il(unsigned long long); constexpr complex<double> operator""i(long double); constexpr complex<double> operator""i(unsigned long long); constexpr complex<float> operator""if(long double); constexpr complex<float> operator""if(unsigned long long); } } }

29.4.3 Class template complex [complex]

namespace std { template<class T> class complex { public: using value_type = T; constexpr complex(const T& re = T(), const T& im = T()); constexpr complex(const complex&) = default; template<class X> constexpr explicit(see below) complex(const complex<X>&); constexpr T real() const; constexpr void real(T); constexpr T imag() const; constexpr void imag(T); constexpr complex& operator= (const T&); constexpr complex& operator+=(const T&); constexpr complex& operator-=(const T&); constexpr complex& operator*=(const T&); constexpr complex& operator/=(const T&); constexpr complex& operator=(const complex&); template<class X> constexpr complex& operator= (const complex<X>&); template<class X> constexpr complex& operator+=(const complex<X>&); template<class X> constexpr complex& operator-=(const complex<X>&); template<class X> constexpr complex& operator*=(const complex<X>&); template<class X> constexpr complex& operator/=(const complex<X>&); }; }
The class complex describes an object that can store the Cartesian components, real() and imag(), of a complex number.

29.4.4 Member functions [complex.members]

constexpr complex(const T& re = T(), const T& im = T());
Postconditions: real() == re && imag() == im is true.
template<class X> constexpr explicit(see below) complex(const complex<X>& other);
Effects: Initializes the real part with other.real() and the imaginary part with other.imag().
Remarks: The expression inside explicit evaluates to false if and only if the floating-point conversion rank of T is greater than or equal to the floating-point conversion rank of X.
constexpr T real() const;
Returns: The value of the real component.
constexpr void real(T val);
Effects: Assigns val to the real component.
constexpr T imag() const;
Returns: The value of the imaginary component.
constexpr void imag(T val);
Effects: Assigns val to the imaginary component.

29.4.5 Member operators [complex.member.ops]

constexpr complex& operator+=(const T& rhs);
Effects: Adds the scalar value rhs to the real part of the complex value *this and stores the result in the real part of *this, leaving the imaginary part unchanged.
Returns: *this.
constexpr complex& operator-=(const T& rhs);
Effects: Subtracts the scalar value rhs from the real part of the complex value *this and stores the result in the real part of *this, leaving the imaginary part unchanged.
Returns: *this.
constexpr complex& operator*=(const T& rhs);
Effects: Multiplies the scalar value rhs by the complex value *this and stores the result in *this.
Returns: *this.
constexpr complex& operator/=(const T& rhs);
Effects: Divides the scalar value rhs into the complex value *this and stores the result in *this.
Returns: *this.
template<class X> constexpr complex& operator=(const complex<X>& rhs);
Effects: Assigns the value rhs.real() to the real part and the value rhs.imag() to the imaginary part of the complex value *this.
Returns: *this.
template<class X> constexpr complex& operator+=(const complex<X>& rhs);
Effects: Adds the complex value rhs to the complex value *this and stores the sum in *this.
Returns: *this.
template<class X> constexpr complex& operator-=(const complex<X>& rhs);
Effects: Subtracts the complex value rhs from the complex value *this and stores the difference in *this.
Returns: *this.
template<class X> constexpr complex& operator*=(const complex<X>& rhs);
Effects: Multiplies the complex value rhs by the complex value *this and stores the product in *this.
Returns: *this.
template<class X> constexpr complex& operator/=(const complex<X>& rhs);
Effects: Divides the complex value rhs into the complex value *this and stores the quotient in *this.
Returns: *this.

29.4.6 Non-member operations [complex.ops]

template<class T> constexpr complex<T> operator+(const complex<T>& lhs);
Returns: complex<T>(lhs).
template<class T> constexpr complex<T> operator+(const complex<T>& lhs, const complex<T>& rhs); template<class T> constexpr complex<T> operator+(const complex<T>& lhs, const T& rhs); template<class T> constexpr complex<T> operator+(const T& lhs, const complex<T>& rhs);
Returns: complex<T>(lhs) += rhs.
template<class T> constexpr complex<T> operator-(const complex<T>& lhs);
Returns: complex<T>(-lhs.real(),-lhs.imag()).
template<class T> constexpr complex<T> operator-(const complex<T>& lhs, const complex<T>& rhs); template<class T> constexpr complex<T> operator-(const complex<T>& lhs, const T& rhs); template<class T> constexpr complex<T> operator-(const T& lhs, const complex<T>& rhs);
Returns: complex<T>(lhs) -= rhs.
template<class T> constexpr complex<T> operator*(const complex<T>& lhs, const complex<T>& rhs); template<class T> constexpr complex<T> operator*(const complex<T>& lhs, const T& rhs); template<class T> constexpr complex<T> operator*(const T& lhs, const complex<T>& rhs);
Returns: complex<T>(lhs) *= rhs.
template<class T> constexpr complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs); template<class T> constexpr complex<T> operator/(const complex<T>& lhs, const T& rhs); template<class T> constexpr complex<T> operator/(const T& lhs, const complex<T>& rhs);
Returns: complex<T>(lhs) /= rhs.
template<class T> constexpr bool operator==(const complex<T>& lhs, const complex<T>& rhs); template<class T> constexpr bool operator==(const complex<T>& lhs, const T& rhs);
Returns: lhs.real() == rhs.real() && lhs.imag() == rhs.imag().
Remarks: The imaginary part is assumed to be T(), or 0.0, for the T arguments.
template<class T, class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, complex<T>& x);
Preconditions: The input values are convertible to T.
Effects: Extracts a complex number x of the form: u, (u), or (u,v), where u is the real part and v is the imaginary part ([istream.formatted]).
If bad input is encountered, calls is.setstate(ios_base​::​failbit) (which may throw ios_base​::​​failure ([iostate.flags])).
Returns: is.
Remarks: This extraction is performed as a series of simpler extractions.
Therefore, the skipping of whitespace is specified to be the same for each of the simpler extractions.
template<class T, class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& o, const complex<T>& x);
Effects: Inserts the complex number x onto the stream o as if it were implemented as follows: basic_ostringstream<charT, traits> s; s.flags(o.flags()); s.imbue(o.getloc()); s.precision(o.precision()); s << '(' << x.real() << ',' << x.imag() << ')'; return o << s.str();
[Note 1: 
In a locale in which comma is used as a decimal point character, the use of comma as a field separator can be ambiguous.
Inserting showpoint into the output stream forces all outputs to show an explicit decimal point character; as a result, all inserted sequences of complex numbers can be extracted unambiguously.
— end note]

29.4.7 Value operations [complex.value.ops]

template<class T> constexpr T real(const complex<T>& x);
Returns: x.real().
template<class T> constexpr T imag(const complex<T>& x);
Returns: x.imag().
template<class T> constexpr T abs(const complex<T>& x);
Returns: The magnitude of x.
template<class T> constexpr T arg(const complex<T>& x);
Returns: The phase angle of x, or atan2(imag(x), real(x)).
template<class T> constexpr T norm(const complex<T>& x);
Returns: The squared magnitude of x.
template<class T> constexpr complex<T> conj(const complex<T>& x);
Returns: The complex conjugate of x.
template<class T> constexpr complex<T> proj(const complex<T>& x);
Returns: The projection of x onto the Riemann sphere.
Remarks: Behaves the same as the C function cproj.
See also: ISO/IEC 9899:2018, 7.3.9.5
template<class T> constexpr complex<T> polar(const T& rho, const T& theta = T());
Preconditions: rho is non-negative and non-NaN.
theta is finite.
Returns: The complex value corresponding to a complex number whose magnitude is rho and whose phase angle is theta.

29.4.8 Transcendentals [complex.transcendentals]

template<class T> constexpr complex<T> acos(const complex<T>& x);
Returns: The complex arc cosine of x.
Remarks: Behaves the same as the C function cacos.
See also: ISO/IEC 9899:2018, 7.3.5.1
template<class T> constexpr complex<T> asin(const complex<T>& x);
Returns: The complex arc sine of x.
Remarks: Behaves the same as the C function casin.
See also: ISO/IEC 9899:2018, 7.3.5.2
template<class T> constexpr complex<T> atan(const complex<T>& x);
Returns: The complex arc tangent of x.
Remarks: Behaves the same as the C function catan.
See also: ISO/IEC 9899:2018, 7.3.5.3
template<class T> constexpr complex<T> acosh(const complex<T>& x);
Returns: The complex arc hyperbolic cosine of x.
Remarks: Behaves the same as the C function cacosh.
See also: ISO/IEC 9899:2018, 7.3.6.1
template<class T> constexpr complex<T> asinh(const complex<T>& x);
Returns: The complex arc hyperbolic sine of x.
Remarks: Behaves the same as the C function casinh.
See also: ISO/IEC 9899:2018, 7.3.6.2
template<class T> constexpr complex<T> atanh(const complex<T>& x);
Returns: The complex arc hyperbolic tangent of x.
Remarks: Behaves the same as the C function catanh.
See also: ISO/IEC 9899:2018, 7.3.6.3
template<class T> constexpr complex<T> cos(const complex<T>& x);
Returns: The complex cosine of x.
template<class T> constexpr complex<T> cosh(const complex<T>& x);
Returns: The complex hyperbolic cosine of x.
template<class T> constexpr complex<T> exp(const complex<T>& x);
Returns: The complex base-e exponential of x.
template<class T> constexpr complex<T> log(const complex<T>& x);
Returns: The complex natural (base-e) logarithm of x.
For all x, imag(log(x)) lies in the interval [, π].
[Note 1: 
The semantics of this function are intended to be the same in C++ as they are for clog in C.
— end note]
Remarks: The branch cuts are along the negative real axis.
template<class T> constexpr complex<T> log10(const complex<T>& x);
Returns: The complex common (base-10) logarithm of x, defined as log(x) / log(10).
Remarks: The branch cuts are along the negative real axis.
template<class T> constexpr complex<T> pow(const complex<T>& x, const complex<T>& y); template<class T> constexpr complex<T> pow(const complex<T>& x, const T& y); template<class T> constexpr complex<T> pow(const T& x, const complex<T>& y);
Returns: The complex power of base x raised to the power, defined as exp(y * log(x)).
The value returned for pow(0, 0) is implementation-defined.
Remarks: The branch cuts are along the negative real axis.
template<class T> constexpr complex<T> sin(const complex<T>& x);
Returns: The complex sine of x.
template<class T> constexpr complex<T> sinh(const complex<T>& x);
Returns: The complex hyperbolic sine of x.
template<class T> constexpr complex<T> sqrt(const complex<T>& x);
Returns: The complex square root of x, in the range of the right half-plane.
[Note 2: 
The semantics of this function are intended to be the same in C++ as they are for csqrt in C.
— end note]
Remarks: The branch cuts are along the negative real axis.
template<class T> constexpr complex<T> tan(const complex<T>& x);
Returns: The complex tangent of x.
template<class T> constexpr complex<T> tanh(const complex<T>& x);
Returns: The complex hyperbolic tangent of x.

29.4.9 Tuple interface [complex.tuple]

template<class T> struct tuple_size<complex<T>> : integral_constant<size_t, 2> {}; template<size_t I, class T> struct tuple_element<I, complex<T>> { using type = T; };
Mandates: I < 2 is true.
template<size_t I, class T> constexpr T& get(complex<T>& z) noexcept; template<size_t I, class T> constexpr T&& get(complex<T>&& z) noexcept; template<size_t I, class T> constexpr const T& get(const complex<T>& z) noexcept; template<size_t I, class T> constexpr const T&& get(const complex<T>&& z) noexcept;
Mandates: I < 2 is true.
Returns: A reference to the real part of z if I == 0 is true, otherwise a reference to the imaginary part of z.

29.4.10 Additional overloads [cmplx.over]

The following function templates have additional constexpr overloads: arg norm conj proj imag real
The additional constexpr overloads are sufficient to ensure:
  • If the argument has a floating-point type T, then it is effectively cast to complex<T>.
  • Otherwise, if the argument has integer type, then it is effectively cast to complex<double>.
Function template pow has additional constexpr overloads sufficient to ensure, for a call with one argument of type complex<T1> and the other argument of type T2 or complex<T2>, both arguments are effectively cast to complex<common_type_t<T1, T2>>.
If common_type_t<T1, T2> is not well-formed, then the program is ill-formed.

29.4.11 Suffixes for complex number literals [complex.literals]

This subclause describes literal suffixes for constructing complex number literals.
The suffixes i, il, and if create complex numbers of the types complex<double>, complex<long double>, and complex<float> respectively, with their imaginary part denoted by the given literal number and the real part being zero.
constexpr complex<long double> operator""il(long double d); constexpr complex<long double> operator""il(unsigned long long d);
Returns: complex<long double>{0.0L, static_cast<long double>(d)}.
constexpr complex<double> operator""i(long double d); constexpr complex<double> operator""i(unsigned long long d);
Returns: complex<double>{0.0, static_cast<double>(d)}.
constexpr complex<float> operator""if(long double d); constexpr complex<float> operator""if(unsigned long long d);
Returns: complex<float>{0.0f, static_cast<float>(d)}.

29.5 Random number generation [rand]

29.5.1 General [rand.general]

Subclause [rand] defines a facility for generating (pseudo-)random numbers.
In addition to a few utilities, four categories of entities are described: uniform random bit generators, random number engines, random number engine adaptors, and random number distributions.
These categorizations are applicable to types that meet the corresponding requirements, to objects instantiated from such types, and to templates producing such types when instantiated.
[Note 1: 
These entities are specified in such a way as to permit the binding of any uniform random bit generator object e as the argument to any random number distribution object d, thus producing a zero-argument function object such as given by bind(d,e).
— end note]
Each of the entities specified in [rand] has an associated arithmetic type ([basic.fundamental]) identified as result_type.
With T as the result_type thus associated with such an entity, that entity is characterized:
If integer-valued, an entity may optionally be further characterized as signed or unsigned, according to numeric_limits<T>​::​is_signed.
Unless otherwise specified, all descriptions of calculations in [rand] use mathematical real numbers.
Throughout [rand], the operators bitand, bitor, and xor denote the respective conventional bitwise operations.
Further:
  • the operator rshift denotes a bitwise right shift with zero-valued bits appearing in the high bits of the result, and
  • the operator denotes a bitwise left shift with zero-valued bits appearing in the low bits of the result, and whose result is always taken modulo .

29.5.2 Header <random> synopsis [rand.synopsis]

#include <initializer_list> // see [initializer.list.syn] namespace std { // [rand.req.urng], uniform random bit generator requirements template<class G> concept uniform_random_bit_generator = see below; // [rand.eng.lcong], class template linear_congruential_engine template<class UIntType, UIntType a, UIntType c, UIntType m> class linear_congruential_engine; // [rand.eng.mers], class template mersenne_twister_engine template<class UIntType, size_t w, size_t n, size_t m, size_t r, UIntType a, size_t u, UIntType d, size_t s, UIntType b, size_t t, UIntType c, size_t l, UIntType f> class mersenne_twister_engine; // [rand.eng.sub], class template subtract_with_carry_engine template<class UIntType, size_t w, size_t s, size_t r> class subtract_with_carry_engine; // [rand.adapt.disc], class template discard_block_engine template<class Engine, size_t p, size_t r> class discard_block_engine; // [rand.adapt.ibits], class template independent_bits_engine template<class Engine, size_t w, class UIntType> class independent_bits_engine; // [rand.adapt.shuf], class template shuffle_order_engine template<class Engine, size_t k> class shuffle_order_engine; // [rand.eng.philox], class template philox_engine template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts> class philox_engine; // [rand.predef], engines and engine adaptors with predefined parameters using minstd_rand0 = see below; using minstd_rand = see below; using mt19937 = see below; using mt19937_64 = see below; using ranlux24_base = see below; using ranlux48_base = see below; using ranlux24 = see below; using ranlux48 = see below; using knuth_b = see below; using philox4x32 = see below; using philox4x64 = see below; using default_random_engine = see below; // [rand.device], class random_device class random_device; // [rand.util.seedseq], class seed_seq class seed_seq; // [rand.util.canonical], function template generate_canonical template<class RealType, size_t digits, class URBG> RealType generate_canonical(URBG& g); namespace ranges { // [alg.rand.generate], generate_random template<class R, class G> requires output_range<R, invoke_result_t<G&>> && uniform_random_bit_generator<remove_cvref_t<G>> constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g); template<class G, output_iterator<invoke_result_t<G&>> O, sentinel_for<O> S> requires uniform_random_bit_generator<remove_cvref_t<G>> constexpr O generate_random(O first, S last, G&& g); template<class R, class G, class D> requires output_range<R, invoke_result_t<D&, G&>> && invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>> && is_arithmetic_v<invoke_result_t<D&, G&>> constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g, D&& d); template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O, sentinel_for<O> S> requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>> && is_arithmetic_v<invoke_result_t<D&, G&>> constexpr O generate_random(O first, S last, G&& g, D&& d); } // [rand.dist.uni.int], class template uniform_int_distribution template<class IntType = int> class uniform_int_distribution; // [rand.dist.uni.real], class template uniform_real_distribution template<class RealType = double> class uniform_real_distribution; // [rand.dist.bern.bernoulli], class bernoulli_distribution class bernoulli_distribution; // [rand.dist.bern.bin], class template binomial_distribution template<class IntType = int> class binomial_distribution; // [rand.dist.bern.geo], class template geometric_distribution template<class IntType = int> class geometric_distribution; // [rand.dist.bern.negbin], class template negative_binomial_distribution template<class IntType = int> class negative_binomial_distribution; // [rand.dist.pois.poisson], class template poisson_distribution template<class IntType = int> class poisson_distribution; // [rand.dist.pois.exp], class template exponential_distribution template<class RealType = double> class exponential_distribution; // [rand.dist.pois.gamma], class template gamma_distribution template<class RealType = double> class gamma_distribution; // [rand.dist.pois.weibull], class template weibull_distribution template<class RealType = double> class weibull_distribution; // [rand.dist.pois.extreme], class template extreme_value_distribution template<class RealType = double> class extreme_value_distribution; // [rand.dist.norm.normal], class template normal_distribution template<class RealType = double> class normal_distribution; // [rand.dist.norm.lognormal], class template lognormal_distribution template<class RealType = double> class lognormal_distribution; // [rand.dist.norm.chisq], class template chi_squared_distribution template<class RealType = double> class chi_squared_distribution; // [rand.dist.norm.cauchy], class template cauchy_distribution template<class RealType = double> class cauchy_distribution; // [rand.dist.norm.f], class template fisher_f_distribution template<class RealType = double> class fisher_f_distribution; // [rand.dist.norm.t], class template student_t_distribution template<class RealType = double> class student_t_distribution; // [rand.dist.samp.discrete], class template discrete_distribution template<class IntType = int> class discrete_distribution; // [rand.dist.samp.pconst], class template piecewise_constant_distribution template<class RealType = double> class piecewise_constant_distribution; // [rand.dist.samp.plinear], class template piecewise_linear_distribution template<class RealType = double> class piecewise_linear_distribution; }

29.5.3 Requirements [rand.req]

29.5.3.1 General requirements [rand.req.genl]

Throughout [rand], the effect of instantiating a template:
  • that has a template type parameter named Sseq is undefined unless the corresponding template argument is cv-unqualified and meets the requirements of seed sequence.
  • that has a template type parameter named URBG is undefined unless the corresponding template argument is cv-unqualified and meets the requirements of uniform random bit generator.
  • that has a template type parameter named Engine is undefined unless the corresponding template argument is cv-unqualified and meets the requirements of random number engine.
  • that has a template type parameter named RealType is undefined unless the corresponding template argument is cv-unqualified and is one of float, double, or long double.
  • that has a template type parameter named IntType is undefined unless the corresponding template argument is cv-unqualified and is one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long.
  • that has a template type parameter named UIntType is undefined unless the corresponding template argument is cv-unqualified and is one of unsigned short, unsigned int, unsigned long, or unsigned long long.
Throughout [rand], phrases of the form “x is an iterator of a specific kind” shall be interpreted as equivalent to the more formal requirement that “x is a value of a type meeting the requirements of the specified iterator type”.
Throughout [rand], any constructor that can be called with a single argument and that meets a requirement specified in this subclause shall be declared explicit.

29.5.3.2 Seed sequence requirements [rand.req.seedseq]

A seed sequence is an object that consumes a sequence of integer-valued data and produces a requested number of unsigned integer values i, , based on the consumed data.
[Note 1: 
Such an object provides a mechanism to avoid replication of streams of random variates.
This can be useful, for example, in applications requiring large numbers of random number engines.
— end note]
A class S meets the requirements of a seed sequence if the expressions shown in Table 121 are valid and have the indicated semantics, and if S also meets all other requirements of [rand.req.seedseq].
In Table 121 and throughout this subclause:
  • T is the type named by S's associated result_type;
  • q is a value of type S and r is a value of type S or const S;
  • ib and ie are input iterators with an unsigned integer value_type of at least 32 bits;
  • rb and re are mutable random access iterators with an unsigned integer value_type of at least 32 bits;
  • ob is an output iterator; and
  • il is a value of type initializer_list<T>.
Table 121 — Seed sequence requirements [tab:rand.req.seedseq]
Expression
Return type
Pre/post-condition
Complexity
S​::​result_type
T
T is an unsigned integer type of at least 32 bits.
S()
Creates a seed sequence with the same initial state as all other default-constructed seed sequences of type S.
constant
S(ib,ie)
Creates a seed sequence having internal state that depends on some or all of the bits of the supplied sequence [ib,ie).
S(il)
Same as S(il.begin(), il.end()).
same as S(il.begin(), il.end())
q.generate(rb,re)
void
Does nothing if rb == re.
Otherwise, fills the supplied sequence [rb,re) with 32-bit quantities that depend on the sequence supplied to the constructor and possibly also depend on the history of generate's previous invocations.
r.size()
size_t
The number of 32-bit units that would be copied by a call to r.param.
constant
r.param(ob)
void
Copies to the given destination a sequence of 32-bit units that can be provided to the constructor of a second object of type S, and that would reproduce in that second object a state indistinguishable from the state of the first object.

29.5.3.3 Uniform random bit generator requirements [rand.req.urng]

A uniform random bit generator g of type G is a function object returning unsigned integer values such that each value in the range of possible results has (ideally) equal probability of being returned.
[Note 1: 
The degree to which g's results approximate the ideal is often determined statistically.
— end note]
template<class G> concept uniform_random_bit_generator = invocable<G&> && unsigned_integral<invoke_result_t<G&>> && requires { { G::min() } -> same_as<invoke_result_t<G&>>; { G::max() } -> same_as<invoke_result_t<G&>>; requires bool_constant<(G::min() < G::max())>::value; };
Let g be an object of type G.
G models uniform_random_bit_generator only if
  • G​::​min() <= g(),
  • g() <= G​::​max(), and
  • g() has amortized constant complexity.
A class G meets the uniform random bit generator requirements if G models uniform_random_bit_generator, invoke_result_t<G&> is an unsigned integer type ([basic.fundamental]), and G provides a nested typedef-name result_type that denotes the same type as invoke_result_t<G&>.

29.5.3.4 Random number engine requirements [rand.req.eng]

A random number engine (commonly shortened to engine) e of type E is a uniform random bit generator that additionally meets the requirements (e.g., for seeding and for input/output) specified in this subclause.
At any given time, e has a state e for some integer i  ≥ 0.
Upon construction, e has an initial state e.
An engine's state may be established via a constructor, a seed function, assignment, or a suitable operator>>.
E's specification shall define:
A class E that meets the requirements of a uniform random bit generator also meets the requirements of a random number engine if the expressions shown in Table 122 are valid and have the indicated semantics, and if E also meets all other requirements of [rand.req.eng].
In Table 122 and throughout this subclause:
  • T is the type named by E's associated result_type;
  • e is a value of E, v is an lvalue of E, x and y are (possibly const) values of E;
  • s is a value of T;
  • q is an lvalue meeting the requirements of a seed sequence;
  • z is a value of type unsigned long long;
  • os is an lvalue of the type of some class template specialization basic_ostream<charT, traits>; and
  • is is an lvalue of the type of some class template specialization basic_istream<charT, traits>;
where charT and traits are constrained according to [strings] and [input.output].
Table 122 — Random number engine requirements [tab:rand.req.eng]
Expression
Return type
Pre/post-condition
Complexity
E()
Creates an engine with the same initial state as all other default-constructed engines of type E.
E(x)
Creates an engine that compares equal to x.
E(s)
Creates an engine with initial state determined by s.
E(q)244
Creates an engine with an initial state that depends on a sequence produced by one call to q.generate.
same as complexity of q.generate called on a sequence whose length is size of state
e.seed()
void
Postconditions: e == E().
same as E()
e.seed(s)
void
Postconditions: e == E(s).
same as E(s)
e.seed(q)
void
Postconditions: e == E(q).
same as E(q)
e()
T
Advances e's state e to e e) and returns GA(e).
e.discard(z)245
void
Advances e's state e to by any means equivalent to z consecutive calls e().
no worse than the complexity of z consecutive calls e()
x == y
bool
This operator is an equivalence relation.
With and as the infinite sequences of values that would be generated by repeated future calls to x() and y(), respectively, returns true if ; else returns false.
x != y
bool
!(x == y).
os << x
reference to the type of os
With os.fmtflags set to ios_base​::​dec|ios_base​::​left and the fill character set to the space character, writes to os the textual representation of x's current state.
In the output, adjacent numbers are separated by one or more space characters.
Postconditions: The os.fmtflags and fill character are unchanged.
is >> v
reference to the type of is
With is.fmtflags set to ios_base​::​dec, sets v's state as determined by reading its textual representation from is.
If bad input is encountered, ensures that v's state is unchanged by the operation and calls is.setstate(ios_base​::​failbit) (which may throw ios_base​::​failure ([iostate.flags])).
If a textual representation written via os << x was subsequently read via is >> v, then x == v provided that there have been no intervening invocations of x or of v.
Preconditions: is provides a textual representation that was previously written using an output stream whose imbued locale was the same as that of is, and whose type's template specialization arguments charT and traits were respectively the same as those of is.
Postconditions: The is.fmtflags are unchanged.
E shall meet the Cpp17CopyConstructible (Table 32) and Cpp17CopyAssignable (Table 34) requirements.
These operations shall each be of complexity no worse than .
244)244)
This constructor (as well as the subsequent corresponding seed() function) can be particularly useful to applications requiring a large number of independent random sequences.
245)245)
This operation is common in user code, and can often be implemented in an engine-specific manner so as to provide significant performance improvements over an equivalent naive loop that makes z consecutive calls e().

29.5.3.5 Random number engine adaptor requirements [rand.req.adapt]

A random number engine adaptor (commonly shortened to adaptor) a of type A is a random number engine that takes values produced by some other random number engine, and applies an algorithm to those values in order to deliver a sequence of values with different randomness properties.
An engine b of type B adapted in this way is termed a base engine in this context.
The expression a.base() shall be valid and shall return a const reference to a's base engine.
The requirements of a random number engine type shall be interpreted as follows with respect to a random number engine adaptor type.
A::A();
Effects: The base engine is initialized as if by its default constructor.
bool operator==(const A& a1, const A& a2);
Returns: true if a1's base engine is equal to a2's base engine.
Otherwise returns false.
A::A(result_type s);
Effects: The base engine is initialized with s.
template<class Sseq> A::A(Sseq& q);
Effects: The base engine is initialized with q.
void seed();
Effects: With b as the base engine, invokes b.seed().
void seed(result_type s);
Effects: With b as the base engine, invokes b.seed(s).
template<class Sseq> void seed(Sseq& q);
Effects: With b as the base engine, invokes b.seed(q).
A shall also meet the following additional requirements:
  • The complexity of each function shall not exceed the complexity of the corresponding function applied to the base engine.
  • The state of A shall include the state of its base engine.
    The size of A's state shall be no less than the size of the base engine.
  • Copying A's state (e.g., during copy construction or copy assignment) shall include copying the state of the base engine of A.
  • The textual representation of A shall include the textual representation of its base engine.

29.5.3.6 Random number distribution requirements [rand.req.dist]

A random number distribution (commonly shortened to distribution) d of type D is a function object returning values that are distributed according to an associated mathematical probability density function p(z) or according to an associated discrete probability function .
A distribution's specification identifies its associated probability function p(z) or .
An associated probability function is typically expressed using certain externally-supplied quantities known as the parameters of the distribution.
Such distribution parameters are identified in this context by writing, for example, p(z|a,b) or , to name specific parameters, or by writing, for example, p(z|{p}) or , to denote a distribution's parameters p taken as a whole.
A class D meets the requirements of a random number distribution if the expressions shown in Table 123 are valid and have the indicated semantics, and if D and its associated types also meet all other requirements of [rand.req.dist].
In Table 123 and throughout this subclause,
  • T is the type named by D's associated result_type;
  • P is the type named by D's associated param_type;
  • d is a value of D, and x and y are (possibly const) values of D;
  • glb and lub are values of T respectively corresponding to the greatest lower bound and the least upper bound on the values potentially returned by d's operator(), as determined by the current values of d's parameters;
  • p is a (possibly const) value of P;
  • g, g1, and g2 are lvalues of a type meeting the requirements of a uniform random bit generator;
  • os is an lvalue of the type of some class template specialization basic_ostream<charT, traits>; and
  • is is an lvalue of the type of some class template specialization basic_istream<charT, traits>;
where charT and traits are constrained according to [strings] and [input.output].
Table 123 — Random number distribution requirements [tab:rand.req.dist]
Expression
Return type
Pre/post-condition
Complexity
D​::​result_type
T
D​::​param_type
P
D()
Creates a distribution whose behavior is indistinguishable from that of any other newly default-constructed distribution of type D.
constant
D(p)
Creates a distribution whose behavior is indistinguishable from that of a distribution newly constructed directly from the values used to construct p.
same as p's construction
d.reset()
void
Subsequent uses of d do not depend on values produced by any engine prior to invoking reset.
constant
x.param()
P
Returns a value p such that D(p).param() == p.
no worse than the complexity of D(p)
d.param(p)
void
Postconditions: d.param() == p.
no worse than the complexity of D(p)
d(g)
T
With , the sequence of numbers returned by successive invocations with the same object g is randomly distributed according to the associated p(z|{p}) or function.
amortized constant number of invocations of g
d(g,p)
T
The sequence of numbers returned by successive invocations with the same objects g and p is randomly distributed according to the associated p(z|{p}) or function.
amortized constant number of invocations of g
x.min()
T
Returns glb.
constant
x.max()
T
Returns lub.
constant
x == y
bool
This operator is an equivalence relation.
Returns true if x.param() == y.param() and , where and are the infinite sequences of values that would be generated, respectively, by repeated future calls to x(g1) and y(g2) whenever g1 == g2.
Otherwise returns false.
constant
x != y
bool
!(x == y).
same as x == y.
os << x
reference to the type of os
Writes to os a textual representation for the parameters and the additional internal data of x.
Postconditions: The os.fmtflags and fill character are unchanged.
is >> d
reference to the type of is
Restores from is the parameters and additional internal data of the lvalue d.
If bad input is encountered, ensures that d is unchanged by the operation and calls is.setstate(ios_base​::​failbit) (which may throw ios_base​::​failure ([iostate.flags])).
Preconditions: is provides a textual representation that was previously written using an os whose imbued locale and whose type's template specialization arguments charT and traits were the same as those of is.
Postconditions: The is.fmtflags are unchanged.
D shall meet the Cpp17CopyConstructible (Table 32) and Cpp17CopyAssignable (Table 34) requirements.
The sequence of numbers produced by repeated invocations of d(g) shall be independent of any invocation of os << d or of any const member function of D between any of the invocations of d(g).
If a textual representation is written using os << x and that representation is restored into the same or a different object y of the same type using is >> y, repeated invocations of y(g) shall produce the same sequence of numbers as would repeated invocations of x(g).
It is unspecified whether D​::​param_type is declared as a (nested) class or via a typedef.
In [rand], declarations of D​::​param_type are in the form of typedefs for convenience of exposition only.
P shall meet the Cpp17CopyConstructible (Table 32), Cpp17CopyAssignable (Table 34), and Cpp17EqualityComparable (Table 28) requirements.
For each of the constructors of D taking arguments corresponding to parameters of the distribution, P shall have a corresponding constructor subject to the same requirements and taking arguments identical in number, type, and default values.
Moreover, for each of the member functions of D that return values corresponding to parameters of the distribution, P shall have a corresponding member function with the identical name, type, and semantics.
P shall have a declaration of the form using distribution_type = D;

29.5.4 Random number engine class templates [rand.eng]

29.5.4.1 General [rand.eng.general]

Each type instantiated from a class template specified in [rand.eng] meets the requirements of a random number engine type.
Except where specified otherwise, the complexity of each function specified in [rand.eng] is constant.
Except where specified otherwise, no function described in [rand.eng] throws an exception.
Every function described in [rand.eng] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type seed_seq throws what and when the invocation of q.generate throws.
Descriptions are provided in [rand.eng] only for engine operations that are not described in [rand.req.eng] or for operations where there is additional semantic information.
In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.
Each template specified in [rand.eng] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold.
A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.
For every random number engine and for every random number engine adaptor X defined in [rand.eng] and in [rand.adapt]:
  • if the constructor template<class Sseq> explicit X(Sseq& q); is called with a type Sseq that does not qualify as a seed sequence, then this constructor shall not participate in overload resolution;
  • if the member function template<class Sseq> void seed(Sseq& q); is called with a type Sseq that does not qualify as a seed sequence, then this function shall not participate in overload resolution.
The extent to which an implementation determines that a type cannot be a seed sequence is unspecified, except that as a minimum a type shall not qualify as a seed sequence if it is implicitly convertible to X​::​result_type.

29.5.4.2 Class template linear_congruential_engine [rand.eng.lcong]

A linear_congruential_engine random number engine produces unsigned integer random numbers.
The state x of a linear_congruential_engine object x is of size 1 and consists of a single integer.
The transition algorithm is a modular linear function of the form ; the generation algorithm is .
namespace std { template<class UIntType, UIntType a, UIntType c, UIntType m> class linear_congruential_engine { public: // types using result_type = UIntType; // engine characteristics static constexpr result_type multiplier = a; static constexpr result_type increment = c; static constexpr result_type modulus = m; static constexpr result_type min() { return c == 0u ? 1u: 0u; } static constexpr result_type max() { return m - 1u; } static constexpr result_type default_seed = 1u; // constructors and seeding functions linear_congruential_engine() : linear_congruential_engine(default_seed) {} explicit linear_congruential_engine(result_type s); template<class Sseq> explicit linear_congruential_engine(Sseq& q); void seed(result_type s = default_seed); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const linear_congruential_engine& x, const linear_congruential_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const linear_congruential_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, linear_congruential_engine& x); }; }
If the template parameter m is 0, the modulus m used throughout [rand.eng.lcong] is numeric_limits<result_type>​::​max() plus 1.
[Note 1: 
m need not be representable as a value of type result_type.
— end note]
If the template parameter m is not 0, the following relations shall hold: a < m and c < m.
The textual representation consists of the value of x.
explicit linear_congruential_engine(result_type s);
Effects: If is 0 and is 0, sets the engine's state to 1, otherwise sets the engine's state to .
template<class Sseq> explicit linear_congruential_engine(Sseq& q);
Effects: With and a an array (or equivalent) of length , invokes q.generate(, ) and then computes .
If is 0 and S is 0, sets the engine's state to 1, else sets the engine's state to S.

29.5.4.3 Class template mersenne_twister_engine [rand.eng.mers]

A mersenne_twister_engine random number engine246 produces unsigned integer random numbers in the closed interval .
The state x of a mersenne_twister_engine object x is of size n and consists of a sequence X of n values of the type delivered by x; all subscripts applied to X are to be taken modulo n.
The transition algorithm employs a twisted generalized feedback shift register defined by shift values n and m, a twist value r, and a conditional xor-mask a.
To improve the uniformity of the result, the bits of the raw shift register are additionally tempered (i.e., scrambled) according to a bit-scrambling matrix defined by values u, d, s, b, t, c, and .
The state transition is performed as follows:
  • Concatenate the upper bits of with the lower r bits of to obtain an unsigned integer value Y.
  • With , set to .
The sequence X is initialized with the help of an initialization multiplier f.
The generation algorithm determines the unsigned integer values as follows, then delivers as its result:
  • Let .
  • Let .
  • Let .
  • Let .
namespace std { template<class UIntType, size_t w, size_t n, size_t m, size_t r, UIntType a, size_t u, UIntType d, size_t s, UIntType b, size_t t, UIntType c, size_t l, UIntType f> class mersenne_twister_engine { public: // types using result_type = UIntType; // engine characteristics static constexpr size_t word_size = w; static constexpr size_t state_size = n; static constexpr size_t shift_size = m; static constexpr size_t mask_bits = r; static constexpr UIntType xor_mask = a; static constexpr size_t tempering_u = u; static constexpr UIntType tempering_d = d; static constexpr size_t tempering_s = s; static constexpr UIntType tempering_b = b; static constexpr size_t tempering_t = t; static constexpr UIntType tempering_c = c; static constexpr size_t tempering_l = l; static constexpr UIntType initialization_multiplier = f; static constexpr result_type min() { return 0; } static constexpr result_type max() { return ; } static constexpr result_type default_seed = 5489u; // constructors and seeding functions mersenne_twister_engine() : mersenne_twister_engine(default_seed) {} explicit mersenne_twister_engine(result_type value); template<class Sseq> explicit mersenne_twister_engine(Sseq& q); void seed(result_type value = default_seed); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const mersenne_twister_engine& x, const mersenne_twister_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const mersenne_twister_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, mersenne_twister_engine& x); }; }
The following relations shall hold: 0 < m, m <= n, 2u < w, r <= w, u <= w, s <= w, t <= w, l <= w, w <= numeric_limits<UIntType>​::​digits, a <= (1u<<w) - 1u, b <= (1u<<w) - 1u, c <= (1u<<w) - 1u, d <= (1u<<w) - 1u, and f <= (1u<<w) - 1u.
The textual representation of x consists of the values of , in that order.
explicit mersenne_twister_engine(result_type value);
Effects: Sets to .
Then, iteratively for , sets to
Complexity: .
template<class Sseq> explicit mersenne_twister_engine(Sseq& q);
Effects: With and a an array (or equivalent) of length , invokes q.generate(, ) and then, iteratively for , sets to .
Finally, if the most significant bits of are zero, and if each of the other resulting is 0, changes to .
246)246)
The name of this engine refers, in part, to a property of its period: For properly-selected values of the parameters, the period is closely related to a large Mersenne prime number.

29.5.4.4 Class template subtract_with_carry_engine [rand.eng.sub]

A subtract_with_carry_engine random number engine produces unsigned integer random numbers.
The state x of a subtract_with_carry_engine object x is of size , and consists of a sequence X of r integer values ; all subscripts applied to X are to be taken modulo r.
The state x additionally consists of an integer c (known as the carry) whose value is either 0 or 1.
The state transition is performed as follows:
  • Let .
  • Set to .
    Set c to 1 if , otherwise set c to 0.
[Note 1: 
This algorithm corresponds to a modular linear function of the form , where b is of the form and .
— end note]
The generation algorithm is given by , where y is the value produced as a result of advancing the engine's state as described above.
namespace std { template<class UIntType, size_t w, size_t s, size_t r> class subtract_with_carry_engine { public: // types using result_type = UIntType; // engine characteristics static constexpr size_t word_size = w; static constexpr size_t short_lag = s; static constexpr size_t long_lag = r; static constexpr result_type min() { return 0; } static constexpr result_type max() { return ; } static constexpr uint_least32_t default_seed = 19780503u; // constructors and seeding functions subtract_with_carry_engine() : subtract_with_carry_engine(0u) {} explicit subtract_with_carry_engine(result_type value); template<class Sseq> explicit subtract_with_carry_engine(Sseq& q); void seed(result_type value = 0u); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const subtract_with_carry_engine& x, const subtract_with_carry_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const subtract_with_carry_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, subtract_with_carry_engine& x); }; }
The following relations shall hold: 0u < s, s < r, 0 < w, and w <= numeric_limits<UIntType>​::​digits.
The textual representation consists of the values of , in that order, followed by c.
explicit subtract_with_carry_engine(result_type value);
Effects: Sets the values of , in that order, as specified below.
If is then 0, sets c to 1; otherwise sets c to 0.
To set the values , first construct e, a linear_congruential_engine object, as if by the following definition: linear_congruential_engine<uint_least32_t, 40014u, 0u, 2147483563u> e( value == 0u ? default_seed : static_cast<uint_least32_t>(value % 2147483563u));
Then, to set each , obtain new values from successive invocations of e.
Set to .
Complexity: Exactly invocations of e.
template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
Effects: With and a an array (or equivalent) of length , invokes q.generate(, ) and then, iteratively for , sets to .
If is then 0, sets c to 1; otherwise sets c to 0.

29.5.4.5 Class template philox_engine [rand.eng.philox]

A philox_engine random number engine produces unsigned integer random numbers in the interval [0, m), where and the template parameter w defines the range of the produced numbers.
The state of a philox_engine object consists of a sequence X of n unsigned integer values of width w, a sequence K of values of result_type, a sequence Y of n values of result_type, and a scalar i, where
  • X is the interpretation of the unsigned integer counter value of bits,
  • K are keys, which are generated once from the seed (see constructors below) and remain constant unless the seed function ([rand.req.eng]) is invoked,
  • Y stores a batch of output values, and
  • i is an index for an element of the sequence Y.
The generation algorithm returns , the value stored in the element of Y after applying the transition algorithm.
The state transition is performed as if by the following algorithm: i = i + 1 if (i == n) { Y = Philox(K, X) // see below Z = Z + 1 i = 0 }
The Philox function maps the length- sequence K and the length-n sequence X into a length-n output sequence Y.
Philox applies an r-round substitution-permutation network to the values in X.
A single round of the generation algorithm performs the following steps:
  • The output sequence of the previous round (X in case of the first round) is permuted to obtain the intermediate state V: where and is defined in Table 124.
    Table 124 — Values for the word permutation [tab:rand.eng.philox.f]
    j
    0
    1
    2
    3
    n
    2
    0
    1
    4
    2
    1
    0
    3
    [Note 1: 
    For the sequence is not permuted.
    — end note]
  • The following computations are applied to the elements of the V sequence: where:
    • mullo(a, b, w) is the low half of the modular multiplication of a and b: ,
    • mulhi(a, b, w) is the high half of the modular multiplication of a and b: ,
    • is the index in the sequences,
    • is the index of the round,
    • is the round key for round q, ,
    • are the elements of the key sequence K,
    • is multipliers[k], and
    • is round_consts[k].
After r applications of the single-round function, Philox returns the sequence .
namespace std { template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts> class philox_engine { static constexpr size_t array-size = n / 2; // exposition only public: // types using result_type = UIntType; // engine characteristics static constexpr size_t word_size = w; static constexpr size_t word_count = n; static constexpr size_t round_count = r; static constexpr array<result_type, array-size> multipliers; static constexpr array<result_type, array-size> round_consts; static constexpr result_type min() { return 0; } static constexpr result_type max() { return m - 1; } static constexpr result_type default_seed = 20111115u; // constructors and seeding functions philox_engine() : philox_engine(default_seed) {} explicit philox_engine(result_type value); template<class Sseq> explicit philox_engine(Sseq& q); void seed(result_type value = default_seed); template<class Sseq> void seed(Sseq& q); void set_counter(const array<result_type, n>& counter); // equality operators friend bool operator==(const philox_engine& x, const philox_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const philox_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, philox_engine& x); }; }
Mandates:
  • sizeof...(consts) == n is true, and
  • n == 2 || n == 4 is true, and
  • 0 < r is true, and
  • 0 < w && w <= numeric_limits<UIntType>​::​digits is true.
The template parameter pack consts represents the and constants which are grouped as follows: .
The textual representation consists of the values of , in that order.
[Note 2: 
The stream extraction operator can reconstruct Y from K and X, as needed.
— end note]
explicit philox_engine(result_type value);
Effects: Sets the element of sequence K to .
All elements of sequences X and K (except ) are set to 0.
The value of i is set to .
template<class Sseq> explicit philox_engine(Sseq& q);
Effects: With and an array (or equivalent) a of length , invokes q.generate(a + 0, a + n / 2 * p) and then iteratively for , sets to .
All elements of sequence X are set to 0.
The value of i is set to .
void set_counter(const array<result_type, n>& c);
Effects: For sets to .
The value of i is set to .
[Note 3: 
The counter is the value Z introduced at the beginning of this subclause.
— end note]

29.5.5 Random number engine adaptor class templates [rand.adapt]

29.5.5.1 General [rand.adapt.general]

Each type instantiated from a class template specified in [rand.adapt] meets the requirements of a random number engine adaptor type.
Except where specified otherwise, the complexity of each function specified in [rand.adapt] is constant.
Except where specified otherwise, no function described in [rand.adapt] throws an exception.
Every function described in [rand.adapt] that has a function parameter q of type Sseq& for a template type parameter named Sseq that is different from type seed_seq throws what and when the invocation of q.generate throws.
Descriptions are provided in [rand.adapt] only for adaptor operations that are not described in subclause [rand.req.adapt] or for operations where there is additional semantic information.
In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.
Each template specified in [rand.adapt] requires one or more relationships, involving the value(s) of its non-type template parameter(s), to hold.
A program instantiating any of these templates is ill-formed if any such required relationship fails to hold.

29.5.5.2 Class template discard_block_engine [rand.adapt.disc]

A discard_block_engine random number engine adaptor produces random numbers selected from those produced by some base engine e.
The state x of a discard_block_engine engine adaptor object x consists of the state e of its base engine e and an additional integer n.
The size of the state is the size of e's state plus 1.
The transition algorithm discards all but values from each block of p  ≥ r values delivered by e.
The state transition is performed as follows: If n  ≥ r, advance the state of e from e to e and set n to 0.
In any case, then increment n and advance e's then-current state e to e.
The generation algorithm yields the value returned by the last invocation of e() while advancing e's state as described above.
namespace std { template<class Engine, size_t p, size_t r> class discard_block_engine { public: // types using result_type = typename Engine::result_type; // engine characteristics static constexpr size_t block_size = p; static constexpr size_t used_block = r; static constexpr result_type min() { return Engine::min(); } static constexpr result_type max() { return Engine::max(); } // constructors and seeding functions discard_block_engine(); explicit discard_block_engine(const Engine& e); explicit discard_block_engine(Engine&& e); explicit discard_block_engine(result_type s); template<class Sseq> explicit discard_block_engine(Sseq& q); void seed(); void seed(result_type s); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const discard_block_engine& x, const discard_block_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // property functions const Engine& base() const noexcept { return e; } // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const discard_block_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, discard_block_engine& x); private: Engine e; // exposition only size_t n; // exposition only }; }
The following relations shall hold: 0 < r and r <= p.
The textual representation consists of the textual representation of e followed by the value of n.
In addition to its behavior pursuant to subclause [rand.req.adapt], each constructor that is not a copy constructor sets n to 0.

29.5.5.3 Class template independent_bits_engine [rand.adapt.ibits]

An independent_bits_engine random number engine adaptor combines random numbers that are produced by some base engine e, so as to produce random numbers with a specified number of bits w.
The state x of an independent_bits_engine engine adaptor object x consists of the state e of its base engine e; the size of the state is the size of e's state.
The transition and generation algorithms are described in terms of the following integral constants:
  • Let and .
  • With n as determined below, let , , , and .
  • Let if and only if the relation holds as a result.
    Otherwise let .
[Note 1: 
The relation always holds.
— end note]
The transition algorithm is carried out by invoking e() as often as needed to obtain values less than and values less than .
The generation algorithm uses the values produced while advancing the state as described above to yield a quantity S obtained as if by the following algorithm: S = 0; for (k = 0; ; k += 1) { do u = e() - e.min(); while (); S = ; } for (k = ; k  ≠ n; k += 1) { do u = e() - e.min(); while (); S = ; }
namespace std { template<class Engine, size_t w, class UIntType> class independent_bits_engine { public: // types using result_type = UIntType; // engine characteristics static constexpr result_type min() { return 0; } static constexpr result_type max() { return ; } // constructors and seeding functions independent_bits_engine(); explicit independent_bits_engine(const Engine& e); explicit independent_bits_engine(Engine&& e); explicit independent_bits_engine(result_type s); template<class Sseq> explicit independent_bits_engine(Sseq& q); void seed(); void seed(result_type s); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const independent_bits_engine& x, const independent_bits_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // property functions const Engine& base() const noexcept { return e; } // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const independent_bits_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, independent_bits_engine& x); private: Engine e; // exposition only }; }
The following relations shall hold: 0 < w and w <= numeric_limits<result_type>​::​digits.
The textual representation consists of the textual representation of e.

29.5.5.4 Class template shuffle_order_engine [rand.adapt.shuf]

A shuffle_order_engine random number engine adaptor produces the same random numbers that are produced by some base engine e, but delivers them in a different sequence.
The state x of a shuffle_order_engine engine adaptor object x consists of the state e of its base engine e, an additional value Y of the type delivered by e, and an additional sequence V of k values also of the type delivered by e.
The size of the state is the size of e's state plus .
The transition algorithm permutes the values produced by e.
The state transition is performed as follows:
  • Calculate an integer .
  • Set Y to and then set to e().
The generation algorithm yields the last value of Y produced while advancing e's state as described above.
namespace std { template<class Engine, size_t k> class shuffle_order_engine { public: // types using result_type = typename Engine::result_type; // engine characteristics static constexpr size_t table_size = k; static constexpr result_type min() { return Engine::min(); } static constexpr result_type max() { return Engine::max(); } // constructors and seeding functions shuffle_order_engine(); explicit shuffle_order_engine(const Engine& e); explicit shuffle_order_engine(Engine&& e); explicit shuffle_order_engine(result_type s); template<class Sseq> explicit shuffle_order_engine(Sseq& q); void seed(); void seed(result_type s); template<class Sseq> void seed(Sseq& q); // equality operators friend bool operator==(const shuffle_order_engine& x, const shuffle_order_engine& y); // generating functions result_type operator()(); void discard(unsigned long long z); // property functions const Engine& base() const noexcept { return e; } // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const shuffle_order_engine& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, shuffle_order_engine& x); private: Engine e; // exposition only result_type V[k]; // exposition only result_type Y; // exposition only }; }
The following relation shall hold: 0 < k.
The textual representation consists of the textual representation of e, followed by the k values of V, followed by the value of Y.
In addition to its behavior pursuant to subclause [rand.req.adapt], each constructor that is not a copy constructor initializes V[0], …, V[k-1] and Y, in that order, with values returned by successive invocations of e().

29.5.6 Engines and engine adaptors with predefined parameters [rand.predef]

using minstd_rand0 = linear_congruential_engine<uint_fast32_t, 16'807, 0, 2'147'483'647>;
Required behavior: The consecutive invocation of a default-constructed object of type minstd_rand0 produces the value 1043618065.
using minstd_rand = linear_congruential_engine<uint_fast32_t, 48'271, 0, 2'147'483'647>;
Required behavior: The consecutive invocation of a default-constructed object of type minstd_rand produces the value 399268537.
using mt19937 = mersenne_twister_engine<uint_fast32_t, 32, 624, 397, 31, 0x9908'b0df, 11, 0xffff'ffff, 7, 0x9d2c'5680, 15, 0xefc6'0000, 18, 1'812'433'253>;
Required behavior: The consecutive invocation of a default-constructed object of type mt19937 produces the value 4123659995.
using mt19937_64 = mersenne_twister_engine<uint_fast64_t, 64, 312, 156, 31, 0xb502'6f5a'a966'19e9, 29, 0x5555'5555'5555'5555, 17, 0x71d6'7fff'eda6'0000, 37, 0xfff7'eee0'0000'0000, 43, 6'364'136'223'846'793'005>;
Required behavior: The consecutive invocation of a default-constructed object of type mt19937_64 produces the value 9981545732273789042.
using ranlux24_base = subtract_with_carry_engine<uint_fast32_t, 24, 10, 24>;
Required behavior: The consecutive invocation of a default-constructed object of type ranlux24_base produces the value 7937952.
using ranlux48_base = subtract_with_carry_engine<uint_fast64_t, 48, 5, 12>;
Required behavior: The consecutive invocation of a default-constructed object of type ranlux48_base produces the value 61839128582725.
using ranlux24 = discard_block_engine<ranlux24_base, 223, 23>;
Required behavior: The consecutive invocation of a default-constructed object of type ranlux24 produces the value 9901578.
using ranlux48 = discard_block_engine<ranlux48_base, 389, 11>;
Required behavior: The consecutive invocation of a default-constructed object of type ranlux48 produces the value 249142670248501.
using knuth_b = shuffle_order_engine<minstd_rand0,256>;
Required behavior: The consecutive invocation of a default-constructed object of type knuth_b produces the value 1112339016.
using default_random_engine = implementation-defined;
Remarks: The choice of engine type named by this typedef is implementation-defined.
[Note 1: 
The implementation can select this type on the basis of performance, size, quality, or any combination of such factors, so as to provide at least acceptable engine behavior for relatively casual, inexpert, and/or lightweight use.
Because different implementations can select different underlying engine types, code that uses this typedef need not generate identical sequences across implementations.
— end note]
using philox4x32 = philox_engine<uint_fast32_t, 32, 4, 10, 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>;
Required behavior: The consecutive invocation a default-constructed object of type philox4x32 produces the value 1955073260.
using philox4x64 = philox_engine<uint_fast64_t, 64, 4, 10, 0xCA5A826395121157, 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>;
Required behavior: The consecutive invocation a default-constructed object of type philox4x64 produces the value 3409172418970261260.

29.5.7 Class random_device [rand.device]

A random_device uniform random bit generator produces nondeterministic random numbers.
If implementation limitations prevent generating nondeterministic random numbers, the implementation may employ a random number engine.
namespace std { class random_device { public: // types using result_type = unsigned int; // generator characteristics static constexpr result_type min() { return numeric_limits<result_type>::min(); } static constexpr result_type max() { return numeric_limits<result_type>::max(); } // constructors random_device() : random_device(implementation-defined) {} explicit random_device(const string& token); // generating functions result_type operator()(); // property functions double entropy() const noexcept; // no copy functions random_device(const random_device&) = delete; void operator=(const random_device&) = delete; }; }
explicit random_device(const string& token);
Throws: A value of an implementation-defined type derived from exception if the random_device cannot be initialized.
Remarks: The semantics of the token parameter and the token value used by the default constructor are implementation-defined.247
double entropy() const noexcept;
Returns: If the implementation employs a random number engine, returns 0.0.
Otherwise, returns an entropy estimate248 for the random numbers returned by operator(), in the range min() to .
result_type operator()();
Returns: A nondeterministic random value, uniformly distributed between min() and max() (inclusive).
It is implementation-defined how these values are generated.
Throws: A value of an implementation-defined type derived from exception if a random number cannot be obtained.
247)247)
The parameter is intended to allow an implementation to differentiate between different sources of randomness.
248)248)
If a device has n states whose respective probabilities are , the device entropy S is defined as
.

29.5.8 Utilities [rand.util]

29.5.8.1 Class seed_seq [rand.util.seedseq]

namespace std { class seed_seq { public: // types using result_type = uint_least32_t; // constructors seed_seq() noexcept; template<class T> seed_seq(initializer_list<T> il); template<class InputIterator> seed_seq(InputIterator begin, InputIterator end); // generating functions template<class RandomAccessIterator> void generate(RandomAccessIterator begin, RandomAccessIterator end); // property functions size_t size() const noexcept; template<class OutputIterator> void param(OutputIterator dest) const; // no copy functions seed_seq(const seed_seq&) = delete; void operator=(const seed_seq&) = delete; private: vector<result_type> v; // exposition only }; }
seed_seq() noexcept;
Postconditions: v.empty() is true.
template<class T> seed_seq(initializer_list<T> il);
Constraints: T is an integer type.
Effects: Same as seed_seq(il.begin(), il.end()).
template<class InputIterator> seed_seq(InputIterator begin, InputIterator end);
Mandates: iterator_traits<InputIterator>​::​value_type is an integer type.
Preconditions: InputIterator meets the Cpp17InputIterator requirements ([input.iterators]).
Effects: Initializes v by the following algorithm: for (InputIterator s = begin; s != end; ++s) v.push_back((*s));
template<class RandomAccessIterator> void generate(RandomAccessIterator begin, RandomAccessIterator end);
Mandates: iterator_traits<RandomAccessIterator>​::​​value_type is an unsigned integer type capable of accommodating 32-bit quantities.
Preconditions: RandomAccessIterator meets the Cpp17RandomAccessIterator requirements ([random.access.iterators]) and the requirements of a mutable iterator.
Effects: Does nothing if begin == end.
Otherwise, with and , fills the supplied range [begin,end) according to the following algorithm in which each operation is to be carried out modulo , each indexing operator applied to begin is to be taken modulo n, and T(x) is defined as x xor(x rshift27):
  • By way of initialization, set each element of the range to the value 0x8b8b8b8b.
    Additionally, for use in subsequent steps, let and let , where
  • With m as the larger of and n, transform the elements of the range: iteratively for , calculate values
    and, in order, increment begin[] by , increment begin[] by , and set begin[k] to .
  • Transform the elements of the range again, beginning where the previous step ended: iteratively for , calculate values
    and, in order, update begin[] by xoring it with , update begin[] by xoring it with , and set begin[k] to .
Throws: What and when RandomAccessIterator operations of begin and end throw.
size_t size() const noexcept;
Returns: The number of 32-bit units that would be returned by a call to param().
Complexity: Constant time.
template<class OutputIterator> void param(OutputIterator dest) const;
Mandates: Values of type result_type are writable ([iterator.requirements.general]) to dest.
Preconditions: OutputIterator meets the Cpp17OutputIterator requirements ([output.iterators]).
Effects: Copies the sequence of prepared 32-bit units to the given destination, as if by executing the following statement: copy(v.begin(), v.end(), dest);
Throws: What and when OutputIterator operations of dest throw.

29.5.8.2 Function template generate_canonical [rand.util.canonical]

template<class RealType, size_t digits, class URBG> RealType generate_canonical(URBG& g);
Let
  • r be numeric_limits<RealType>​::​radix,
  • R be ,
  • d be the smaller of digits and numeric_limits<RealType>​::​digits,249
  • k be the smallest integer such that , and
  • x be .
An attempt is k invocations of g() to obtain values , respectively, and the calculation of a quantity S given by Formula 29.1:
Effects: Attempts are made until .
[Note 1: 
When R is a power of r, precisely one attempt is made.
— end note]
Returns: .
[Note 2: 
The return value c satisfies .
— end note]
Throws: What and when g throws.
Complexity: Exactly k invocations of g per attempt.
[Note 3: 
If the values produced by g are uniformly distributed, the instantiation's results are distributed as uniformly as possible.
Obtaining a value in this way can be a useful step in the process of transforming a value generated by a uniform random bit generator into a value that can be delivered by a random number distribution.
— end note]
[Note 4: 
When R is a power of r, an implementation can avoid using an arithmetic type that is wider than the output when computing S.
— end note]
249)249)
d is introduced to avoid any attempt to produce more bits of randomness than can be held in RealType.

29.5.9 Random number distribution class templates [rand.dist]

29.5.9.1 General [rand.dist.general]

Each type instantiated from a class template specified in [rand.dist] meets the requirements of a random number distribution type.
Descriptions are provided in [rand.dist] only for distribution operations that are not described in [rand.req.dist] or for operations where there is additional semantic information.
In particular, declarations for copy constructors, for copy assignment operators, for streaming operators, and for equality and inequality operators are not shown in the synopses.
The algorithms for producing each of the specified distributions are implementation-defined.
The value of each probability density function p(z) and of each discrete probability function specified in this subclause is 0 everywhere outside its stated domain.

29.5.9.2 Uniform distributions [rand.dist.uni]

29.5.9.2.1 Class template uniform_int_distribution [rand.dist.uni.int]

A uniform_int_distribution random number distribution produces random integers i, a  ≤ i  ≤ b, distributed according to the constant discrete probability function in Formula 29.2.
namespace std { template<class IntType = int> class uniform_int_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructors and reset functions uniform_int_distribution() : uniform_int_distribution(0) {} explicit uniform_int_distribution(IntType a, IntType b = numeric_limits<IntType>::max()); explicit uniform_int_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const uniform_int_distribution& x, const uniform_int_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions result_type a() const; result_type b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const uniform_int_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, uniform_int_distribution& x); }; }
explicit uniform_int_distribution(IntType a, IntType b = numeric_limits<IntType>::max());
Preconditions: a  ≤ b.
Remarks: a and b correspond to the respective parameters of the distribution.
result_type a() const;
Returns: The value of the a parameter with which the object was constructed.
result_type b() const;
Returns: The value of the b parameter with which the object was constructed.

29.5.9.2.2 Class template uniform_real_distribution [rand.dist.uni.real]

A uniform_real_distribution random number distribution produces random numbers x, , distributed according to the constant probability density function in Formula 29.3.
[Note 1: 
This implies that p(x|a,b) is undefined when a == b.
— end note]
namespace std { template<class RealType = double> class uniform_real_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructors and reset functions uniform_real_distribution() : uniform_real_distribution(0.0) {} explicit uniform_real_distribution(RealType a, RealType b = 1.0); explicit uniform_real_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const uniform_real_distribution& x, const uniform_real_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions result_type a() const; result_type b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const uniform_real_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, uniform_real_distribution& x); }; }
explicit uniform_real_distribution(RealType a, RealType b = 1.0);
Preconditions: a  ≤ b and .
Remarks: a and b correspond to the respective parameters of the distribution.
result_type a() const;
Returns: The value of the a parameter with which the object was constructed.
result_type b() const;
Returns: The value of the b parameter with which the object was constructed.

29.5.9.3 Bernoulli distributions [rand.dist.bern]

29.5.9.3.1 Class bernoulli_distribution [rand.dist.bern.bernoulli]

A bernoulli_distribution random number distribution produces bool values b distributed according to the discrete probability function in Formula 29.4.
namespace std { class bernoulli_distribution { public: // types using result_type = bool; using param_type = unspecified; // 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<class URBG> result_type operator()(URBG& g); template<class URBG> 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<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bernoulli_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bernoulli_distribution& x); }; }
explicit bernoulli_distribution(double p);
Preconditions: 0  ≤ p  ≤ 1.
Remarks: p corresponds to the parameter of the distribution.
double p() const;
Returns: The value of the p parameter with which the object was constructed.

29.5.9.3.2 Class template binomial_distribution [rand.dist.bern.bin]

A binomial_distribution random number distribution produces integer values i  ≥ 0 distributed according to the discrete probability function in Formula 29.5.
namespace std { template<class IntType = int> class binomial_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructors and reset functions binomial_distribution() : binomial_distribution(1) {} explicit binomial_distribution(IntType t, double p = 0.5); explicit binomial_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const binomial_distribution& x, const binomial_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions IntType t() const; 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<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const binomial_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, binomial_distribution& x); }; }
explicit binomial_distribution(IntType t, double p = 0.5);
Preconditions: 0  ≤ p  ≤ 1 and 0  ≤ t.
Remarks: t and p correspond to the respective parameters of the distribution.
IntType t() const;
Returns: The value of the t parameter with which the object was constructed.
double p() const;
Returns: The value of the p parameter with which the object was constructed.

29.5.9.3.3 Class template geometric_distribution [rand.dist.bern.geo]

A geometric_distribution random number distribution produces integer values i  ≥ 0 distributed according to the discrete probability function in Formula 29.6.
namespace std { template<class IntType = int> class geometric_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructors and reset functions geometric_distribution() : geometric_distribution(0.5) {} explicit geometric_distribution(double p); explicit geometric_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const geometric_distribution& x, const geometric_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> 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<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const geometric_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, geometric_distribution& x); }; }
explicit geometric_distribution(double p);
Preconditions: .
Remarks: p corresponds to the parameter of the distribution.
double p() const;
Returns: The value of the p parameter with which the object was constructed.

29.5.9.3.4 Class template negative_binomial_distribution [rand.dist.bern.negbin]

A negative_binomial_distribution random number distribution produces random integers i  ≥ 0 distributed according to the discrete probability function in Formula 29.7.
[Note 1: 
This implies that P(i|k,p) is undefined when p == 1.
— end note]
namespace std { template<class IntType = int> class negative_binomial_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructor and reset functions negative_binomial_distribution() : negative_binomial_distribution(1) {} explicit negative_binomial_distribution(IntType k, double p = 0.5); explicit negative_binomial_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const negative_binomial_distribution& x, const negative_binomial_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions IntType k() const; 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<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const negative_binomial_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, negative_binomial_distribution& x); }; }
explicit negative_binomial_distribution(IntType k, double p = 0.5);
Preconditions: and .
Remarks: k and p correspond to the respective parameters of the distribution.
IntType k() const;
Returns: The value of the k parameter with which the object was constructed.
double p() const;
Returns: The value of the p parameter with which the object was constructed.

29.5.9.4 Poisson distributions [rand.dist.pois]

29.5.9.4.1 Class template poisson_distribution [rand.dist.pois.poisson]

A poisson_distribution random number distribution produces integer values i  ≥ 0 distributed according to the discrete probability function in Formula 29.8.
The distribution parameter μ is also known as this distribution's mean.
namespace std { template<class IntType = int> class poisson_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructors and reset functions poisson_distribution() : poisson_distribution(1.0) {} explicit poisson_distribution(double mean); explicit poisson_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const poisson_distribution& x, const poisson_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions double mean() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const poisson_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, poisson_distribution& x); }; }
explicit poisson_distribution(double mean);
Preconditions: .
Remarks: mean corresponds to the parameter of the distribution.
double mean() const;
Returns: The value of the mean parameter with which the object was constructed.

29.5.9.4.2 Class template exponential_distribution [rand.dist.pois.exp]

An exponential_distribution random number distribution produces random numbers distributed according to the probability density function in Formula 29.9.
namespace std { template<class RealType = double> class exponential_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructors and reset functions exponential_distribution() : exponential_distribution(1.0) {} explicit exponential_distribution(RealType lambda); explicit exponential_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const exponential_distribution& x, const exponential_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType lambda() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const exponential_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, exponential_distribution& x); }; }
explicit exponential_distribution(RealType lambda);
Preconditions: .
Remarks: lambda corresponds to the parameter of the distribution.
RealType lambda() const;
Returns: The value of the lambda parameter with which the object was constructed.

29.5.9.4.3 Class template gamma_distribution [rand.dist.pois.gamma]

A gamma_distribution random number distribution produces random numbers distributed according to the probability density function in Formula 29.10.
namespace std { template<class RealType = double> class gamma_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructors and reset functions gamma_distribution() : gamma_distribution(1.0) {} explicit gamma_distribution(RealType alpha, RealType beta = 1.0); explicit gamma_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const gamma_distribution& x, const gamma_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType alpha() const; RealType beta() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const gamma_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, gamma_distribution& x); }; }
explicit gamma_distribution(RealType alpha, RealType beta = 1.0);
Preconditions: and .
Remarks: alpha and beta correspond to the parameters of the distribution.
RealType alpha() const;
Returns: The value of the alpha parameter with which the object was constructed.
RealType beta() const;
Returns: The value of the beta parameter with which the object was constructed.

29.5.9.4.4 Class template weibull_distribution [rand.dist.pois.weibull]

A weibull_distribution random number distribution produces random numbers x  ≥ 0 distributed according to the probability density function in Formula 29.11.
namespace std { template<class RealType = double> class weibull_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions weibull_distribution() : weibull_distribution(1.0) {} explicit weibull_distribution(RealType a, RealType b = 1.0); explicit weibull_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const weibull_distribution& x, const weibull_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType a() const; RealType b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weibull_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, weibull_distribution& x); }; }
explicit weibull_distribution(RealType a, RealType b = 1.0);
Preconditions: and .
Remarks: a and b correspond to the respective parameters of the distribution.
RealType a() const;
Returns: The value of the a parameter with which the object was constructed.
RealType b() const;
Returns: The value of the b parameter with which the object was constructed.

29.5.9.4.5 Class template extreme_value_distribution [rand.dist.pois.extreme]

An extreme_value_distribution random number distribution produces random numbers x distributed according to the probability density function in Formula 29.12.250
namespace std { template<class RealType = double> class extreme_value_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions extreme_value_distribution() : extreme_value_distribution(0.0) {} explicit extreme_value_distribution(RealType a, RealType b = 1.0); explicit extreme_value_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const extreme_value_distribution& x, const extreme_value_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType a() const; RealType b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const extreme_value_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, extreme_value_distribution& x); }; }
explicit extreme_value_distribution(RealType a, RealType b = 1.0);
Preconditions: .
Remarks: a and b correspond to the respective parameters of the distribution.
RealType a() const;
Returns: The value of the a parameter with which the object was constructed.
RealType b() const;
Returns: The value of the b parameter with which the object was constructed.
250)250)
The distribution corresponding to this probability density function is also known (with a possible change of variable) as the Gumbel Type I, the log-Weibull, or the Fisher-Tippett Type I distribution.

29.5.9.5 Normal distributions [rand.dist.norm]

29.5.9.5.1 Class template normal_distribution [rand.dist.norm.normal]

A normal_distribution random number distribution produces random numbers x distributed according to the probability density function in Formula 29.13.
The distribution parameters μ and σ are also known as this distribution's mean and standard deviation.
namespace std { template<class RealType = double> class normal_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructors and reset functions normal_distribution() : normal_distribution(0.0) {} explicit normal_distribution(RealType mean, RealType stddev = 1.0); explicit normal_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const normal_distribution& x, const normal_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType mean() const; RealType stddev() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const normal_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, normal_distribution& x); }; }
explicit normal_distribution(RealType mean, RealType stddev = 1.0);
Preconditions: .
Remarks: mean and stddev correspond to the respective parameters of the distribution.
RealType mean() const;
Returns: The value of the mean parameter with which the object was constructed.
RealType stddev() const;
Returns: The value of the stddev parameter with which the object was constructed.

29.5.9.5.2 Class template lognormal_distribution [rand.dist.norm.lognormal]

A lognormal_distribution random number distribution produces random numbers distributed according to the probability density function in Formula 29.14.
namespace std { template<class RealType = double> class lognormal_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions lognormal_distribution() : lognormal_distribution(0.0) {} explicit lognormal_distribution(RealType m, RealType s = 1.0); explicit lognormal_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const lognormal_distribution& x, const lognormal_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType m() const; RealType s() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const lognormal_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, lognormal_distribution& x); }; }
explicit lognormal_distribution(RealType m, RealType s = 1.0);
Preconditions: .
Remarks: m and s correspond to the respective parameters of the distribution.
RealType m() const;
Returns: The value of the m parameter with which the object was constructed.
RealType s() const;
Returns: The value of the s parameter with which the object was constructed.

29.5.9.5.3 Class template chi_squared_distribution [rand.dist.norm.chisq]

A chi_squared_distribution random number distribution produces random numbers distributed according to the probability density function in Formula 29.15.
namespace std { template<class RealType = double> class chi_squared_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions chi_squared_distribution() : chi_squared_distribution(1.0) {} explicit chi_squared_distribution(RealType n); explicit chi_squared_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const chi_squared_distribution& x, const chi_squared_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType n() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const chi_squared_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, chi_squared_distribution& x); }; }
explicit chi_squared_distribution(RealType n);
Preconditions: .
Remarks: n corresponds to the parameter of the distribution.
RealType n() const;
Returns: The value of the n parameter with which the object was constructed.

29.5.9.5.4 Class template cauchy_distribution [rand.dist.norm.cauchy]

A cauchy_distribution random number distribution produces random numbers x distributed according to the probability density function in Formula 29.16.
namespace std { template<class RealType = double> class cauchy_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions cauchy_distribution() : cauchy_distribution(0.0) {} explicit cauchy_distribution(RealType a, RealType b = 1.0); explicit cauchy_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const cauchy_distribution& x, const cauchy_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType a() const; RealType b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const cauchy_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, cauchy_distribution& x); }; }
explicit cauchy_distribution(RealType a, RealType b = 1.0);
Preconditions: .
Remarks: a and b correspond to the respective parameters of the distribution.
RealType a() const;
Returns: The value of the a parameter with which the object was constructed.
RealType b() const;
Returns: The value of the b parameter with which the object was constructed.

29.5.9.5.5 Class template fisher_f_distribution [rand.dist.norm.f]

A fisher_f_distribution random number distribution produces random numbers x  ≥ 0 distributed according to the probability density function in Formula 29.17.
namespace std { template<class RealType = double> class fisher_f_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions fisher_f_distribution() : fisher_f_distribution(1.0) {} explicit fisher_f_distribution(RealType m, RealType n = 1.0); explicit fisher_f_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const fisher_f_distribution& x, const fisher_f_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType m() const; RealType n() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const fisher_f_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, fisher_f_distribution& x); }; }
explicit fisher_f_distribution(RealType m, RealType n = 1);
Preconditions: and .
Remarks: m and n correspond to the respective parameters of the distribution.
RealType m() const;
Returns: The value of the m parameter with which the object was constructed.
RealType n() const;
Returns: The value of the n parameter with which the object was constructed.

29.5.9.5.6 Class template student_t_distribution [rand.dist.norm.t]

A student_t_distribution random number distribution produces random numbers x distributed according to the probability density function in Formula 29.18.
namespace std { template<class RealType = double> class student_t_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions student_t_distribution() : student_t_distribution(1.0) {} explicit student_t_distribution(RealType n); explicit student_t_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const student_t_distribution& x, const student_t_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions RealType n() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const student_t_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, student_t_distribution& x); }; }
explicit student_t_distribution(RealType n);
Preconditions: .
Remarks: n corresponds to the parameter of the distribution.
RealType n() const;
Returns: The value of the n parameter with which the object was constructed.

29.5.9.6 Sampling distributions [rand.dist.samp]

29.5.9.6.1 Class template discrete_distribution [rand.dist.samp.discrete]

A discrete_distribution random number distribution produces random integers i, , distributed according to the discrete probability function in Formula 29.19.
Unless specified otherwise, the distribution parameters are calculated as: for , in which the values , commonly known as the weights, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold: .
namespace std { template<class IntType = int> class discrete_distribution { public: // types using result_type = IntType; using param_type = unspecified; // constructor and reset functions discrete_distribution(); template<class InputIterator> discrete_distribution(InputIterator firstW, InputIterator lastW); discrete_distribution(initializer_list<double> wl); template<class UnaryOperation> discrete_distribution(size_t nw, double xmin, double xmax, UnaryOperation fw); explicit discrete_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const discrete_distribution& x, const discrete_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions vector<double> probabilities() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const discrete_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, discrete_distribution& x); }; }
discrete_distribution();
Effects: Constructs a discrete_distribution object with and .
[Note 1: 
Such an object will always deliver the value 0.
— end note]
template<class InputIterator> discrete_distribution(InputIterator firstW, InputIterator lastW);
Mandates: is_convertible_v<iterator_traits<InputIterator>​::​value_type, double> is true.
Preconditions: InputIterator meets the Cpp17InputIterator requirements ([input.iterators]).
If firstW == lastW, let and .
Otherwise, [firstW, lastW) forms a sequence w of length .
Effects: Constructs a discrete_distribution object with probabilities given by the Formula 29.19.
discrete_distribution(initializer_list<double> wl);
Effects: Same as discrete_distribution(wl.begin(), wl.end()).
template<class UnaryOperation> discrete_distribution(size_t nw, double xmin, double xmax, UnaryOperation fw);
Mandates: is_invocable_r_v<double, UnaryOperation&, double> is true.
Preconditions: If , let , otherwise let .
The relation holds.
Effects: Constructs a discrete_distribution object with probabilities given by the formula above, using the following values: If , let .
Otherwise, let for .
Complexity: The number of invocations of fw does not exceed n.
vector<double> probabilities() const;
Returns: A vector<double> whose size member returns n and whose operator[] member returns when invoked with argument k for .

29.5.9.6.2 Class template piecewise_constant_distribution [rand.dist.samp.pconst]

A piecewise_constant_distribution random number distribution produces random numbers x, , uniformly distributed over each subinterval according to the probability density function in Formula 29.20.
The distribution parameters , also known as this distribution's interval boundaries, shall satisfy the relation for .
Unless specified otherwise, the remaining n distribution parameters are calculated as:
in which the values , commonly known as the weights, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold: .
namespace std { template<class RealType = double> class piecewise_constant_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions piecewise_constant_distribution(); template<class InputIteratorB, class InputIteratorW> piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW); template<class UnaryOperation> piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw); template<class UnaryOperation> piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); explicit piecewise_constant_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const piecewise_constant_distribution& x, const piecewise_constant_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions vector<result_type> intervals() const; vector<result_type> densities() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const piecewise_constant_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, piecewise_constant_distribution& x); }; }
piecewise_constant_distribution();
Effects: Constructs a piecewise_constant_distribution object with , , , and .
template<class InputIteratorB, class InputIteratorW> piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);
Mandates: Both of
  • is_convertible_v<iterator_traits<InputIteratorB>​::​value_type, double>
  • is_convertible_v<iterator_traits<InputIteratorW>​::​value_type, double>
are true.
Preconditions: InputIteratorB and InputIteratorW each meet the Cpp17InputIterator requirements ([input.iterators]).
If firstB == lastB or ++firstB == lastB, let , , , and .
Otherwise, [firstB, lastB) forms a sequence b of length , the length of the sequence w starting from firstW is at least n, and any for k  ≥ n are ignored by the distribution.
Effects: Constructs a piecewise_constant_distribution object with parameters as specified above.
template<class UnaryOperation> piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw);
Mandates: is_invocable_r_v<double, UnaryOperation&, double> is true.
Effects: Constructs a piecewise_constant_distribution object with parameters taken or calculated from the following values: If , let , , , and .
Otherwise, let [bl.begin(), bl.end()) form a sequence , and let for .
Complexity: The number of invocations of fw does not exceed n.
template<class UnaryOperation> piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);
Mandates: is_invocable_r_v<double, UnaryOperation&, double> is true.
Preconditions: If , let , otherwise let .
The relation holds.
Effects: Constructs a piecewise_constant_distribution object with parameters taken or calculated from the following values: Let for , and for .
Complexity: The number of invocations of fw does not exceed n.
vector<result_type> intervals() const;
Returns: A vector<result_type> whose size member returns and whose operator[] member returns when invoked with argument k for .
vector<result_type> densities() const;
Returns: A vector<result_type> whose size member returns n and whose operator[] member returns when invoked with argument k for .

29.5.9.6.3 Class template piecewise_linear_distribution [rand.dist.samp.plinear]

A piecewise_linear_distribution random number distribution produces random numbers x, , distributed over each subinterval according to the probability density function in Formula 29.21.
The distribution parameters , also known as this distribution's interval boundaries, shall satisfy the relation for .
Unless specified otherwise, the remaining distribution parameters are calculated as for , in which the values , commonly known as the weights at boundaries, shall be non-negative, non-NaN, and non-infinity.
Moreover, the following relation shall hold:
namespace std { template<class RealType = double> class piecewise_linear_distribution { public: // types using result_type = RealType; using param_type = unspecified; // constructor and reset functions piecewise_linear_distribution(); template<class InputIteratorB, class InputIteratorW> piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW); template<class UnaryOperation> piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw); template<class UnaryOperation> piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw); explicit piecewise_linear_distribution(const param_type& parm); void reset(); // equality operators friend bool operator==(const piecewise_linear_distribution& x, const piecewise_linear_distribution& y); // generating functions template<class URBG> result_type operator()(URBG& g); template<class URBG> result_type operator()(URBG& g, const param_type& parm); // property functions vector<result_type> intervals() const; vector<result_type> densities() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; // inserters and extractors template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const piecewise_linear_distribution& x); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, piecewise_linear_distribution& x); }; }
piecewise_linear_distribution();
Effects: Constructs a piecewise_linear_distribution object with , , , and .
template<class InputIteratorB, class InputIteratorW> piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);
Mandates: Both of
  • is_convertible_v<iterator_traits<InputIteratorB>​::​value_type, double>
  • is_convertible_v<iterator_traits<InputIteratorW>​::​value_type, double>
are true.
Preconditions: InputIteratorB and InputIteratorW each meet the Cpp17InputIterator requirements ([input.iterators]).
If firstB == lastB or ++firstB == lastB, let , , , and .
Otherwise, [firstB, lastB) forms a sequence b of length , the length of the sequence w starting from firstW is at least , and any for are ignored by the distribution.
Effects: Constructs a piecewise_linear_distribution object with parameters as specified above.
template<class UnaryOperation> piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw);
Mandates: is_invocable_r_v<double, UnaryOperation&, double> is true.
Effects: Constructs a piecewise_linear_distribution object with parameters taken or calculated from the following values: If , let , , , and .
Otherwise, let [bl.begin(), bl.end()) form a sequence , and let for .
Complexity: The number of invocations of fw does not exceed .
template<class UnaryOperation> piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);
Mandates: is_invocable_r_v<double, UnaryOperation&, double> is true.
Preconditions: If , let , otherwise let .
The relation holds.
Effects: Constructs a piecewise_linear_distribution object with parameters taken or calculated from the following values: Let for , and for .
Complexity: The number of invocations of fw does not exceed .
vector<result_type> intervals() const;
Returns: A vector<result_type> whose size member returns and whose operator[] member returns when invoked with argument k for .
vector<result_type> densities() const;
Returns: A vector<result_type> whose size member returns n and whose operator[] member returns when invoked with argument k for .

29.5.10 Low-quality random number generation [c.math.rand]

[Note 1: 
The header <cstdlib> declares the functions described in this subclause.
— end note]
int rand(); void srand(unsigned int seed);
Effects: The rand and srand functions have the semantics specified in the C standard library.
Remarks: The implementation may specify that particular library functions may call rand.
It is implementation-defined whether the rand function may introduce data races ([res.on.data.races]).
[Note 2: 
The other random number generation facilities in this document ([rand]) are often preferable to rand, because rand's underlying algorithm is unspecified.
Use of rand therefore continues to be non-portable, with unpredictable and oft-questionable quality and performance.
— end note]
See also: ISO/IEC 9899:2018, 7.22.2

29.6 Numeric arrays [numarray]

29.6.1 Header <valarray> synopsis [valarray.syn]

#include <initializer_list> // see [initializer.list.syn] namespace std { template<class T> class valarray; // An array of type T class slice; // a BLAS-like slice out of an array template<class T> class slice_array; class gslice; // a generalized slice out of an array template<class T> class gslice_array; template<class T> class mask_array; // a masked array template<class T> class indirect_array; // an indirected array template<class T> void swap(valarray<T>&, valarray<T>&) noexcept; template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator* (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator* (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator/ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator% (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator+ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator- (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator^ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator& (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator| (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator<<(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator>>(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator&&(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator||(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator==(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator==(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator!=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator< (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator> (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator<=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator>=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> abs (const valarray<T>&); template<class T> valarray<T> acos (const valarray<T>&); template<class T> valarray<T> asin (const valarray<T>&); template<class T> valarray<T> atan (const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> atan2(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> cos (const valarray<T>&); template<class T> valarray<T> cosh (const valarray<T>&); template<class T> valarray<T> exp (const valarray<T>&); template<class T> valarray<T> log (const valarray<T>&); template<class T> valarray<T> log10(const valarray<T>&); template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> pow(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> pow(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> sin (const valarray<T>&); template<class T> valarray<T> sinh (const valarray<T>&); template<class T> valarray<T> sqrt (const valarray<T>&); template<class T> valarray<T> tan (const valarray<T>&); template<class T> valarray<T> tanh (const valarray<T>&); template<class T> unspecified1 begin(valarray<T>& v); template<class T> unspecified2 begin(const valarray<T>& v); template<class T> unspecified1 end(valarray<T>& v); template<class T> unspecified2 end(const valarray<T>& v); }
The header <valarray> defines five class templates (valarray, slice_array, gslice_array, mask_array, and indirect_array), two classes (slice and gslice), and a series of related function templates for representing and manipulating arrays of values.
The valarray array classes are defined to be free of certain forms of aliasing, thus allowing operations on these classes to be optimized.
Any function returning a valarray<T> is permitted to return an object of another type, provided all the const member functions of valarray<T> are also applicable to this type.
This return type shall not add more than two levels of template nesting over the most deeply nested argument type.251
Implementations introducing such replacement types shall provide additional functions and operators as follows:
  • for every function taking a const valarray<T>& other than begin and end, identical functions taking the replacement types shall be added;
  • for every function taking two const valarray<T>& arguments, identical functions taking every combination of const valarray<T>& and replacement types shall be added.
In particular, an implementation shall allow a valarray<T> to be constructed from such replacement types and shall allow assignments and compound assignments of such types to valarray<T>, slice_array<T>, gslice_array<T>, mask_array<T> and indirect_array<T> objects.
These library functions are permitted to throw a bad_alloc exception if there are not sufficient resources available to carry out the operation.
Note that the exception is not mandated.
251)251)
[implimits] recommends a minimum number of recursively nested template instantiations.
This requirement thus indirectly suggests a minimum allowable complexity for valarray expressions.

29.6.2 Class template valarray [template.valarray]

29.6.2.1 Overview [template.valarray.overview]

namespace std { template<class T> class valarray { public: using value_type = T; // [valarray.cons], construct/destroy valarray(); explicit valarray(size_t); valarray(const T&, size_t); valarray(const T*, size_t); valarray(const valarray&); valarray(valarray&&) noexcept; valarray(const slice_array<T>&); valarray(const gslice_array<T>&); valarray(const mask_array<T>&); valarray(const indirect_array<T>&); valarray(initializer_list<T>); ~valarray(); // [valarray.assign], assignment valarray& operator=(const valarray&); valarray& operator=(valarray&&) noexcept; valarray& operator=(initializer_list<T>); valarray& operator=(const T&); valarray& operator=(const slice_array<T>&); valarray& operator=(const gslice_array<T>&); valarray& operator=(const mask_array<T>&); valarray& operator=(const indirect_array<T>&); // [valarray.access], element access const T& operator[](size_t) const; T& operator[](size_t); // [valarray.sub], subset operations valarray operator[](slice) const; slice_array<T> operator[](slice); valarray operator[](const gslice&) const; gslice_array<T> operator[](const gslice&); valarray operator[](const valarray<bool>&) const; mask_array<T> operator[](const valarray<bool>&); valarray operator[](const valarray<size_t>&) const; indirect_array<T> operator[](const valarray<size_t>&); // [valarray.unary], unary operators valarray operator+() const; valarray operator-() const; valarray operator~() const; valarray<bool> operator!() const; // [valarray.cassign], compound assignment valarray& operator*= (const T&); valarray& operator/= (const T&); valarray& operator%= (const T&); valarray& operator+= (const T&); valarray& operator-= (const T&); valarray& operator^= (const T&); valarray& operator&= (const T&); valarray& operator|= (const T&); valarray& operator<<=(const T&); valarray& operator>>=(const T&); valarray& operator*= (const valarray&); valarray& operator/= (const valarray&); valarray& operator%= (const valarray&); valarray& operator+= (const valarray&); valarray& operator-= (const valarray&); valarray& operator^= (const valarray&); valarray& operator|= (const valarray&); valarray& operator&= (const valarray&); valarray& operator<<=(const valarray&); valarray& operator>>=(const valarray&); // [valarray.members], member functions void swap(valarray&) noexcept; size_t size() const; T sum() const; T min() const; T max() const; valarray shift (int) const; valarray cshift(int) const; valarray apply(T func(T)) const; valarray apply(T func(const T&)) const; void resize(size_t sz, T c = T()); }; template<class T, size_t cnt> valarray(const T(&)[cnt], size_t) -> valarray<T>; }
The class template valarray<T> is a one-dimensional smart array, with elements numbered sequentially from zero.
It is a representation of the mathematical concept of an ordered set of values.
For convenience, an object of type valarray<T> is referred to as an “array” throughout the remainder of [numarray].
The illusion of higher dimensionality may be produced by the familiar idiom of computed indices, together with the powerful subsetting capabilities provided by the generalized subscript operators.252
252)252)
The intent is to specify an array template that has the minimum functionality necessary to address aliasing ambiguities and the proliferation of temporary objects.
Thus, the valarray template is neither a matrix class nor a field class.
However, it is a very useful building block for designing such classes.

29.6.2.2 Constructors [valarray.cons]

valarray();
Effects: Constructs a valarray that has zero length.253
explicit valarray(size_t n);
Effects: Constructs a valarray that has length n.
Each element of the array is value-initialized.
valarray(const T& v, size_t n);
Effects: Constructs a valarray that has length n.
Each element of the array is initialized with v.
valarray(const T* p, size_t n);
Preconditions: [p, p + n) is a valid range.
Effects: Constructs a valarray that has length n.
The values of the elements of the array are initialized with the first n values pointed to by the first argument.254
valarray(const valarray& v);
Effects: Constructs a valarray that has the same length as v.
The elements are initialized with the values of the corresponding elements of v.255
valarray(valarray&& v) noexcept;
Effects: Constructs a valarray that has the same length as v.
The elements are initialized with the values of the corresponding elements of v.
Complexity: Constant.
valarray(initializer_list<T> il);
Effects: Equivalent to valarray(il.begin(), il.size()).
valarray(const slice_array<T>&); valarray(const gslice_array<T>&); valarray(const mask_array<T>&); valarray(const indirect_array<T>&);
These conversion constructors convert one of the four reference templates to a valarray.
~valarray();
Effects: The destructor is applied to every element of *this; an implementation may return all allocated memory.
253)253)
This default constructor is essential, since arrays of valarray can be useful.
After initialization, the length of an empty array can be increased with the resize member function.
254)254)
This constructor is the preferred method for converting a C array to a valarray object.
255)255)
This copy constructor creates a distinct array rather than an alias.
Implementations in which arrays share storage are permitted, but they would need to implement a copy-on-reference mechanism to ensure that arrays are conceptually distinct.

29.6.2.3 Assignment [valarray.assign]

valarray& operator=(const valarray& v);
Effects: Each element of the *this array is assigned the value of the corresponding element of v.
If the length of v is not equal to the length of *this, resizes *this to make the two arrays the same length, as if by calling resize(v.size()), before performing the assignment.
Postconditions: size() == v.size().
Returns: *this.
valarray& operator=(valarray&& v) noexcept;
Effects: *this obtains the value of v.
The value of v after the assignment is not specified.
Returns: *this.
Complexity: Linear.
valarray& operator=(initializer_list<T> il);
Effects: Equivalent to: return *this = valarray(il);
valarray& operator=(const T& v);
Effects: Assigns v to each element of *this.
Returns: *this.
valarray& operator=(const slice_array<T>&); valarray& operator=(const gslice_array<T>&); valarray& operator=(const mask_array<T>&); valarray& operator=(const indirect_array<T>&);
Preconditions: The length of the array to which the argument refers equals size().
The value of an element in the left-hand side of a valarray assignment operator does not depend on the value of another element in that left-hand side.
These operators allow the results of a generalized subscripting operation to be assigned directly to a valarray.

29.6.2.4 Element access [valarray.access]

const T& operator[](size_t n) const; T& operator[](size_t n);
Preconditions: n < size() is true.
Returns: A reference to the corresponding element of the array.
[Note 1: 
The expression (a[i] = q, a[i]) == q evaluates to true for any non-constant valarray<T> a, any T q, and for any size_t i such that the value of i is less than the length of a.
— end note]
Remarks: The expression addressof(a[i+j]) == addressof(a[i]) + j evaluates to true for all size_t i and size_t j such that i+j < a.size().
The expression addressof(a[i]) != addressof(b[j]) evaluates to true for any two arrays a and b and for any size_t i and size_t j such that i < a.size() and j < b.size().
[Note 2: 
This property indicates an absence of aliasing and can be used to advantage by optimizing compilers.
Compilers can take advantage of inlining, constant propagation, loop fusion, tracking of pointers obtained from operator new, and other techniques to generate efficient valarrays.
— end note]
The reference returned by the subscript operator for an array shall be valid until the member function resize(size_t, T) is called for that array or until the lifetime of that array ends, whichever happens first.

29.6.2.5 Subset operations [valarray.sub]

The member operator[] is overloaded to provide several ways to select sequences of elements from among those controlled by *this.
Each of these operations returns a subset of the array.
The const-qualified versions return this subset as a new valarray object.
The non-const versions return a class template object which has reference semantics to the original array, working in conjunction with various overloads of operator= and other assigning operators to allow selective replacement (slicing) of the controlled sequence.
In each case the selected element(s) shall exist.
valarray operator[](slice slicearr) const;
Returns: A valarray containing those elements of the controlled sequence designated by slicearr.
[Example 1: const valarray<char> v0("abcdefghijklmnop", 16); // v0[slice(2, 5, 3)] returns valarray<char>("cfilo", 5) — end example]
slice_array<T> operator[](slice slicearr);
Returns: An object that holds references to elements of the controlled sequence selected by slicearr.
[Example 2: valarray<char> v0("abcdefghijklmnop", 16); valarray<char> v1("ABCDE", 5); v0[slice(2, 5, 3)] = v1; // v0 == valarray<char>("abAdeBghCjkDmnEp", 16); — end example]
valarray operator[](const gslice& gslicearr) const;
Returns: A valarray containing those elements of the controlled sequence designated by gslicearr.
[Example 3: const valarray<char> v0("abcdefghijklmnop", 16); const size_t lv[] = { 2, 3 }; const size_t dv[] = { 7, 2 }; const valarray<size_t> len(lv, 2), str(dv, 2); // v0[gslice(3, len, str)] returns // valarray<char>("dfhkmo", 6) — end example]
gslice_array<T> operator[](const gslice& gslicearr);
Returns: An object that holds references to elements of the controlled sequence selected by gslicearr.
[Example 4: valarray<char> v0("abcdefghijklmnop", 16); valarray<char> v1("ABCDEF", 6); const size_t lv[] = { 2, 3 }; const size_t dv[] = { 7, 2 }; const valarray<size_t> len(lv, 2), str(dv, 2); v0[gslice(3, len, str)] = v1; // v0 == valarray<char>("abcAeBgCijDlEnFp", 16) — end example]
valarray operator[](const valarray<bool>& boolarr) const;
Returns: A valarray containing those elements of the controlled sequence designated by boolarr.
[Example 5: const valarray<char> v0("abcdefghijklmnop", 16); const bool vb[] = { false, false, true, true, false, true }; // v0[valarray<bool>(vb, 6)] returns // valarray<char>("cdf", 3) — end example]
mask_array<T> operator[](const valarray<bool>& boolarr);
Returns: An object that holds references to elements of the controlled sequence selected by boolarr.
[Example 6: valarray<char> v0("abcdefghijklmnop", 16); valarray<char> v1("ABC", 3); const bool vb[] = { false, false, true, true, false, true }; v0[valarray<bool>(vb, 6)] = v1; // v0 == valarray<char>("abABeCghijklmnop", 16) — end example]
valarray operator[](const valarray<size_t>& indarr) const;
Returns: A valarray containing those elements of the controlled sequence designated by indarr.
[Example 7: const valarray<char> v0("abcdefghijklmnop", 16); const size_t vi[] = { 7, 5, 2, 3, 8 }; // v0[valarray<size_t>(vi, 5)] returns // valarray<char>("hfcdi", 5) — end example]
indirect_array<T> operator[](const valarray<size_t>& indarr);
Returns: An object that holds references to elements of the controlled sequence selected by indarr.
[Example 8: valarray<char> v0("abcdefghijklmnop", 16); valarray<char> v1("ABCDE", 5); const size_t vi[] = { 7, 5, 2, 3, 8 }; v0[valarray<size_t>(vi, 5)] = v1; // v0 == valarray<char>("abCDeBgAEjklmnop", 16) — end example]

29.6.2.6 Unary operators [valarray.unary]

valarray operator+() const; valarray operator-() const; valarray operator~() const; valarray<bool> operator!() const;
Mandates: The indicated operator can be applied to operands of type T and returns a value of type T (bool for operator!) or which may be unambiguously implicitly converted to type T (bool for operator!).
Returns: A valarray whose length is size().
Each element of the returned array is initialized with the result of applying the indicated operator to the corresponding element of the array.

29.6.2.7 Compound assignment [valarray.cassign]

valarray& operator*= (const valarray& v); valarray& operator/= (const valarray& v); valarray& operator%= (const valarray& v); valarray& operator+= (const valarray& v); valarray& operator-= (const valarray& v); valarray& operator^= (const valarray& v); valarray& operator&= (const valarray& v); valarray& operator|= (const valarray& v); valarray& operator<<=(const valarray& v); valarray& operator>>=(const valarray& v);
Mandates: The indicated operator can be applied to two operands of type T.
Preconditions: size() == v.size() is true.
The value of an element in the left-hand side of a valarray compound assignment operator does not depend on the value of another element in that left hand side.
Effects: Each of these operators performs the indicated operation on each of the elements of *this and the corresponding element of v.
Returns: *this.
Remarks: The appearance of an array on the left-hand side of a compound assignment does not invalidate references or pointers.
valarray& operator*= (const T& v); valarray& operator/= (const T& v); valarray& operator%= (const T& v); valarray& operator+= (const T& v); valarray& operator-= (const T& v); valarray& operator^= (const T& v); valarray& operator&= (const T& v); valarray& operator|= (const T& v); valarray& operator<<=(const T& v); valarray& operator>>=(const T& v);
Mandates: The indicated operator can be applied to two operands of type T.
Effects: Each of these operators applies the indicated operation to each element of *this and v.
Returns: *this
Remarks: The appearance of an array on the left-hand side of a compound assignment does not invalidate references or pointers to the elements of the array.

29.6.2.8 Member functions [valarray.members]

void swap(valarray& v) noexcept;
Effects: *this obtains the value of v.
v obtains the value of *this.
Complexity: Constant.
size_t size() const;
Returns: The number of elements in the array.
Complexity: Constant time.
T sum() const;
Mandates: operator+= can be applied to operands of type T.
Preconditions: size() > 0 is true.
Returns: The sum of all the elements of the array.
If the array has length 1, returns the value of element 0.
Otherwise, the returned value is calculated by applying operator+= to a copy of an element of the array and all other elements of the array in an unspecified order.
T min() const;
Preconditions: size() > 0 is true.
Returns: The minimum value contained in *this.
For an array of length 1, the value of element 0 is returned.
For all other array lengths, the determination is made using operator<.
T max() const;
Preconditions: size() > 0 is true.
Returns: The maximum value contained in *this.
For an array of length 1, the value of element 0 is returned.
For all other array lengths, the determination is made using operator<.
valarray shift(int n) const;
Returns: A valarray of length size(), each of whose elements I is (*this)[I + n] if I + n is non-negative and less than size(), otherwise T().
[Note 1: 
If element zero is taken as the leftmost element, a positive value of n shifts the elements left n places, with zero fill.
— end note]
[Example 1: 
If the argument has the value , the first two elements of the result will be value-initialized; the third element of the result will be assigned the value of the first element of *this; etc.
— end example]
valarray cshift(int n) const;
Returns: A valarray of length size() that is a circular shift of *this.
If element zero is taken as the leftmost element, a non-negative value of n shifts the elements circularly left n places and a negative value of n shifts the elements circularly right places.
valarray apply(T func(T)) const; valarray apply(T func(const T&)) const;
Returns: A valarray whose length is size().
Each element of the returned array is assigned the value returned by applying the argument function to the corresponding element of *this.
void resize(size_t sz, T c = T());
Effects: Changes the length of the *this array to sz and then assigns to each element the value of the second argument.
Resizing invalidates all pointers and references to elements in the array.

29.6.3 valarray non-member operations [valarray.nonmembers]

29.6.3.1 Binary operators [valarray.binary]

template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&);
Mandates: The indicated operator can be applied to operands of type T and returns a value of type T or which can be unambiguously implicitly converted to T.
Preconditions: The argument arrays have the same length.
Returns: A valarray whose length is equal to the lengths of the argument arrays.
Each element of the returned array is initialized with the result of applying the indicated operator to the corresponding elements of the argument arrays.
template<class T> valarray<T> operator* (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator* (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator/ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator/ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator% (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator% (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator+ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator+ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator- (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator- (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator^ (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator^ (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator& (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator& (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator| (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator| (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator<<(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator<<(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> operator>>(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> operator>>(const typename valarray<T>::value_type&, const valarray<T>&);
Mandates: The indicated operator can be applied to operands of type T and returns a value of type T or which can be unambiguously implicitly converted to T.
Returns: A valarray whose length is equal to the length of the array argument.
Each element of the returned array is initialized with the result of applying the indicated operator to the corresponding element of the array argument and the non-array argument.

29.6.3.2 Logical operators [valarray.comparison]

template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&);
Mandates: The indicated operator can be applied to operands of type T and returns a value of type bool or which can be unambiguously implicitly converted to bool.
Preconditions: The two array arguments have the same length.
Returns: A valarray<bool> whose length is equal to the length of the array arguments.
Each element of the returned array is initialized with the result of applying the indicated operator to the corresponding elements of the argument arrays.
template<class T> valarray<bool> operator==(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator==(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator!=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator!=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator< (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator< (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator> (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator> (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator<=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator<=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator>=(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator>=(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator&&(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator&&(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<bool> operator||(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<bool> operator||(const typename valarray<T>::value_type&, const valarray<T>&);
Mandates: The indicated operator can be applied to operands of type T and returns a value of type bool or which can be unambiguously implicitly converted to bool.
Returns: A valarray<bool> whose length is equal to the length of the array argument.
Each element of the returned array is initialized with the result of applying the indicated operator to the corresponding element of the array and the non-array argument.

29.6.3.3 Transcendentals [valarray.transcend]

template<class T> valarray<T> abs (const valarray<T>&); template<class T> valarray<T> acos (const valarray<T>&); template<class T> valarray<T> asin (const valarray<T>&); template<class T> valarray<T> atan (const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&); template<class T> valarray<T> atan2(const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> atan2(const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> cos (const valarray<T>&); template<class T> valarray<T> cosh (const valarray<T>&); template<class T> valarray<T> exp (const valarray<T>&); template<class T> valarray<T> log (const valarray<T>&); template<class T> valarray<T> log10(const valarray<T>&); template<class T> valarray<T> pow (const valarray<T>&, const valarray<T>&); template<class T> valarray<T> pow (const valarray<T>&, const typename valarray<T>::value_type&); template<class T> valarray<T> pow (const typename valarray<T>::value_type&, const valarray<T>&); template<class T> valarray<T> sin (const valarray<T>&); template<class T> valarray<T> sinh (const valarray<T>&); template<class T> valarray<T> sqrt (const valarray<T>&); template<class T> valarray<T> tan (const valarray<T>&); template<class T> valarray<T> tanh (const valarray<T>&);
Mandates: A unique function with the indicated name can be applied (unqualified) to an operand of type T.
This function returns a value of type T or which can be unambiguously implicitly converted to type T.

29.6.3.4 Specialized algorithms [valarray.special]

template<class T> void swap(valarray<T>& x, valarray<T>& y) noexcept;
Effects: Equivalent to x.swap(y).

29.6.4 Class slice [class.slice]

29.6.4.1 Overview [class.slice.overview]

namespace std { class slice { public: slice(); slice(size_t, size_t, size_t); slice(const slice&); size_t start() const; size_t size() const; size_t stride() const; friend bool operator==(const slice& x, const slice& y); }; }
The slice class represents a BLAS-like slice from an array.
Such a slice is specified by a starting index, a length, and a stride.256
256)256)
BLAS stands for Basic Linear Algebra Subprograms.
C++ programs can instantiate this class.
See, for example, Dongarra, Du Croz, Duff, and Hammerling: A set of Level 3 Basic Linear Algebra Subprograms; Technical Report MCS-P1-0888, Argonne National Laboratory (USA), Mathematics and Computer Science Division, August, 1988.

29.6.4.2 Constructors [cons.slice]

slice(); slice(size_t start, size_t length, size_t stride);
The default constructor is equivalent to slice(0, 0, 0).
A default constructor is provided only to permit the declaration of arrays of slices.
The constructor with arguments for a slice takes a start, length, and stride parameter.
[Example 1: 
slice(3, 8, 2) constructs a slice which selects elements from an array.
— end example]

29.6.4.3 Access functions [slice.access]

size_t start() const; size_t size() const; size_t stride() const;
Returns: The start, length, or stride specified by a slice object.
Complexity: Constant time.

29.6.4.4 Operators [slice.ops]

friend bool operator==(const slice& x, const slice& y);
Effects: Equivalent to: return x.start() == y.start() && x.size() == y.size() && x.stride() == y.stride();

29.6.5 Class template slice_array [template.slice.array]

29.6.5.1 Overview [template.slice.array.overview]

namespace std { template<class T> class slice_array { public: using value_type = T; void operator= (const valarray<T>&) const; void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const; slice_array(const slice_array&); ~slice_array(); const slice_array& operator=(const slice_array&) const; void operator=(const T&) const; slice_array() = delete; // as implied by declaring copy constructor above }; }
This template is a helper template used by the slice subscript operator slice_array<T> valarray<T>::operator[](slice);
It has reference semantics to a subset of an array specified by a slice object.
[Example 1: 
The expression a[slice(1, 5, 3)] = b; has the effect of assigning the elements of b to a slice of the elements in a.
For the slice shown, the elements selected from a are .
— end example]

29.6.5.2 Assignment [slice.arr.assign]

void operator=(const valarray<T>&) const; const slice_array& operator=(const slice_array&) const;
These assignment operators have reference semantics, assigning the values of the argument array elements to selected elements of the valarray<T> object to which the slice_array object refers.

29.6.5.3 Compound assignment [slice.arr.comp.assign]

void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const;
These compound assignments have reference semantics, applying the indicated operation to the elements of the argument array and selected elements of the valarray<T> object to which the slice_array object refers.

29.6.5.4 Fill function [slice.arr.fill]

void operator=(const T&) const;
This function has reference semantics, assigning the value of its argument to the elements of the valarray<T> object to which the slice_array object refers.

29.6.6 The gslice class [class.gslice]

29.6.6.1 Overview [class.gslice.overview]

namespace std { class gslice { public: gslice(); gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d); size_t start() const; valarray<size_t> size() const; valarray<size_t> stride() const; }; }
This class represents a generalized slice out of an array.
A gslice is defined by a starting offset (s), a set of lengths (), and a set of strides ().
The number of lengths shall equal the number of strides.
A gslice represents a mapping from a set of indices (), equal in number to the number of strides, to a single index k.
It is useful for building multidimensional array classes using the valarray template, which is one-dimensional.
The set of one-dimensional index values specified by a gslice are
where the multidimensional indices range in value from 0 to .
[Example 1: 
The gslice specification start = 3 length = {2, 4, 3} stride = {19, 4, 1} yields the sequence of one-dimensional indices
which are ordered as shown in the following table:
	
		(0,  0,  0,   3),    
		(0,  0,  1,   4),    
		(0,  0,  2,   5),    
		(0,  1,  0,   7),    
		(0,  1,  1,   8),    
		(0,  1,  2,   9),    
		(0,  2,  0,  11), 
		(0,  2,  1,  12), 
		(0,  2,  2,  13), 
		(0,  3,  0,  15), 
		(0,  3,  1,  16), 
		(0,  3,  2,  17), 
		(1,  0,  0,  22), 
		(1,  0,  1,  23), 
		      
		(1,  3,  2,  36)
That is, the highest-ordered index turns fastest.
— end example]
It is possible to have degenerate generalized slices in which an address is repeated.
[Example 2: 
If the stride parameters in the previous example are changed to {1, 1, 1}, the first few elements of the resulting sequence of indices will be
	(0,  0,  0,   3),  
	(0,  0,  1,   4),  
	(0,  0,  2,   5),  
	(0,  1,  0,   4),  
	(0,  1,  1,   5),  
	(0,  1,  2,   6),  
	
— end example]
If a degenerate slice is used as the argument to the non-const version of operator[](const gslice&), the behavior is undefined.

29.6.6.2 Constructors [gslice.cons]

gslice(); gslice(size_t start, const valarray<size_t>& lengths, const valarray<size_t>& strides);
The default constructor is equivalent to gslice(0, valarray<size_t>(), valarray<size_t>()).
The constructor with arguments builds a gslice based on a specification of start, lengths, and strides, as explained in the previous subclause.

29.6.6.3 Access functions [gslice.access]

size_t start() const; valarray<size_t> size() const; valarray<size_t> stride() const;
Returns: The representation of the start, lengths, or strides specified for the gslice.
Complexity: start() is constant time.
size() and stride() are linear in the number of strides.

29.6.7 Class template gslice_array [template.gslice.array]

29.6.7.1 Overview [template.gslice.array.overview]

namespace std { template<class T> class gslice_array { public: using value_type = T; void operator= (const valarray<T>&) const; void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const; gslice_array(const gslice_array&); ~gslice_array(); const gslice_array& operator=(const gslice_array&) const; void operator=(const T&) const; gslice_array() = delete; // as implied by declaring copy constructor above }; }
This template is a helper template used by the gslice subscript operator
gslice_array<T> valarray<T>::operator[](const gslice&);
It has reference semantics to a subset of an array specified by a gslice object.
Thus, the expression a[gslice(1, length, stride)] = b has the effect of assigning the elements of b to a generalized slice of the elements in a.

29.6.7.2 Assignment [gslice.array.assign]

void operator=(const valarray<T>&) const; const gslice_array& operator=(const gslice_array&) const;
These assignment operators have reference semantics, assigning the values of the argument array elements to selected elements of the valarray<T> object to which the gslice_array refers.

29.6.7.3 Compound assignment [gslice.array.comp.assign]

void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const;
These compound assignments have reference semantics, applying the indicated operation to the elements of the argument array and selected elements of the valarray<T> object to which the gslice_array object refers.

29.6.7.4 Fill function [gslice.array.fill]

void operator=(const T&) const;
This function has reference semantics, assigning the value of its argument to the elements of the valarray<T> object to which the gslice_array object refers.

29.6.8 Class template mask_array [template.mask.array]

29.6.8.1 Overview [template.mask.array.overview]

namespace std { template<class T> class mask_array { public: using value_type = T; void operator= (const valarray<T>&) const; void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const; mask_array(const mask_array&); ~mask_array(); const mask_array& operator=(const mask_array&) const; void operator=(const T&) const; mask_array() = delete; // as implied by declaring copy constructor above }; }
This template is a helper template used by the mask subscript operator:
mask_array<T> valarray<T>::operator[](const valarray<bool>&);
It has reference semantics to a subset of an array specified by a boolean mask.
Thus, the expression a[mask] = b; has the effect of assigning the elements of b to the masked elements in a (those for which the corresponding element in mask is true).

29.6.8.2 Assignment [mask.array.assign]

void operator=(const valarray<T>&) const; const mask_array& operator=(const mask_array&) const;
These assignment operators have reference semantics, assigning the values of the argument array elements to selected elements of the valarray<T> object to which the mask_array object refers.

29.6.8.3 Compound assignment [mask.array.comp.assign]

void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const;
These compound assignments have reference semantics, applying the indicated operation to the elements of the argument array and selected elements of the valarray<T> object to which the mask_array object refers.

29.6.8.4 Fill function [mask.array.fill]

void operator=(const T&) const;
This function has reference semantics, assigning the value of its argument to the elements of the valarray<T> object to which the mask_array object refers.

29.6.9 Class template indirect_array [template.indirect.array]

29.6.9.1 Overview [template.indirect.array.overview]

namespace std { template<class T> class indirect_array { public: using value_type = T; void operator= (const valarray<T>&) const; void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const; indirect_array(const indirect_array&); ~indirect_array(); const indirect_array& operator=(const indirect_array&) const; void operator=(const T&) const; indirect_array() = delete; // as implied by declaring copy constructor above }; }
This template is a helper template used by the indirect subscript operator
indirect_array<T> valarray<T>::operator[](const valarray<size_t>&);
It has reference semantics to a subset of an array specified by an indirect_array.
Thus, the expression a[​indirect] = b; has the effect of assigning the elements of b to the elements in a whose indices appear in indirect.

29.6.9.2 Assignment [indirect.array.assign]

void operator=(const valarray<T>&) const; const indirect_array& operator=(const indirect_array&) const;
These assignment operators have reference semantics, assigning the values of the argument array elements to selected elements of the valarray<T> object to which it refers.
If the indirect_array specifies an element in the valarray<T> object to which it refers more than once, the behavior is undefined.
[Example 1: 
int addr[] = {2, 3, 1, 4, 4}; valarray<size_t> indirect(addr, 5); valarray<double> a(0., 10), b(1., 5); a[indirect] = b; results in undefined behavior since element 4 is specified twice in the indirection.
— end example]

29.6.9.3 Compound assignment [indirect.array.comp.assign]

void operator*= (const valarray<T>&) const; void operator/= (const valarray<T>&) const; void operator%= (const valarray<T>&) const; void operator+= (const valarray<T>&) const; void operator-= (const valarray<T>&) const; void operator^= (const valarray<T>&) const; void operator&= (const valarray<T>&) const; void operator|= (const valarray<T>&) const; void operator<<=(const valarray<T>&) const; void operator>>=(const valarray<T>&) const;
These compound assignments have reference semantics, applying the indicated operation to the elements of the argument array and selected elements of the valarray<T> object to which the indirect_array object refers.
If the indirect_array specifies an element in the valarray<T> object to which it refers more than once, the behavior is undefined.

29.6.9.4 Fill function [indirect.array.fill]

void operator=(const T&) const;
This function has reference semantics, assigning the value of its argument to the elements of the valarray<T> object to which the indirect_array object refers.

29.6.10 valarray range access [valarray.range]

In the begin and end function templates that follow, unspecified1 is a type that meets the requirements of a mutable Cpp17RandomAccessIterator ([random.access.iterators]) and models contiguous_iterator ([iterator.concept.contiguous]), whose value_type is the template parameter T and whose reference type is T&.
unspecified2 is a type that meets the requirements of a constant Cpp17RandomAccessIterator and models contiguous_iterator, whose value_type is the template parameter T and whose reference type is const T&.
The iterators returned by begin and end for an array are guaranteed to be valid until the member function resize(size_t, T) is called for that array or until the lifetime of that array ends, whichever happens first.
template<class T> unspecified1 begin(valarray<T>& v); template<class T> unspecified2 begin(const valarray<T>& v);
Returns: An iterator referencing the first value in the array.
template<class T> unspecified1 end(valarray<T>& v); template<class T> unspecified2 end(const valarray<T>& v);
Returns: An iterator referencing one past the last value in the array.

29.7 Mathematical functions for floating-point types [c.math]

29.7.1 Header <cmath> synopsis [cmath.syn]

namespace std { using float_t = see below; using double_t = see below; } #define HUGE_VAL see below #define HUGE_VALF see below #define HUGE_VALL see below #define INFINITY see below #define NAN see below #define FP_INFINITE see below #define FP_NAN see below #define FP_NORMAL see below #define FP_SUBNORMAL see below #define FP_ZERO see below #define FP_FAST_FMA see below #define FP_FAST_FMAF see below #define FP_FAST_FMAL see below #define FP_ILOGB0 see below #define FP_ILOGBNAN see below #define MATH_ERRNO see below #define MATH_ERREXCEPT see below #define math_errhandling see below namespace std { constexpr floating-point-type acos(floating-point-type x); constexpr float acosf(float x); constexpr long double acosl(long double x); constexpr floating-point-type asin(floating-point-type x); constexpr float asinf(float x); constexpr long double asinl(long double x); constexpr floating-point-type atan(floating-point-type x); constexpr float atanf(float x); constexpr long double atanl(long double x); constexpr floating-point-type atan2(floating-point-type y, floating-point-type x); constexpr float atan2f(float y, float x); constexpr long double atan2l(long double y, long double x); constexpr floating-point-type cos(floating-point-type x); constexpr float cosf(float x); constexpr long double cosl(long double x); constexpr floating-point-type sin(floating-point-type x); constexpr float sinf(float x); constexpr long double sinl(long double x); constexpr floating-point-type tan(floating-point-type x); constexpr float tanf(float x); constexpr long double tanl(long double x); constexpr floating-point-type acosh(floating-point-type x); constexpr float acoshf(float x); constexpr long double acoshl(long double x); constexpr floating-point-type asinh(floating-point-type x); constexpr float asinhf(float x); constexpr long double asinhl(long double x); constexpr floating-point-type atanh(floating-point-type x); constexpr float atanhf(float x); constexpr long double atanhl(long double x); constexpr floating-point-type cosh(floating-point-type x); constexpr float coshf(float x); constexpr long double coshl(long double x); constexpr floating-point-type sinh(floating-point-type x); constexpr float sinhf(float x); constexpr long double sinhl(long double x); constexpr floating-point-type tanh(floating-point-type x); constexpr float tanhf(float x); constexpr long double tanhl(long double x); constexpr floating-point-type exp(floating-point-type x); constexpr float expf(float x); constexpr long double expl(long double x); constexpr floating-point-type exp2(floating-point-type x); constexpr float exp2f(float x); constexpr long double exp2l(long double x); constexpr floating-point-type expm1(floating-point-type x); constexpr float expm1f(float x); constexpr long double expm1l(long double x); constexpr floating-point-type frexp(floating-point-type value, int* exp); constexpr float frexpf(float value, int* exp); constexpr long double frexpl(long double value, int* exp); constexpr int ilogb(floating-point-type x); constexpr int ilogbf(float x); constexpr int ilogbl(long double x); constexpr floating-point-type ldexp(floating-point-type x, int exp); constexpr float ldexpf(float x, int exp); constexpr long double ldexpl(long double x, int exp); constexpr floating-point-type log(floating-point-type x); constexpr float logf(float x); constexpr long double logl(long double x); constexpr floating-point-type log10(floating-point-type x); constexpr float log10f(float x); constexpr long double log10l(long double x); constexpr floating-point-type log1p(floating-point-type x); constexpr float log1pf(float x); constexpr long double log1pl(long double x); constexpr floating-point-type log2(floating-point-type x); constexpr float log2f(float x); constexpr long double log2l(long double x); constexpr floating-point-type logb(floating-point-type x); constexpr float logbf(float x); constexpr long double logbl(long double x); constexpr floating-point-type modf(floating-point-type value, floating-point-type* iptr); constexpr float modff(float value, float* iptr); constexpr long double modfl(long double value, long double* iptr); constexpr floating-point-type scalbn(floating-point-type x, int n); constexpr float scalbnf(float x, int n); constexpr long double scalbnl(long double x, int n); constexpr floating-point-type scalbln(floating-point-type x, long int n); constexpr float scalblnf(float x, long int n); constexpr long double scalblnl(long double x, long int n); constexpr floating-point-type cbrt(floating-point-type x); constexpr float cbrtf(float x); constexpr long double cbrtl(long double x); // [c.math.abs], absolute values constexpr int abs(int j); // freestanding constexpr long int abs(long int j); // freestanding constexpr long long int abs(long long int j); // freestanding constexpr floating-point-type abs(floating-point-type j); // freestanding-deleted constexpr floating-point-type fabs(floating-point-type x); constexpr float fabsf(float x); constexpr long double fabsl(long double x); constexpr floating-point-type hypot(floating-point-type x, floating-point-type y); constexpr float hypotf(float x, float y); constexpr long double hypotl(long double x, long double y); // [c.math.hypot3], three-dimensional hypotenuse constexpr floating-point-type hypot(floating-point-type x, floating-point-type y, floating-point-type z); constexpr floating-point-type pow(floating-point-type x, floating-point-type y); constexpr float powf(float x, float y); constexpr long double powl(long double x, long double y); constexpr floating-point-type sqrt(floating-point-type x); constexpr float sqrtf(float x); constexpr long double sqrtl(long double x); constexpr floating-point-type erf(floating-point-type x); constexpr float erff(float x); constexpr long double erfl(long double x); constexpr floating-point-type erfc(floating-point-type x); constexpr float erfcf(float x); constexpr long double erfcl(long double x); constexpr floating-point-type lgamma(floating-point-type x); constexpr float lgammaf(float x); constexpr long double lgammal(long double x); constexpr floating-point-type tgamma(floating-point-type x); constexpr float tgammaf(float x); constexpr long double tgammal(long double x); constexpr floating-point-type ceil(floating-point-type x); constexpr float ceilf(float x); constexpr long double ceill(long double x); constexpr floating-point-type floor(floating-point-type x); constexpr float floorf(float x); constexpr long double floorl(long double x); floating-point-type nearbyint(floating-point-type x); float nearbyintf(float x); long double nearbyintl(long double x); floating-point-type rint(floating-point-type x); float rintf(float x); long double rintl(long double x); long int lrint(floating-point-type x); long int lrintf(float x); long int lrintl(long double x); long long int llrint(floating-point-type x); long long int llrintf(float x); long long int llrintl(long double x); constexpr floating-point-type round(floating-point-type x); constexpr float roundf(float x); constexpr long double roundl(long double x); constexpr long int lround(floating-point-type x); constexpr long int lroundf(float x); constexpr long int lroundl(long double x); constexpr long long int llround(floating-point-type x); constexpr long long int llroundf(float x); constexpr long long int llroundl(long double x); constexpr floating-point-type trunc(floating-point-type x); constexpr float truncf(float x); constexpr long double truncl(long double x); constexpr floating-point-type fmod(floating-point-type x, floating-point-type y); constexpr float fmodf(float x, float y); constexpr long double fmodl(long double x, long double y); constexpr floating-point-type remainder(floating-point-type x, floating-point-type y); constexpr float remainderf(float x, float y); constexpr long double remainderl(long double x, long double y); constexpr floating-point-type remquo(floating-point-type x, floating-point-type y, int* quo); constexpr float remquof(float x, float y, int* quo); constexpr long double remquol(long double x, long double y, int* quo); constexpr floating-point-type copysign(floating-point-type x, floating-point-type y); constexpr float copysignf(float x, float y); constexpr long double copysignl(long double x, long double y); double nan(const char* tagp); float nanf(const char* tagp); long double nanl(const char* tagp); constexpr floating-point-type nextafter(floating-point-type x, floating-point-type y); constexpr float nextafterf(float x, float y); constexpr long double nextafterl(long double x, long double y); constexpr floating-point-type nexttoward(floating-point-type x, long double y); constexpr float nexttowardf(float x, long double y); constexpr long double nexttowardl(long double x, long double y); constexpr floating-point-type fdim(floating-point-type x, floating-point-type y); constexpr float fdimf(float x, float y); constexpr long double fdiml(long double x, long double y); constexpr floating-point-type fmax(floating-point-type x, floating-point-type y); constexpr float fmaxf(float x, float y); constexpr long double fmaxl(long double x, long double y); constexpr floating-point-type fmin(floating-point-type x, floating-point-type y); constexpr float fminf(float x, float y); constexpr long double fminl(long double x, long double y); constexpr floating-point-type fma(floating-point-type x, floating-point-type y, floating-point-type z); constexpr float fmaf(float x, float y, float z); constexpr long double fmal(long double x, long double y, long double z); // [c.math.lerp], linear interpolation constexpr floating-point-type lerp(floating-point-type a, floating-point-type b, floating-point-type t) noexcept; // [c.math.fpclass], classification / comparison functions constexpr int fpclassify(floating-point-type x); constexpr bool isfinite(floating-point-type x); constexpr bool isinf(floating-point-type x); constexpr bool isnan(floating-point-type x); constexpr bool isnormal(floating-point-type x); constexpr bool signbit(floating-point-type x); constexpr bool isgreater(floating-point-type x, floating-point-type y); constexpr bool isgreaterequal(floating-point-type x, floating-point-type y); constexpr bool isless(floating-point-type x, floating-point-type y); constexpr bool islessequal(floating-point-type x, floating-point-type y); constexpr bool islessgreater(floating-point-type x, floating-point-type y); constexpr bool isunordered(floating-point-type x, floating-point-type y); // [sf.cmath], mathematical special functions // [sf.cmath.assoc.laguerre], associated Laguerre polynomials floating-point-type assoc_laguerre(unsigned n, unsigned m, floating-point-type x); float assoc_laguerref(unsigned n, unsigned m, float x); long double assoc_laguerrel(unsigned n, unsigned m, long double x); // [sf.cmath.assoc.legendre], associated Legendre functions floating-point-type assoc_legendre(unsigned l, unsigned m, floating-point-type x); float assoc_legendref(unsigned l, unsigned m, float x); long double assoc_legendrel(unsigned l, unsigned m, long double x); // [sf.cmath.beta], beta function floating-point-type beta(floating-point-type x, floating-point-type y); float betaf(float x, float y); long double betal(long double x, long double y); // [sf.cmath.comp.ellint.1], complete elliptic integral of the first kind floating-point-type comp_ellint_1(floating-point-type k); float comp_ellint_1f(float k); long double comp_ellint_1l(long double k); // [sf.cmath.comp.ellint.2], complete elliptic integral of the second kind floating-point-type comp_ellint_2(floating-point-type k); float comp_ellint_2f(float k); long double comp_ellint_2l(long double k); // [sf.cmath.comp.ellint.3], complete elliptic integral of the third kind floating-point-type comp_ellint_3(floating-point-type k, floating-point-type nu); float comp_ellint_3f(float k, float nu); long double comp_ellint_3l(long double k, long double nu); // [sf.cmath.cyl.bessel.i], regular modified cylindrical Bessel functions floating-point-type cyl_bessel_i(floating-point-type nu, floating-point-type x); float cyl_bessel_if(float nu, float x); long double cyl_bessel_il(long double nu, long double x); // [sf.cmath.cyl.bessel.j], cylindrical Bessel functions of the first kind floating-point-type cyl_bessel_j(floating-point-type nu, floating-point-type x); float cyl_bessel_jf(float nu, float x); long double cyl_bessel_jl(long double nu, long double x); // [sf.cmath.cyl.bessel.k], irregular modified cylindrical Bessel functions floating-point-type cyl_bessel_k(floating-point-type nu, floating-point-type x); float cyl_bessel_kf(float nu, float x); long double cyl_bessel_kl(long double nu, long double x); // [sf.cmath.cyl.neumann], cylindrical Neumann functions // cylindrical Bessel functions of the second kind floating-point-type cyl_neumann(floating-point-type nu, floating-point-type x); float cyl_neumannf(float nu, float x); long double cyl_neumannl(long double nu, long double x); // [sf.cmath.ellint.1], incomplete elliptic integral of the first kind floating-point-type ellint_1(floating-point-type k, floating-point-type phi); float ellint_1f(float k, float phi); long double ellint_1l(long double k, long double phi); // [sf.cmath.ellint.2], incomplete elliptic integral of the second kind floating-point-type ellint_2(floating-point-type k, floating-point-type phi); float ellint_2f(float k, float phi); long double ellint_2l(long double k, long double phi); // [sf.cmath.ellint.3], incomplete elliptic integral of the third kind floating-point-type ellint_3(floating-point-type k, floating-point-type nu, floating-point-type phi); float ellint_3f(float k, float nu, float phi); long double ellint_3l(long double k, long double nu, long double phi); // [sf.cmath.expint], exponential integral floating-point-type expint(floating-point-type x); float expintf(float x); long double expintl(long double x); // [sf.cmath.hermite], Hermite polynomials floating-point-type hermite(unsigned n, floating-point-type x); float hermitef(unsigned n, float x); long double hermitel(unsigned n, long double x); // [sf.cmath.laguerre], Laguerre polynomials floating-point-type laguerre(unsigned n, floating-point-type x); float laguerref(unsigned n, float x); long double laguerrel(unsigned n, long double x); // [sf.cmath.legendre], Legendre polynomials floating-point-type legendre(unsigned l, floating-point-type x); float legendref(unsigned l, float x); long double legendrel(unsigned l, long double x); // [sf.cmath.riemann.zeta], Riemann zeta function floating-point-type riemann_zeta(floating-point-type x); float riemann_zetaf(float x); long double riemann_zetal(long double x); // [sf.cmath.sph.bessel], spherical Bessel functions of the first kind floating-point-type sph_bessel(unsigned n, floating-point-type x); float sph_besself(unsigned n, float x); long double sph_bessell(unsigned n, long double x); // [sf.cmath.sph.legendre], spherical associated Legendre functions floating-point-type sph_legendre(unsigned l, unsigned m, floating-point-type theta); float sph_legendref(unsigned l, unsigned m, float theta); long double sph_legendrel(unsigned l, unsigned m, long double theta); // [sf.cmath.sph.neumann], spherical Neumann functions; // spherical Bessel functions of the second kind floating-point-type sph_neumann(unsigned n, floating-point-type x); float sph_neumannf(unsigned n, float x); long double sph_neumannl(unsigned n, long double x); }
The contents and meaning of the header <cmath> are the same as the C standard library header <math.h>, with the addition of a three-dimensional hypotenuse function, a linear interpolation function, and the mathematical special functions described in [sf.cmath].
[Note 1: 
Several functions have additional overloads in this document, but they have the same behavior as in the C standard library.
— end note]
For each function with at least one parameter of type floating-point-type, the implementation provides an overload for each cv-unqualified floating-point type ([basic.fundamental]) where all uses of floating-point-type in the function signature are replaced with that floating-point type.
For each function with at least one parameter of type floating-point-type other than abs, the implementation also provides additional overloads sufficient to ensure that, if every argument corresponding to a floating-point-type parameter has arithmetic type, then every such argument is effectively cast to the floating-point type with the greatest floating-point conversion rank and greatest floating-point conversion subrank among the types of all such arguments, where arguments of integer type are considered to have the same floating-point conversion rank as double.
If no such floating-point type with the greatest rank and subrank exists, then overload resolution does not result in a usable candidate ([over.match.general]) from the overloads provided by the implementation.
An invocation of nexttoward is ill-formed if the argument corresponding to the floating-point-type parameter has extended floating-point type.
See also: ISO/IEC 9899:2018, 7.12

29.7.2 Absolute values [c.math.abs]

[Note 1: 
The headers <cstdlib> and <cmath> declare the functions described in this subclause.
— end note]
constexpr int abs(int j); constexpr long int abs(long int j); constexpr long long int abs(long long int j);
Effects: These functions have the semantics specified in the C standard library for the functions abs, labs, and llabs, respectively.
Remarks: If abs is called with an argument of type X for which is_unsigned_v<X> is true and if X cannot be converted to int by integral promotion, the program is ill-formed.
[Note 2: 
Allowing arguments that can be promoted to int provides compatibility with C.
— end note]
constexpr floating-point-type abs(floating-point-type x);
Returns: The absolute value of x.
See also: ISO/IEC 9899:2018, 7.12.7.2, 7.22.6.1

29.7.3 Three-dimensional hypotenuse [c.math.hypot3]

constexpr floating-point-type hypot(floating-point-type x, floating-point-type y, floating-point-type z);
Returns: .

29.7.4 Linear interpolation [c.math.lerp]

constexpr floating-point-type lerp(floating-point-type a, floating-point-type b, floating-point-type t) noexcept;
Returns: .
Remarks: Let r be the value returned.
If isfinite(a) && isfinite(b), then:
  • If t == 0, then r == a.
  • If t == 1, then r == b.
  • If t >= 0 && t <= 1, then isfinite(r).
  • If isfinite(t) && a == b, then r == a.
  • If isfinite(t) || !isnan(t) && b-a != 0, then !isnan(r).
Let CMP(x,y) be 1 if x > y, -1 if x < y, and 0 otherwise.
For any t1 and t2, the product of CMP(lerp(a, b, t2), lerp(a, b, t1)), CMP(t2, t1), and CMP(b, a) is non-negative.

29.7.5 Classification / comparison functions [c.math.fpclass]

The classification / comparison functions behave the same as the C macros with the corresponding names defined in the C standard library.
See also: ISO/IEC 9899:2018, 7.12.3, 7.12.4

29.7.6 Mathematical special functions [sf.cmath]

29.7.6.1 General [sf.cmath.general]

If any argument value to any of the functions specified in [sf.cmath] is a NaN (Not a Number), the function shall return a NaN but it shall not report a domain error.
Otherwise, the function shall report a domain error for just those argument values for which:
  • the function description's Returns: element explicitly specifies a domain and those argument values fall outside the specified domain, or
  • the corresponding mathematical function value has a nonzero imaginary component, or
  • the corresponding mathematical function is not mathematically defined.257
Unless otherwise specified, each function is defined for all finite values, for negative infinity, and for positive infinity.
257)257)
A mathematical function is mathematically defined for a given set of argument values (a) if it is explicitly defined for that set of argument values, or (b) if its limiting value exists and does not depend on the direction of approach.

29.7.6.2 Associated Laguerre polynomials [sf.cmath.assoc.laguerre]

floating-point-type assoc_laguerre(unsigned n, unsigned m, floating-point-type x); float assoc_laguerref(unsigned n, unsigned m, float x); long double assoc_laguerrel(unsigned n, unsigned m, long double x);
Effects: These functions compute the associated Laguerre polynomials of their respective arguments n, m, and x.
Returns: , where is given by Formula 29.22, is given by Formula 29.37, n is n, m is m, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if n >= 128 or if m >= 128.

29.7.6.3 Associated Legendre functions [sf.cmath.assoc.legendre]

floating-point-type assoc_legendre(unsigned l, unsigned m, floating-point-type x); float assoc_legendref(unsigned l, unsigned m, float x); long double assoc_legendrel(unsigned l, unsigned m, long double x);
Effects: These functions compute the associated Legendre functions of their respective arguments l, m, and x.
Returns: , where is given by Formula 29.23, is given by Formula 29.38, is l, m is m, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if l >= 128.

29.7.6.4 Beta function [sf.cmath.beta]

floating-point-type beta(floating-point-type x, floating-point-type y); float betaf(float x, float y); long double betal(long double x, long double y);
Effects: These functions compute the beta function of their respective arguments x and y.
Returns: , where B is given by Formula 29.24, x is x and y is y.

29.7.6.5 Complete elliptic integral of the first kind [sf.cmath.comp.ellint.1]

floating-point-type comp_ellint_1(floating-point-type k); float comp_ellint_1f(float k); long double comp_ellint_1l(long double k);
Effects: These functions compute the complete elliptic integral of the first kind of their respective arguments k.
Returns: K(k), where K is given by Formula 29.25 and k is k.

29.7.6.6 Complete elliptic integral of the second kind [sf.cmath.comp.ellint.2]

floating-point-type comp_ellint_2(floating-point-type k); float comp_ellint_2f(float k); long double comp_ellint_2l(long double k);
Effects: These functions compute the complete elliptic integral of the second kind of their respective arguments k.
Returns: E(k), where E is given by Formula 29.26 and k is k.

29.7.6.7 Complete elliptic integral of the third kind [sf.cmath.comp.ellint.3]

floating-point-type comp_ellint_3(floating-point-type k, floating-point-type nu); float comp_ellint_3f(float k, float nu); long double comp_ellint_3l(long double k, long double nu);
Effects: These functions compute the complete elliptic integral of the third kind of their respective arguments k and nu.
Returns: , where Π is given by Formula 29.27, k is k, and ν is nu.

29.7.6.8 Regular modified cylindrical Bessel functions [sf.cmath.cyl.bessel.i]

floating-point-type cyl_bessel_i(floating-point-type nu, floating-point-type x); float cyl_bessel_if(float nu, float x); long double cyl_bessel_il(long double nu, long double x);
Effects: These functions compute the regular modified cylindrical Bessel functions of their respective arguments nu and x.
Returns: , where is given by Formula 29.28, ν is nu, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if nu >= 128.

29.7.6.9 Cylindrical Bessel functions of the first kind [sf.cmath.cyl.bessel.j]

floating-point-type cyl_bessel_j(floating-point-type nu, floating-point-type x); float cyl_bessel_jf(float nu, float x); long double cyl_bessel_jl(long double nu, long double x);
Effects: These functions compute the cylindrical Bessel functions of the first kind of their respective arguments nu and x.
Returns: , where is given by Formula 29.29, ν is nu, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if nu >= 128.

29.7.6.10 Irregular modified cylindrical Bessel functions [sf.cmath.cyl.bessel.k]

floating-point-type cyl_bessel_k(floating-point-type nu, floating-point-type x); float cyl_bessel_kf(float nu, float x); long double cyl_bessel_kl(long double nu, long double x);
Effects: These functions compute the irregular modified cylindrical Bessel functions of their respective arguments nu and x.
Returns: , where is given by Formula 29.30, ν is nu, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if nu >= 128.

29.7.6.11 Cylindrical Neumann functions [sf.cmath.cyl.neumann]

floating-point-type cyl_neumann(floating-point-type nu, floating-point-type x); float cyl_neumannf(float nu, float x); long double cyl_neumannl(long double nu, long double x);
Effects: These functions compute the cylindrical Neumann functions, also known as the cylindrical Bessel functions of the second kind, of their respective arguments nu and x.
Returns: , where is given by Formula 29.31, ν is nu, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if nu >= 128.

29.7.6.12 Incomplete elliptic integral of the first kind [sf.cmath.ellint.1]

floating-point-type ellint_1(floating-point-type k, floating-point-type phi); float ellint_1f(float k, float phi); long double ellint_1l(long double k, long double phi);
Effects: These functions compute the incomplete elliptic integral of the first kind of their respective arguments k and phi (phi measured in radians).
Returns: F(k, φ), where F is given by Formula 29.32, k is k, and φ is phi.

29.7.6.13 Incomplete elliptic integral of the second kind [sf.cmath.ellint.2]

floating-point-type ellint_2(floating-point-type k, floating-point-type phi); float ellint_2f(float k, float phi); long double ellint_2l(long double k, long double phi);
Effects: These functions compute the incomplete elliptic integral of the second kind of their respective arguments k and phi (phi measured in radians).
Returns: E(k, φ), where E is given by Formula 29.33, k is k, and φ is phi.

29.7.6.14 Incomplete elliptic integral of the third kind [sf.cmath.ellint.3]

floating-point-type ellint_3(floating-point-type k, floating-point-type nu, floating-point-type phi); float ellint_3f(float k, float nu, float phi); long double ellint_3l(long double k, long double nu, long double phi);
Effects: These functions compute the incomplete elliptic integral of the third kind of their respective arguments k, nu, and phi (phi measured in radians).
Returns: , where Π is given by Formula 29.34, ν is nu, k is k, and φ is phi.

29.7.6.15 Exponential integral [sf.cmath.expint]

floating-point-type expint(floating-point-type x); float expintf(float x); long double expintl(long double x);
Effects: These functions compute the exponential integral of their respective arguments x.
Returns: Ei(x), where Ei is given by Formula 29.35 and x is x.

29.7.6.16 Hermite polynomials [sf.cmath.hermite]

floating-point-type hermite(unsigned n, floating-point-type x); float hermitef(unsigned n, float x); long double hermitel(unsigned n, long double x);
Effects: These functions compute the Hermite polynomials of their respective arguments n and x.
Returns: , where is given by Formula 29.36, n is n, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if n >= 128.

29.7.6.17 Laguerre polynomials [sf.cmath.laguerre]

floating-point-type laguerre(unsigned n, floating-point-type x); float laguerref(unsigned n, float x); long double laguerrel(unsigned n, long double x);
Effects: These functions compute the Laguerre polynomials of their respective arguments n and x.
Returns: , where is given by Formula 29.37, n is n, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if n >= 128.

29.7.6.18 Legendre polynomials [sf.cmath.legendre]

floating-point-type legendre(unsigned l, floating-point-type x); float legendref(unsigned l, float x); long double legendrel(unsigned l, long double x);
Effects: These functions compute the Legendre polynomials of their respective arguments l and x.
Returns: , where is given by Formula 29.38, l is l, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if l >= 128.

29.7.6.19 Riemann zeta function [sf.cmath.riemann.zeta]

floating-point-type riemann_zeta(floating-point-type x); float riemann_zetaf(float x); long double riemann_zetal(long double x);
Effects: These functions compute the Riemann zeta function of their respective arguments x.
Returns: ζ(x), where ζ is given by Formula 29.39 and x is x.

29.7.6.20 Spherical Bessel functions of the first kind [sf.cmath.sph.bessel]

floating-point-type sph_bessel(unsigned n, floating-point-type x); float sph_besself(unsigned n, float x); long double sph_bessell(unsigned n, long double x);
Effects: These functions compute the spherical Bessel functions of the first kind of their respective arguments n and x.
Returns: , where is given by Formula 29.40, n is n, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if n >= 128.

29.7.6.21 Spherical associated Legendre functions [sf.cmath.sph.legendre]

floating-point-type sph_legendre(unsigned l, unsigned m, floating-point-type theta); float sph_legendref(unsigned l, unsigned m, float theta); long double sph_legendrel(unsigned l, unsigned m, long double theta);
Effects: These functions compute the spherical associated Legendre functions of their respective arguments l, m, and theta (theta measured in radians).
Returns: , where is given by Formula 29.41, l is l, m is m, and θ is theta.
Remarks: The effect of calling each of these functions is implementation-defined if l >= 128.

29.7.6.22 Spherical Neumann functions [sf.cmath.sph.neumann]

floating-point-type sph_neumann(unsigned n, floating-point-type x); float sph_neumannf(unsigned n, float x); long double sph_neumannl(unsigned n, long double x);
Effects: These functions compute the spherical Neumann functions, also known as the spherical Bessel functions of the second kind, of their respective arguments n and x.
Returns: , where is given by Formula 29.42, n is n, and x is x.
Remarks: The effect of calling each of these functions is implementation-defined if n >= 128.

29.8 Numbers [numbers]

29.8.1 Header <numbers> synopsis [numbers.syn]

namespace std::numbers { template<class T> constexpr T e_v = unspecified; template<class T> constexpr T log2e_v = unspecified; template<class T> constexpr T log10e_v = unspecified; template<class T> constexpr T pi_v = unspecified; template<class T> constexpr T inv_pi_v = unspecified; template<class T> constexpr T inv_sqrtpi_v = unspecified; template<class T> constexpr T ln2_v = unspecified; template<class T> constexpr T ln10_v = unspecified; template<class T> constexpr T sqrt2_v = unspecified; template<class T> constexpr T sqrt3_v = unspecified; template<class T> constexpr T inv_sqrt3_v = unspecified; template<class T> constexpr T egamma_v = unspecified; template<class T> constexpr T phi_v = unspecified; template<floating_point T> constexpr T e_v<T> = see below; template<floating_point T> constexpr T log2e_v<T> = see below; template<floating_point T> constexpr T log10e_v<T> = see below; template<floating_point T> constexpr T pi_v<T> = see below; template<floating_point T> constexpr T inv_pi_v<T> = see below; template<floating_point T> constexpr T inv_sqrtpi_v<T> = see below; template<floating_point T> constexpr T ln2_v<T> = see below; template<floating_point T> constexpr T ln10_v<T> = see below; template<floating_point T> constexpr T sqrt2_v<T> = see below; template<floating_point T> constexpr T sqrt3_v<T> = see below; template<floating_point T> constexpr T inv_sqrt3_v<T> = see below; template<floating_point T> constexpr T egamma_v<T> = see below; template<floating_point T> constexpr T phi_v<T> = see below; inline constexpr double e = e_v<double>; inline constexpr double log2e = log2e_v<double>; inline constexpr double log10e = log10e_v<double>; inline constexpr double pi = pi_v<double>; inline constexpr double inv_pi = inv_pi_v<double>; inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>; inline constexpr double ln2 = ln2_v<double>; inline constexpr double ln10 = ln10_v<double>; inline constexpr double sqrt2 = sqrt2_v<double>; inline constexpr double sqrt3 = sqrt3_v<double>; inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>; inline constexpr double egamma = egamma_v<double>; inline constexpr double phi = phi_v<double>; }

29.8.2 Mathematical constants [math.constants]

The library-defined partial specializations of mathematical constant variable templates are initialized with the nearest representable values of e, , , π, , , ln2, ln10, , , , the Euler-Mascheroni γ constant, and the golden ratio φ constant , respectively.
Pursuant to [namespace.std], a program may partially or explicitly specialize a mathematical constant variable template provided that the specialization depends on a program-defined type.
A program that instantiates a primary template of a mathematical constant variable template is ill-formed.

29.9 Basic linear algebra algorithms [linalg]

29.9.1 Overview [linalg.overview]

Subclause [linalg] defines basic linear algebra algorithms.
The algorithms that access the elements of arrays view those elements through mdspan ([views.multidim]).

29.9.2 Header <linalg> synopsis [linalg.syn]

namespace std::linalg { // [linalg.tags.order], storage order tags struct column_major_t; inline constexpr column_major_t column_major; struct row_major_t; inline constexpr row_major_t row_major; // [linalg.tags.triangle], triangle tags struct upper_triangle_t; inline constexpr upper_triangle_t upper_triangle; struct lower_triangle_t; inline constexpr lower_triangle_t lower_triangle; // [linalg.tags.diagonal], diagonal tags struct implicit_unit_diagonal_t; inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal; struct explicit_diagonal_t; inline constexpr explicit_diagonal_t explicit_diagonal; // [linalg.layout.packed], class template layout_blas_packed template<class Triangle, class StorageOrder> class layout_blas_packed; // [linalg.helpers], exposition-only helpers // [linalg.helpers.concepts], linear algebra argument concepts template<class T> constexpr bool is-mdspan = see below; // exposition only template<class T> concept in-vector = see below; // exposition only template<class T> concept out-vector = see below; // exposition only template<class T> concept inout-vector = see below; // exposition only template<class T> concept in-matrix = see below; // exposition only template<class T> concept out-matrix = see below; // exposition only template<class T> concept inout-matrix = see below; // exposition only template<class T> concept possibly-packed-inout-matrix = see below; // exposition only template<class T> concept in-object = see below; // exposition only template<class T> concept out-object = see below; // exposition only template<class T> concept inout-object = see below; // exposition only // [linalg.scaled], scaled in-place transformation // [linalg.scaled.scaledaccessor], class template scaled_accessor template<class ScalingFactor, class NestedAccessor> class scaled_accessor; // [linalg.scaled.scaled], function template scaled template<class ScalingFactor, class ElementType, class Extents, class Layout, class Accessor> constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x); // [linalg.conj], conjugated in-place transformation // [linalg.conj.conjugatedaccessor], class template conjugated_accessor template<class NestedAccessor> class conjugated_accessor; // [linalg.conj.conjugated], function template conjugated template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a); // [linalg.transp], transpose in-place transformation // [linalg.transp.layout.transpose], class template layout_transpose template<class Layout> class layout_transpose; // [linalg.transp.transposed], function template transposed template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a); // [linalg.conjtransposed], conjugated transpose in-place transformation template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a); // [linalg.algs.blas1], BLAS 1 algorithms // [linalg.algs.blas1.givens], Givens rotations // [linalg.algs.blas1.givens.lartg], compute Givens rotation template<class Real> struct setup_givens_rotation_result { Real c; Real s; Real r; }; template<class Real> struct setup_givens_rotation_result<complex<Real>> { Real c; complex<Real> s; complex<Real> r; }; template<class Real> setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept; template<class Real> setup_givens_rotation_result<complex<Real>> setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept; // [linalg.algs.blas1.givens.rot], apply computed Givens rotation template<inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, Real s); template<inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s); template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, complex<Real> s); // [linalg.algs.blas1.swap], swap elements template<inout-object InOutObj1, inout-object InOutObj2> void swap_elements(InOutObj1 x, InOutObj2 y); template<class ExecutionPolicy, inout-object InOutObj1, inout-object InOutObj2> void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y); // [linalg.algs.blas1.scal], multiply elements by scalar template<class Scalar, inout-object InOutObj> void scale(Scalar alpha, InOutObj x); template<class ExecutionPolicy, class Scalar, inout-object InOutObj> void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); // [linalg.algs.blas1.copy], copy elements template<in-object InObj, out-object OutObj> void copy(InObj x, OutObj y); template<class ExecutionPolicy, in-object InObj, out-object OutObj> void copy(ExecutionPolicy&& exec, InObj x, OutObj y); // [linalg.algs.blas1.add], add elementwise template<in-object InObj1, in-object InObj2, out-object OutObj> void add(InObj1 x, InObj2 y, OutObj z); template<class ExecutionPolicy, in-object InObj1, in-object InObj2, out-object OutObj> void add(ExecutionPolicy&& exec, InObj1 x, InObj2 y, OutObj z); // [linalg.algs.blas1.dot], dot product of two vectors template<in-vector InVec1, in-vector InVec2, class Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar> Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); template<in-vector InVec1, in-vector InVec2> auto dot(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2> auto dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2); template<in-vector InVec1, in-vector InVec2, class Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar> Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init); template<in-vector InVec1, in-vector InVec2> auto dotc(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2> auto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2); // [linalg.algs.blas1.ssq], scaled sum of squares of a vector's elements template<class Scalar> struct sum_of_squares_result { Scalar scaling_factor; Scalar scaled_sum_of_squares; }; template<in-vector InVec, class Scalar> sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init); template<class ExecutionPolicy, in-vector InVec, class Scalar> sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec, InVec v, sum_of_squares_result<Scalar> init); // [linalg.algs.blas1.nrm2], Euclidean norm of a vector template<in-vector InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); template<class ExecutionPolicy, in-vector InVec, class Scalar> Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); template<in-vector InVec> auto vector_two_norm(InVec v); template<class ExecutionPolicy, in-vector InVec> auto vector_two_norm(ExecutionPolicy&& exec, InVec v); // [linalg.algs.blas1.asum], sum of absolute values of vector elements template<in-vector InVec, class Scalar> Scalar vector_abs_sum(InVec v, Scalar init); template<class ExecutionPolicy, in-vector InVec, class Scalar> Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); template<in-vector InVec> auto vector_abs_sum(InVec v); template<class ExecutionPolicy, in-vector InVec> auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); // [linalg.algs.blas1.iamax], index of maximum absolute value of vector elements template<in-vector InVec> typename InVec::extents_type vector_idx_abs_max(InVec v); template<class ExecutionPolicy, in-vector InVec> typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); // [linalg.algs.blas1.matfrobnorm], Frobenius norm of a matrix template<in-matrix InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<in-matrix InMat> auto matrix_frob_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); // [linalg.algs.blas1.matonenorm], one norm of a matrix template<in-matrix InMat, class Scalar> Scalar matrix_one_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<in-matrix InMat> auto matrix_one_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); // [linalg.algs.blas1.matinfnorm], infinity norm of a matrix template<in-matrix InMat, class Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); template<in-matrix InMat> auto matrix_inf_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); // [linalg.algs.blas2], BLAS 2 algorithms // [linalg.algs.blas2.gemv], general matrix-vector product template<in-matrix InMat, in-vector InVec, out-vector OutVec> void matrix_vector_product(InMat A, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, in-vector InVec, out-vector OutVec> void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y); template<in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec> void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec> void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec1 x, InVec2 y, OutVec z); // [linalg.algs.blas2.symv], symmetric matrix-vector product template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void symmetric_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y); template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void symmetric_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); // [linalg.algs.blas2.hemv], Hermitian matrix-vector product template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void hermitian_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y); template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void hermitian_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); // [linalg.algs.blas2.trmv], triangular matrix-vector product // Overwriting triangular matrix-vector product template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); // In-place triangular matrix-vector product template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec y); // Updating triangular matrix-vector product template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec1, in-vector InVec2, out-vector OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec1, in-vector InVec2, out-vector OutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z); // [linalg.algs.blas2.trsv], solve a triangular linear system // Solve a triangular linear system, not in place template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x, BinaryDivideOp divide); template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); // Solve a triangular linear system, in place template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide); template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec b); // [linalg.algs.blas2.rank1], nonsymmetric rank-1 matrix update template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); // [linalg.algs.blas2.symherrank1], symmetric or Hermitian rank-1 matrix update template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t); template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t); template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); // [linalg.algs.blas2.rank2], symmetric and Hermitian rank-2 matrix updates // symmetric rank-2 matrix update template<in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A, Triangle t); // Hermitian rank-2 matrix update template<in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A, Triangle t); // [linalg.algs.blas3], BLAS 3 algorithms // [linalg.algs.blas3.gemm], general matrix-matrix product template<in-matrix InMat1, in-matrix InMat2, out-matrix OutMat> void matrix_product(InMat1 A, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, out-matrix OutMat> void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C); template<in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C); // [linalg.algs.blas3.xxmm], symmetric, Hermitian, and triangular matrix-matrix product template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, out-matrix OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C); // [linalg.algs.blas3.trmm], in-place triangular matrix-matrix product template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_left_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_right_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C); // [linalg.algs.blas3.rankk], rank-k update of a symmetric or Hermitian matrix // rank-k symmetric matrix update template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t); template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t); // rank-k Hermitian matrix update template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t); template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t); // [linalg.algs.blas3.rank2k], rank-2k update of a symmetric or Hermitian matrix // rank-2k symmetric matrix update template<in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InOutMat C, Triangle t); // rank-2k Hermitian matrix update template<in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InOutMat C, Triangle t); // [linalg.algs.blas3.trsm], solve multiple triangular linear systems // solve multiple triangular systems on the left, not-in-place template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); // solve multiple triangular systems on the right, not-in-place template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X); // solve multiple triangular systems on the left, in-place template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B); // solve multiple triangular systems on the right, in-place template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B); }

29.9.3 General [linalg.general]

For the effects of all functions in [linalg], when the effects are described as “computes ” or “compute ” (for some R and mathematical expression E), the following apply:
  • E has the conventional mathematical meaning as written.
  • The pattern should be read as “the transpose of x.
  • The pattern should be read as “the conjugate transpose of x.
  • When R is the same name as a function parameter whose type is a template parameter with Out in its name, the intent is that the result of the computation is written to the elements of the function parameter R.
Some of the functions and types in [linalg] distinguish between the “rows” and the “columns” of a matrix.
For a matrix A and a multidimensional index i, j in A.extents(),
  • row i of A is the set of elements A[i, k1] for all k1 such that i, k1 is in A.extents(); and
  • column j of A is the set of elements A[k0, j] for all k0 such that k0, j is in A.extents().
Some of the functions in [linalg] distinguish between the “upper triangle,” “lower triangle,” and “diagonal” of a matrix.
  • The diagonal is the set of all elements of A accessed by A[i,i] for 0  ≤  i < min(A.extent(0), A.extent(1)).
  • The upper triangle of a matrix A is the set of all elements of A accessed by A[i,j] with i  ≤  j.
    It includes the diagonal.
  • The lower triangle of A is the set of all elements of A accessed by A[i,j] with i  ≥  j.
    It includes the diagonal.
For any function F that takes a parameter named t, t applies to accesses done through the parameter preceding t in the parameter list of F.
Let m be such an access-modified function parameter.
F will only access the triangle of m specified by t.
For accesses m[i, j] outside the triangle specified by t, F will use the value
  • conj-if-needed(m[j, i]) if the name of F starts with hermitian,
  • m[j, i] if the name of F starts with symmetric, or
  • the additive identity if the name of F starts with triangular.
[Example 1: 
Small vector product accessing only specified triangle.
It would not be a precondition violation for the non-accessed matrix element to be non-zero.
template<class Triangle> void triangular_matrix_vector_2x2_product( mdspan<const float, extents<int, 2, 2>> m, Triangle t, mdspan<const float, extents<int, 2>> x, mdspan<float, extents<int, 2>> y) { static_assert(is_same_v<Triangle, lower_triangle_t> || is_same_v<Triangle, upper_triangle_t>); if constexpr (is_same_v<Triangle, lower_triangle_t>) { y[0] = m[0,0] * x[0]; // + 0 * x[1] y[1] = m[1,0] * x[0] + m[1,1] * x[1]; } else { // upper_triangle_t y[0] = m[0,0] * x[0] + m[0,1] * x[1]; y[1] = /* 0 * x[0] + */ m[1,1] * x[1]; } } — end example]
For any function F that takes a parameter named d, d applies to accesses done through the previous-of-the-previous parameter of d in the parameter list of F.
Let m be such an access-modified function parameter.
If d specifies that an implicit unit diagonal is to be assumed, then
  • F will not access the diagonal of m; and
  • the algorithm will interpret m as if it has a unit diagonal, that is, a diagonal each of whose elements behaves as a two-sided multiplicative identity (even if m's value type does not have a two-sided multiplicative identity).
Otherwise, if d specifies that an explicit diagonal is to be assumed, then F will access the diagonal of m.
Within all the functions in [linalg], any calls to abs, conj, imag, and real are unqualified.
Two mdspan objects x and y alias each other, if they have the same extents e, and for every pack of integers i which is a multidimensional index in e, x[i...] and y[i...] refer to the same element.
[Note 1: 
This means that x and y view the same elements in the same order.
— end note]
Two mdspan objects x and y overlap each other, if for some pack of integers i that is a multidimensional index in x.extents(), there exists a pack of integers j that is a multidimensional index in y.extents(), such that x[i....] and y[j...] refer to the same element.
[Note 2: 
Aliasing is a special case of overlapping.
If x and y do not overlap, then they also do not alias each other.
— end note]

29.9.4 Requirements [linalg.reqs]

29.9.4.1 Linear algebra value types [linalg.reqs.val]

Throughout [linalg], the following types are linear algebra value types:
  • the value_type type alias of any input or output mdspan parameter(s) of any function in [linalg]; and
  • the Scalar template parameter (if any) of any function or class in [linalg].
Linear algebra value types shall model semiregular.
A value-initialized object of linear algebra value type shall act as the additive identity.

29.9.4.2 Algorithm and class requirements [linalg.reqs.alg]

[linalg.reqs.alg] lists common requirements for all algorithms and classes in [linalg].
All of the following statements presume that the algorithm's asymptotic complexity requirements, if any, are satisfied.
  • The function may make arbitrarily many objects of any linear algebra value type, value-initializing or direct-initializing them with any existing object of that type.
  • The triangular solve algorithms in [linalg.algs.blas2.trsv], [linalg.algs.blas3.trmm], [linalg.algs.blas3.trsm], and [linalg.algs.blas3.inplacetrsm] either have a BinaryDivideOp template parameter (see [linalg.algs.reqs]) and a binary function object parameter divide of that type, or they have effects equivalent to invoking such an algorithm.
    Triangular solve algorithms interpret divide(a, b) as a times the multiplicative inverse of b.
    Each triangular solve algorithm uses a sequence of evaluations of *, *=, divide, unary +, binary +, +=, unary -, binary -, -=, and = operators that would produce the result specified by the algorithm's Effects and Remarks when operating on elements of a field with noncommutative multiplication.
    It is a precondition of the algorithm that any addend, any subtrahend, any partial sum of addends in any order (treating any difference as a sum with the second term negated), any factor, any partial product of factors respecting their order, any numerator (first argument of divide), any denominator (second argument of divide), and any assignment is a well-formed expression.
  • Each function in [linalg.algs.blas1], [linalg.algs.blas2], and [linalg.algs.blas3] that is not a triangular solve algorithm will use a sequence of evaluations of *, *=, +, +=, and = operators that would produce the result specified by the algorithm's Effects and Remarks when operating on elements of a semiring with noncommutative multiplication.
    It is a precondition of the algorithm that any addend, any partial sum of addends in any order, any factor, any partial product of factors respecting their order, and any assignment is a well-formed expression.
  • If the function has an output mdspan, then all addends, subtrahends (for the triangular solve algorithms), or results of the divide parameter on intermediate terms (if the function takes a divide parameter) are assignable and convertible to the output mdspan's value_type.
  • The function may reorder addends and partial sums arbitrarily.
    [Note 1: 
    Factors in each product are not reordered; multiplication is not necessarily commutative.
    — end note]
[Note 2: 
The above requirements do not prohibit implementation approaches and optimization techniques which are not user-observable.
In particular, if for all input and output arguments the value_type is a floating-point type, implementers are free to leverage approximations, use arithmetic operations not explicitly listed above, and compute floating point sums in any way that improves their accuracy.
— end note]
[Note 3: 
For all functions in [linalg], suppose that all input and output mdspan have as value_type a floating-point type, and any Scalar template argument has a floating-point type.
Then, functions can do all of the following:
  • compute floating-point sums in any way that improves their accuracy for arbitrary input;
  • perform additional arithmetic operations (other than those specified by the function's wording and [linalg.reqs.alg]) in order to improve performance or accuracy; and
  • use approximations (that might not be exact even if computing with real numbers), instead of computations that would be exact if it were possible to compute without rounding error;
as long as
  • the function satisfies the complexity requirements; and
  • the function is logarithmically stable, as defined in Demmel 2007[bib].
    Strassen's algorithm for matrix-matrix multiply is an example of a logarithmically stable algorithm.
— end note]

29.9.5 Tag classes [linalg.tags]

29.9.5.1 Storage order tags [linalg.tags.order]

The storage order tags describe the order of elements in an mdspan with layout_blas_packed ([linalg.layout.packed]) layout.
struct column_major_t { explicit column_major_t() = default; }; inline constexpr column_major_t column_major{}; struct row_major_t { explicit row_major_t() = default; }; inline constexpr row_major_t row_major{};
column_major_t indicates a column-major order, and row_major_t indicates a row-major order.

29.9.5.2 Triangle tags [linalg.tags.triangle]

struct upper_triangle_t { explicit upper_triangle_t() = default; }; inline constexpr upper_triangle_t upper_triangle{}; struct lower_triangle_t { explicit lower_triangle_t() = default; }; inline constexpr lower_triangle_t lower_triangle{};
These tag classes specify whether algorithms and other users of a matrix (represented as an mdspan) access the upper triangle (upper_triangle_t) or lower triangle (lower_triangle_t) of the matrix (see also [linalg.general]).
This is also subject to the restrictions of implicit_unit_diagonal_t if that tag is also used as a function argument; see below.

29.9.5.3 Diagonal tags [linalg.tags.diagonal]

struct implicit_unit_diagonal_t { explicit implicit_unit_diagonal_t() = default; }; inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal{}; struct explicit_diagonal_t { explicit explicit_diagonal_t() = default; }; inline constexpr explicit_diagonal_t explicit_diagonal{};
These tag classes specify whether algorithms access the matrix's diagonal entries, and if not, then how algorithms interpret the matrix's implicitly represented diagonal values.
The implicit_unit_diagonal_t tag indicates that an implicit unit diagonal is to be assumed ([linalg.general]).
The explicit_diagonal_t tag indicates that an explicit diagonal is used ([linalg.general]).

29.9.6 Layouts for packed matrix types [linalg.layout.packed]

29.9.6.1 Overview [linalg.layout.packed.overview]

layout_blas_packed is an mdspan layout mapping policy that represents a square matrix that stores only the entries in one triangle, in a packed contiguous format.
Its Triangle template parameter determines whether an mdspan with this layout stores the upper or lower triangle of the matrix.
Its StorageOrder template parameter determines whether the layout packs the matrix's elements in column-major or row-major order.
A StorageOrder of column_major_t indicates column-major ordering.
This packs matrix elements starting with the leftmost (least column index) column, and proceeding column by column, from the top entry (least row index).
A StorageOrder of row_major_t indicates row-major ordering.
This packs matrix elements starting with the topmost (least row index) row, and proceeding row by row, from the leftmost (least column index) entry.
[Note 1: 
layout_blas_packed describes the data layout used by the BLAS' Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP) matrix types.
— end note]
namespace std::linalg { template<class Triangle, class StorageOrder> class layout_blas_packed { public: using triangle_type = Triangle; using storage_order_type = StorageOrder; template<class Extents> struct mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_blas_packed; // [linalg.layout.packed.cons], constructors constexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents> constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [linalg.layout.packed.obs], observers constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const noexcept; template<class Index0, class Index1> constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; static constexpr bool is_always_unique() noexcept { return (extents_type::static_extent(0) != dynamic_extent && extents_type::static_extent(0) < 2) || (extents_type::static_extent(1) != dynamic_extent && extents_type::static_extent(1) < 2); } static constexpr bool is_always_exhaustive() noexcept { return true; } static constexpr bool is_always_strided() noexcept { return is_always_unique(); } constexpr bool is_unique() const noexcept { return extents_.extent(0) < 2; } constexpr bool is_exhaustive() const noexcept { return true; } constexpr bool is_strided() const noexcept { return extents_.extent(0) < 2; } constexpr index_type stride(rank_type) const noexcept; template<class OtherExtents> friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type extents_{}; // exposition only }; }; }
Mandates:
  • Triangle is either upper_triangle_t or lower_triangle_t,
  • StorageOrder is either column_major_t or row_major_t,
  • Extents is a specialization of std​::​extents,
  • Extents​::​rank() equals 2,
  • one of extents_type::static_extent(0) == dynamic_extent, extents_type::static_extent(1) == dynamic_extent, or extents_type::static_extent(0) == extents_type::static_extent(1) is true, and
  • if Extents​::​rank_dynamic() == 0 is true, let be equal to Extents​::​static_extent(0); then, is representable as a value of type index_type.
layout_blas_packed<T, SO>​::​mapping<E> is a trivially copyable type that models regular for each T, SO, and E.

29.9.6.2 Constructors [linalg.layout.packed.cons]

constexpr mapping(const extents_type& e) noexcept;
Preconditions:
Effects: Direct-non-list-initializes extents_ with e.
template<class OtherExtents> explicit(!is_convertible_v<OtherExtents, extents_type>) constexpr mapping(const mapping<OtherExtents>& other) noexcept;
Constraints: is_constructible_v<extents_type, OtherExtents> is true.
Preconditions: Let N be other.extents().extent(0).
Then, is representable as a value of type index_type ([basic.fundamental]).
Effects: Direct-non-list-initializes extents_ with other.extents().

29.9.6.3 Observers [linalg.layout.packed.obs]

constexpr index_type required_span_size() const noexcept;
Returns: extents_.extent(0) * (extents_.extent(0) + 1)/2.
[Note 1: 
For example, a 5 x 5 packed matrix only stores 15 matrix elements.
— end note]
template<class Index0, class Index1> constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
Constraints:
  • is_convertible_v<Index0, index_type> is true,
  • is_convertible_v<Index1, index_type> is true,
  • is_nothrow_constructible_v<index_type, Index0> is true, and
  • is_nothrow_constructible_v<index_type, Index1> is true.
Let i be extents_type​::​index-cast(ind0), and let j be extents_type​::​index-cast(ind1).
Preconditions: i, j is a multidimensional index in extents_ ([mdspan.overview]).
Returns: Let N be extents_.extent(0).
Then
  • (*this)(j, i) if i > j is true; otherwise
  • i + j * (j + 1)/2 if is_same_v<StorageOrder, column_major_t> && is_same_v<Triangle, upper_triangle_t> is true or is_same_v<StorageOrder, row_major_t> && is_same_v<Triangle, lower_triangle_t> is true; otherwise
  • j + N * i - i * (i + 1)/2.
constexpr index_type stride(rank_type r) const noexcept;
Preconditions:
  • is_strided() is true, and
  • r < extents_type​::​rank() is true.
Returns: 1.
template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
Effects: Equivalent to: return x.extents() == y.extents();

29.9.7 Exposition-only helpers [linalg.helpers]

29.9.7.1 abs-if-needed [linalg.helpers.abs]

The name abs-if-needed denotes an exposition-only function object.
The expression abs-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:
  • E if T is an unsigned integer;
  • otherwise, std​::​abs(E) if T is an arithmetic type,
  • otherwise, abs(E), if that expression is valid, with overload resolution performed in a context that includes the declaration template<class U> U abs(U) = delete;
    If the function selected by overload resolution does not return the absolute value of its input, the program is ill-formed, no diagnostic required.

29.9.7.2 conj-if-needed [linalg.helpers.conj]

The name conj-if-needed denotes an exposition-only function object.
The expression conj-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:
  • conj(E), if T is not an arithmetic type and the expression conj(E) is valid, with overload resolution performed in a context that includes the declaration template<class U> U conj(const U&) = delete;
    If the function selected by overload resolution does not return the complex conjugate of its input, the program is ill-formed, no diagnostic required;
  • otherwise, E.

29.9.7.3 real-if-needed [linalg.helpers.real]

The name real-if-needed denotes an exposition-only function object.
The expression real-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:
  • real(E), if T is not an arithmetic type and the expression real(E) is valid, with overload resolution performed in a context that includes the declaration template<class U> U real(const U&) = delete;
    If the function selected by overload resolution does not return the real part of its input, the program is ill-formed, no diagnostic required;
  • otherwise, E.

29.9.7.4 imag-if-needed [linalg.helpers.imag]

The name imag-if-needed denotes an exposition-only function object.
The expression imag-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:
  • imag(E), if T is not an arithmetic type and the expression imag(E) is valid, with overload resolution performed in a context that includes the declaration template<class U> U imag(const U&) = delete;
    If the function selected by overload resolution does not return the imaginary part of its input, the program is ill-formed, no diagnostic required;
  • otherwise, ((void)E, T{}).

29.9.7.5 Argument concepts [linalg.helpers.concepts]

The exposition-only concepts defined in this section constrain the algorithms in [linalg].
template<class T> constexpr bool is-mdspan = false; template<class ElementType, class Extents, class Layout, class Accessor> constexpr bool is-mdspan<mdspan<ElementType, Extents, Layout, Accessor>> = true; template<class T> concept in-vector = is-mdspan<T> && T::rank() == 1; template<class T> concept out-vector = is-mdspan<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique(); template<class T> concept inout-vector = is-mdspan<T> && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique(); template<class T> concept in-matrix = is-mdspan<T> && T::rank() == 2; template<class T> concept out-matrix = is-mdspan<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique(); template<class T> concept inout-matrix = is-mdspan<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique(); template<class T> constexpr bool is-layout-blas-packed = false; // exposition only template<class Triangle, class StorageOrder> constexpr bool is-layout-blas-packed<layout_blas_packed<Triangle, StorageOrder>> = true; template<class T> concept possibly-packed-inout-matrix = is-mdspan<T> && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && (T::is_always_unique() || is-layout-blas-packed<typename T::layout_type>); template<class T> concept in-object = is-mdspan<T> && (T::rank() == 1 || T::rank() == 2); template<class T> concept out-object = is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique(); template<class T> concept inout-object = is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
If a function in [linalg] accesses the elements of a parameter constrained by in-vector, in-matrix, or in-object, those accesses will not modify the elements.
Unless explicitly permitted, any inout-vector, inout-matrix, inout-object, out-vector, out-matrix, out-object, or possibly-packed-inout-matrix parameter of a function in [linalg] shall not overlap any other mdspan parameter of the function.

29.9.7.6 Mandates [linalg.helpers.mandates]

[Note 1: 
These exposition-only helper functions use the less constraining input concepts even for the output arguments, because the additional constraint for assignability of elements is not necessary, and they are sometimes used in a context where the third argument is an input type too.
— end note]
template<class MDS1, class MDS2> requires(is-mdspan<MDS1> && is-mdspan<MDS2>) constexpr bool compatible-static-extents(size_t r1, size_t r2) { // exposition only return MDS1::static_extent(r1) == dynamic_extent || MDS2::static_extent(r2) == dynamic_extent || MDS1::static_extent(r1) == MDS2::static_extent(r2); } template<in-vector In1, in-vector In2, in-vector Out> constexpr bool possibly-addable() { // exposition only return compatible-static-extents<Out, In1>(0, 0) && compatible-static-extents<Out, In2>(0, 0) && compatible-static-extents<In1, In2>(0, 0); } template<in-matrix In1, in-matrix In2, in-matrix Out> constexpr bool possibly-addable() { // exposition only return compatible-static-extents<Out, In1>(0, 0) && compatible-static-extents<Out, In1>(1, 1) && compatible-static-extents<Out, In2>(0, 0) && compatible-static-extents<Out, In2>(1, 1) && compatible-static-extents<In1, In2>(0, 0) && compatible-static-extents<In1, In2>(1, 1); } template<in-matrix InMat, in-vector InVec, in-vector OutVec> constexpr bool possibly-multipliable() { // exposition only return compatible-static-extents<OutVec, InMat>(0, 0) && compatible-static-extents<InMat, InVec>(1, 0); } template<in-vector InVec, in-matrix InMat, in-vector OutVec> constexpr bool possibly-multipliable() { // exposition only return compatible-static-extents<OutVec, InMat>(0, 1) && compatible-static-extents<InMat, InVec>(0, 0); } template<in-matrix InMat1, in-matrix InMat2, in-matrix OutMat> constexpr bool possibly-multipliable() { // exposition only return compatible-static-extents<OutMat, InMat1>(0, 0) && compatible-static-extents<OutMat, InMat2>(1, 1) && compatible-static-extents<InMat1, InMat2>(1, 0); }

29.9.7.7 Preconditions [linalg.helpers.precond]

[Note 1: 
These exposition-only helper functions use the less constraining input concepts even for the output arguments, because the additional constraint for assignability of elements is not necessary, and they are sometimes used in a context where the third argument is an input type too.
— end note]
constexpr bool addable( // exposition only const in-vector auto& in1, const in-vector auto& in2, const in-vector auto& out) { return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0); } constexpr bool addable( // exposition only const in-matrix auto& in1, const in-matrix auto& in2, const in-matrix auto& out) { return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) && out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1); } constexpr bool multipliable( // exposition only const in-matrix auto& in_mat, const in-vector auto& in_vec, const in-vector auto& out_vec) { return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0); } constexpr bool multipliable( // exposition only const in-vector auto& in_vec, const in-matrix auto& in_mat, const in-vector auto& out_vec) { return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0); } constexpr bool multipliable( // exposition only const in-matrix auto& in_mat1, const in-matrix auto& in_mat2, const in-matrix auto& out_mat) { return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) && in_mat1.extent(1) == in_mat2.extent(0); }

29.9.8 Scaled in-place transformation [linalg.scaled]

29.9.8.1 Introduction [linalg.scaled.intro]

The scaled function takes a value alpha and an mdspan x, and returns a new read-only mdspan that represents the elementwise product of alpha with each element of x.
[Example 1: using Vec = mdspan<double, dextents<size_t, 1>>; // z = alpha * x + y void z_equals_alpha_times_x_plus_y(double alpha, Vec x, Vec y, Vec z) { add(scaled(alpha, x), y, z); } // z = alpha * x + beta * y void z_equals_alpha_times_x_plus_beta_times_y(double alpha, Vec x, double beta, Vec y, Vec z) { add(scaled(alpha, x), scaled(beta, y), z); } — end example]

29.9.8.2 Class template scaled_accessor [linalg.scaled.scaledaccessor]

The class template scaled_accessor is an mdspan accessor policy which upon access produces scaled elements.
It is part of the implementation of scaled ([linalg.scaled.scaled]).
namespace std::linalg { template<class ScalingFactor, class NestedAccessor> class scaled_accessor { public: using element_type = add_const_t<decltype(declval<ScalingFactor>() * declval<NestedAccessor::element_type>())>; using reference = remove_const_t<element_type>; using data_handle_type = NestedAccessor::data_handle_type; using offset_policy = scaled_accessor<ScalingFactor, NestedAccessor::offset_policy>; constexpr scaled_accessor() = default; template<class OtherNestedAccessor> explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>) constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other); constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); constexpr reference access(data_handle_type p, size_t i) const; constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; constexpr const ScalingFactor& scaling_factor() const noexcept { return scaling-factor; } constexpr const NestedAccessor& nested_accessor() const noexcept { return nested-accessor; } private: ScalingFactor scaling-factor{}; // exposition only NestedAccessor nested-accessor{}; // exposition only }; }
Mandates:
template<class OtherNestedAccessor> explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>) constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other);
Constraints: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true.
Effects:
  • Direct-non-list-initializes scaling-factor with other.scaling_factor(), and
  • direct-non-list-initializes nested-accessor with other.nested_accessor().
constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
Effects:
  • Direct-non-list-initializes scaling-factor with s, and
  • direct-non-list-initializes nested-accessor with a.
constexpr reference access(data_handle_type p, size_t i) const;
Returns: scaling_factor() * NestedAccessor::element_type(nested-accessor.access(p, i))
constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
Returns: nested-accessor.offset(p, i)

29.9.8.3 Function template scaled [linalg.scaled.scaled]

The scaled function template takes a scaling factor alpha and an mdspan x, and returns a new read-only mdspan with the same domain as x, that represents the elementwise product of alpha with each element of x.
template<class ScalingFactor, class ElementType, class Extents, class Layout, class Accessor> constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
Let SA be scaled_accessor<ScalingFactor, Accessor>.
Returns: mdspan<typename SA::element_type, Extents, Layout, SA>(x.data_handle(), x.mapping(), SA(alpha, x.accessor()))
[Example 1: void test_scaled(mdspan<double, extents<int, 10>> x) { auto x_scaled = scaled(5.0, x); for (int i = 0; i < x.extent(0); ++i) { assert(x_scaled[i] == 5.0 * x[i]); } } — end example]

29.9.9 Conjugated in-place transformation [linalg.conj]

29.9.9.1 Introduction [linalg.conj.intro]

The conjugated function takes an mdspan x, and returns a new read-only mdspan y with the same domain as x, whose elements are the complex conjugates of the corresponding elements of x.

29.9.9.2 Class template conjugated_accessor [linalg.conj.conjugatedaccessor]

The class template conjugated_accessor is an mdspan accessor policy which upon access produces conjugate elements.
It is part of the implementation of conjugated ([linalg.conj.conjugated]).
namespace std::linalg { template<class NestedAccessor> class conjugated_accessor { public: using element_type = add_const_t<decltype(conj-if-needed(declval<NestedAccessor::element_type>()))>; using reference = remove_const_t<element_type>; using data_handle_type = typename NestedAccessor::data_handle_type; using offset_policy = conjugated_accessor<NestedAccessor::offset_policy>; constexpr conjugated_accessor() = default; template<class OtherNestedAccessor> explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>>) constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other); constexpr reference access(data_handle_type p, size_t i) const; constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; constexpr const Accessor& nested_accessor() const noexcept { return nested-accessor_; } private: NestedAccessor nested-accessor_{}; // exposition only }; }
Mandates:
  • element_type is valid and denotes a type,
  • is_copy_constructible_v<reference> is true,
  • is_reference_v<element_type> is false, and
  • NestedAccessor meets the accessor policy requirements ([mdspan.accessor.reqmts]).
constexpr conjugated_accessor(const NestedAccessor& acc);
Effects: Direct-non-list-initializes nested-accessor_ with acc.
template<class OtherNestedAccessor> explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>>) constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
Constraints: is_constructible_v<NestedAccessor, const OtherNestedAccessor&> is true.
Effects: Direct-non-list-initializes nested-accessor_ with other.nested_accessor().
constexpr reference access(data_handle_type p, size_t i) const;
Returns: conj-if-needed(NestedAccessor​::​element_type(nested-accessor_.access(p, i)))
constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
Returns: nested-accessor_.offset(p, i)

29.9.9.3 Function template conjugated [linalg.conj.conjugated]

template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a);
Let A be
  • remove_cvref_t<decltype(a.accessor().nested_accessor())> if Accessor is a specialization of conjugated_accessor; otherwise,
  • Accessor if remove_cvref_t<ElementType> is an arithmetic type; otherwise,
  • Accessor if the expression conj(E) is not valid for any subexpression E whose type is remove_cvref_t<ElementType> with overload resolution performed in a context that includes the declaration template<class T> conj(const T&) = delete;; and otherwise,
  • conjugated_accessor<Accessor>.
Returns:
  • The value mdspan<typename A::element_type, Extents, Layout, A>(a.data_handle(), a.mapping(), a.accessor().nested_accessor()) if Accessor is a specialization of conjugated_accessor; otherwise,
  • a if remove_cvref_t<ElementType> is an arithmetic type; otherwise,
  • a if the expression conj(E) is not valid for any subexpression E whose type is remove_cvref_t<ElementType> with overload resolution performed in a context that includes the declaration template<class T> conj(const T&) = delete;; and otherwise,
  • the value mdspan<typename A::element_type, Extents, Layout, A>(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor()))
[Example 1: void test_conjugated_complex(mdspan<complex<double>, extents<int, 10>> a) { auto a_conj = conjugated(a); for (int i = 0; i < a.extent(0); ++i) { assert(a_conj[i] == conj(a[i]); } auto a_conj_conj = conjugated(a_conj); for (int i = 0; i < a.extent(0); ++i) { assert(a_conj_conj[i] == a[i]); } } void test_conjugated_real(mdspan<double, extents<int, 10>> a) { auto a_conj = conjugated(a); for (int i = 0; i < a.extent(0); ++i) { assert(a_conj[i] == a[i]); } auto a_conj_conj = conjugated(a_conj); for (int i = 0; i < a.extent(0); ++i) { assert(a_conj_conj[i] == a[i]); } } — end example]

29.9.10 Transpose in-place transformation [linalg.transp]

29.9.10.1 Introduction [linalg.transp.intro]

layout_transpose is an mdspan layout mapping policy that swaps the two indices, extents, and strides of any unique mdspan layout mapping policy.
The transposed function takes an mdspan representing a matrix, and returns a new mdspan representing the transpose of the input matrix.

29.9.10.2 Exposition-only helpers for layout_transpose and transposed [linalg.transp.helpers]

The exposition-only transpose-extents function takes an extents object representing the extents of a matrix, and returns a new extents object representing the extents of the transpose of the matrix.
The exposition-only alias template transpose-extents-t<InputExtents> gives the type of transpose-extents(e) for a given extents object e of type InputExtents.
template<class IndexType, size_t InputExtent0, size_t InputExtent1> constexpr extents<IndexType, InputExtent1, InputExtent0> transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
Returns: extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))
template<class InputExtents> using transpose-extents-t = decltype(transpose-extents(declval<InputExtents>())); // exposition only

29.9.10.3 Class template layout_transpose [linalg.transp.layout.transpose]

layout_transpose is an mdspan layout mapping policy that swaps the two indices, extents, and strides of any mdspan layout mapping policy.
namespace std::linalg { template<class Layout> class layout_transpose { public: using nested_layout_type = Layout; template<class Extents> struct mapping { private: using nested-mapping-type = typename Layout::template mapping<transpose-extents-t<Extents>>; // exposition only public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_transpose; constexpr explicit mapping(const nested-mapping-type&); constexpr const extents_type& extents() const noexcept { return extents_; } constexpr index_type required_span_size() const { return nested-mapping_.required_span_size(); template<class Index0, class Index1> constexpr index_type operator()(Index0 ind0, Index1 ind1) const { return nested-mapping_(ind1, ind0); } constexpr const nested-mapping-type& nested_mapping() const noexcept { return nested-mapping_; } static constexpr bool is_always_unique() noexcept { return nested-mapping-type::is_always_unique(); } static constexpr bool is_always_exhaustive() noexcept { return nested-mapping-type::is_always_exhaustive(); } static constexpr bool is_always_strided() noexcept { return nested-mapping-type::is_always_strided(); } constexpr bool is_unique() const { return nested-mapping_.is_unique(); } constexpr bool is_exhaustive() const { return nested-mapping_.is_exhaustive(); } constexpr bool is_strided() const { return nested-mapping_.is_strided(); } constexpr index_type stride(size_t r) const; template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y); }; private: nested-mapping-type nested-mapping_; // exposition only extents_type extents_; // exposition only }; }
Layout shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]).
Mandates:
  • Extents is a specialization of std​::​extents, and
  • Extents​::​rank() equals 2.
constexpr explicit mapping(const nested-mapping-type& map);
Effects:
  • Initializes nested-mapping_ with map, and
  • initializes extents_ with transpose-extents(map.extents()).
constexpr index_type stride(size_t r) const;
Preconditions:
Returns: nested-mapping_.stride(r == 0 ? 1 : 0)
template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
Constraints: The expression x.nested-mapping_ == y.nested-mapping_ is well-formed and its result is convertible to bool.
Returns: x.nested-mapping_ == y.nested-mapping_.

29.9.10.4 Function template transposed [linalg.transp.transposed]

The transposed function takes a rank-2 mdspan representing a matrix, and returns a new mdspan representing the input matrix's transpose.
The input matrix's data are not modified, and the returned mdspan accesses the input matrix's data in place.
template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
Mandates: Extents​::​rank() == 2 is true.
Let ReturnExtents be transpose-extents-t<Extents>.
Let R be mdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>, where ReturnLayout is:
  • layout_right if Layout is layout_left;
  • otherwise, layout_left if Layout is layout_right;
  • otherwise, layout_right_padded<PaddingValue> if Layout is
    layout_left_padded<PaddingValue> for some size_t value PaddingValue;
  • otherwise, layout_left_padded<PaddingValue> if Layout is
    layout_right_padded<PaddingValue> for some size_t value PaddingValue;
  • otherwise, layout_stride if Layout is layout_stride;
  • otherwise, layout_blas_packed<OppositeTriangle, OppositeStorageOrder>, if Layout is
    layout_blas_packed<Triangle, StorageOrder> for some Triangle and StorageOrder, where
    • OppositeTriangle is conditional_t<is_same_v<Triangle, upper_triangle_t>, lower_triangle_t, upper_triangle_t> and
    • OppositeStorageOrder is conditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
  • otherwise, NestedLayout if Layout is layout_transpose<NestedLayout> for some NestedLayout;
  • otherwise, layout_transpose<Layout>.
Returns: With ReturnMapping being the type typename ReturnLayout​::​template mapping<ReturnExtents>:
  • if Layout is layout_left, layout_right, or a specialization of layout_blas_packed, R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents())), a.accessor())
  • otherwise, R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()), a.mapping().stride(1)), a.accessor()) if Layout is layout_left_padded<PaddingValue> for some size_t value PaddingValue;
  • otherwise, R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()), a.mapping().stride(0)), a.accessor()) if Layout is layout_right_padded<PaddingValue> for some size_t value PaddingValue;
  • otherwise, if Layout is layout_stride, R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()), array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
  • otherwise, if Layout is a specialization of layout_transpose, R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
  • otherwise, R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
[Example 1: void test_transposed(mdspan<double, extents<size_t, 3, 4>> a) { const auto num_rows = a.extent(0); const auto num_cols = a.extent(1); auto a_t = transposed(a); assert(num_rows == a_t.extent(1)); assert(num_cols == a_t.extent(0)); assert(a.stride(0) == a_t.stride(1)); assert(a.stride(1) == a_t.stride(0)); for (size_t row = 0; row < num_rows; ++row) { for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == a_t[col, row]); } } auto a_t_t = transposed(a_t); assert(num_rows == a_t_t.extent(0)); assert(num_cols == a_t_t.extent(1)); assert(a.stride(0) == a_t_t.stride(0)); assert(a.stride(1) == a_t_t.stride(1)); for (size_t row = 0; row < num_rows; ++row) { for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == a_t_t[row, col]); } } } — end example]

29.9.11 Conjugate transpose in-place transform [linalg.conjtransposed]

The conjugate_transposed function returns a conjugate transpose view of an object.
This combines the effects of transposed and conjugated.
template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
Effects: Equivalent to: return conjugated(transposed(a));
[Example 1: void test_conjugate_transposed(mdspan<complex<double>, extents<size_t, 3, 4>> a) { const auto num_rows = a.extent(0); const auto num_cols = a.extent(1); auto a_ct = conjugate_transposed(a); assert(num_rows == a_ct.extent(1)); assert(num_cols == a_ct.extent(0)); assert(a.stride(0) == a_ct.stride(1)); assert(a.stride(1) == a_ct.stride(0)); for (size_t row = 0; row < num_rows; ++row) { for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == conj(a_ct[col, row])); } } auto a_ct_ct = conjugate_transposed(a_ct); assert(num_rows == a_ct_ct.extent(0)); assert(num_cols == a_ct_ct.extent(1)); assert(a.stride(0) == a_ct_ct.stride(0)); assert(a.stride(1) == a_ct_ct.stride(1)); for (size_t row = 0; row < num_rows; ++row) { for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == a_ct_ct[row, col]); assert(conj(a_ct[col, row]) == a_ct_ct[row, col]); } } } — end example]

29.9.12 Algorithm requirements based on template parameter name [linalg.algs.reqs]

Throughout [linalg.algs.blas1], [linalg.algs.blas2], and [linalg.algs.blas3], where the template parameters are not constrained, the names of template parameters are used to express the following constraints.
[Note 1: 
Function templates that have a template parameter named ExecutionPolicy are parallel algorithms ([algorithms.parallel.defns]).
— end note]

29.9.13 BLAS 1 algorithms [linalg.algs.blas1]

29.9.13.1 Complexity [linalg.algs.blas1.complexity]

Complexity: All algorithms in [linalg.algs.blas1] with mdspan parameters perform a count of mdspan array accesses and arithmetic operations that is linear in the maximum product of extents of any mdspan parameter.

29.9.13.2 Givens rotations [linalg.algs.blas1.givens]

29.9.13.2.1 Compute Givens rotation [linalg.algs.blas1.givens.lartg]

template<class Real> setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept; template<class Real> setup_givens_rotation_result<complex<Real>> setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
These functions compute the Givens plane rotation represented by the two values c and s such that the 2 x 2 system of equations
holds, where c is always a real scalar, and .
That is, c and s represent a 2 x 2 matrix, that when multiplied by the right by the input vector whose components are a and b, produces a result vector whose first component r is the Euclidean norm of the input vector, and whose second component is zero.
[Note 1: 
These functions correspond to the LAPACK function xLARTG[bib].
— end note]
Returns: c, s, r, where c and s form the Givens plane rotation corresponding to the input a and b, and r is the Euclidean norm of the two-component vector formed by a and b.

29.9.13.2.2 Apply a computed Givens rotation to vectors [linalg.algs.blas1.givens.rot]

template<inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, Real s); template<inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s); template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real> void apply_givens_rotation(ExecutionPolicy&& exec, InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
[Note 1: 
These functions correspond to the BLAS function xROT[bib].
— end note]
Mandates: compatible-static-extents<InOutVec1, InOutVec2>(0, 0) is true.
Preconditions: x.extent(0) equals y.extent(0).
Effects: Applies the plane rotation specified by c and s to the input vectors x and y, as if the rotation were a 2 x 2 matrix and the input vectors were successive rows of a matrix with two rows.

29.9.13.3 Swap matrix or vector elements [linalg.algs.blas1.swap]

template<inout-object InOutObj1, inout-object InOutObj2> void swap_elements(InOutObj1 x, InOutObj2 y); template<class ExecutionPolicy, inout-object InOutObj1, inout-object InOutObj2> void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
[Note 1: 
These functions correspond to the BLAS function xSWAP[bib].
— end note]
Constraints: x.rank() equals y.rank().
Mandates: For all r in the range [0, x.rank()), compatible-static-extents<InOutObj1, InOutObj2>(r, r) is true.
Preconditions: x.extents() equals y.extents().
Effects: Swaps all corresponding elements of x and y.

29.9.13.4 Multiply the elements of an object in place by a scalar [linalg.algs.blas1.scal]

template<class Scalar, inout-object InOutObj> void scale(Scalar alpha, InOutObj x); template<class ExecutionPolicy, class Scalar, inout-object InOutObj> void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
[Note 1: 
These functions correspond to the BLAS function xSCAL[bib].
— end note]
Effects: Overwrites x with the result of computing the elementwise multiplication αx, where the scalar α is alpha.

29.9.13.5 Copy elements of one matrix or vector into another [linalg.algs.blas1.copy]

template<in-object InObj, out-object OutObj> void copy(InObj x, OutObj y); template<class ExecutionPolicy, in-object InObj, out-object OutObj> void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
[Note 1: 
These functions correspond to the BLAS function xCOPY[bib].
— end note]
Constraints: x.rank() equals y.rank().
Mandates: For all r in the range , compatible-static-extents<InObj, OutObj>(r, r) is true.
Preconditions: x.extents() equals y.extents().
Effects: Assigns each element of x to the corresponding element of y.

29.9.13.6 Add vectors or matrices elementwise [linalg.algs.blas1.add]

template<in-object InObj1, in-object InObj2, out-object OutObj> void add(InObj1 x, InObj2 y, OutObj z); template<class ExecutionPolicy, in-object InObj1, in-object InObj2, out-object OutObj> void add(ExecutionPolicy&& exec, InObj1 x, InObj2 y, OutObj z);
[Note 1: 
These functions correspond to the BLAS function xAXPY[bib].
— end note]
Constraints: x.rank(), y.rank(), and z.rank() are all equal.
Mandates: possibly-addable<InObj1, InObj2, OutObj>() is true.
Preconditions: addable(x,y,z) is true.
Effects: Computes .
Remarks: z may alias x or y.

29.9.13.7 Dot product of two vectors [linalg.algs.blas1.dot]

[Note 1: 
The functions in this section correspond to the BLAS functions xDOT, xDOTU, and xDOTC[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas1.dot].
Mandates: compatible-static-extents<InVec1, InVec2>(0, 0) is true.
Preconditions: v1.extent(0) equals v2.extent(0).
template<in-vector InVec1, in-vector InVec2, class Scalar> Scalar dot(InVec1 v1, InVec2 v2, Scalar init); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar> Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
These functions compute a non-conjugated dot product with an explicitly specified result type.
Returns: Let N be v1.extent(0).
  • init if N is zero;
  • otherwise, GENERALIZED_SUM(plus<>(), init, v1[0]*v2[0], …, v1[N-1]*v2[N-1]).
Remarks: If InVec1​::​value_type, InVec2​::​value_type, and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InVec1​::​value_type or InVec2​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
template<in-vector InVec1, in-vector InVec2> auto dot(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2> auto dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);
These functions compute a non-conjugated dot product with a default result type.
Effects: Let T be decltype(declval<typename InVec1​::​value_type>() * declval<typename InVec2​::​value_type>()).
Then,
  • the two-parameter overload is equivalent to: return dot(v1, v2, T{}); and
  • the three-parameter overload is equivalent to: return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
template<in-vector InVec1, in-vector InVec2, class Scalar> Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar> Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
These functions compute a conjugated dot product with an explicitly specified result type.
Effects:
  • The three-parameter overload is equivalent to: return dot(conjugated(v1), v2, init); and
  • the four-parameter overload is equivalent to: return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
template<in-vector InVec1, in-vector InVec2> auto dotc(InVec1 v1, InVec2 v2); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2> auto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);
These functions compute a conjugated dot product with a default result type.
Effects: Let T be decltype(conj-if-needed(declval<typename InVec1​::​value_type>()) * declval<typename InVec2​::​value_type>()).
Then,
  • the two-parameter overload is equivalent to: return dotc(v1, v2, T{}); and
  • the three-parameter overload is equivalent to return dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});

29.9.13.8 Scaled sum of squares of a vector's elements [linalg.algs.blas1.ssq]

template<in-vector InVec, class Scalar> sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init); template<class ExecutionPolicy, in-vector InVec, class Scalar> sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec, InVec v, sum_of_squares_result<Scalar> init);
[Note 1: 
These functions correspond to the LAPACK function xLASSQ[bib].
— end note]
Mandates: decltype(abs-if-needed(declval<typename InVec​::​value_type>())) is convertible to Scalar.
Effects: Returns a value result such that
  • result.scaling_factor is the maximum of init.scaling_factor and abs-if-needed(x[i]) for all i in the domain of v; and
  • let s2init be init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares then result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares equals the sum of s2init and the squares of abs-if-needed(x[i]) for all i in the domain of v.
Remarks: If InVec​::​value_type, and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InVec​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.

29.9.13.9 Euclidean norm of a vector [linalg.algs.blas1.nrm2]

template<in-vector InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); template<class ExecutionPolicy, in-vector InVec, class Scalar> Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
[Note 1: 
These functions correspond to the BLAS function xNRM2[bib].
— end note]
Mandates: Let a be abs-if-needed(declval<typename InVec​::​value_type>()).
Then, decltype(init + a * a is convertible to Scalar.
Returns: The square root of the sum of the square of init and the squares of the absolute values of the elements of v.
[Note 2: 
For init equal to zero, this is the Euclidean norm (also called 2-norm) of the vector v.
— end note]
Remarks: If InVec​::​value_type, and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InVec​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
[Note 3: 
An implementation of this function for floating-point types T can use the scaled_sum_of_squares result from vector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init}).
— end note]
template<in-vector InVec> auto vector_two_norm(InVec v); template<class ExecutionPolicy, in-vector InVec> auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
Effects: Let a be abs-if-needed(declval<typename InVec​::​value_type>()).
Let T be decltype(a * a).
Then,
  • the one-parameter overload is equivalent to: return vector_two_norm(v, T{}); and
  • the two-parameter overload is equivalent to: return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});

29.9.13.10 Sum of absolute values of vector elements [linalg.algs.blas1.asum]

template<in-vector InVec, class Scalar> Scalar vector_abs_sum(InVec v, Scalar init); template<class ExecutionPolicy, in-vector InVec, class Scalar> Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
[Note 1: 
These functions correspond to the BLAS functions SASUM, DASUM, SCASUM, and DZASUM[bib].
— end note]
Mandates: decltype(init + abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) + abs-if-needed(imag-if-needed(declval<typename InVec::value_type>()))) is convertible to Scalar.
Returns: Let N be v.extent(0).
  • init if N is zero;
  • otherwise, if InVec​::​value_type is an arithmetic type, GENERALIZED_SUM(plus<>(), init, abs-if-needed(v[0]), …, abs-if-needed(v[N-1]))
  • otherwise, GENERALIZED_SUM(plus<>(), init, abs-if-needed(real-if-needed(v[0])) + abs-if-needed(imag-if-needed(v[0])), …, abs-if-needed(real-if-needed(v[N-1])) + abs-if-needed(imag-if-needed(v[N-1])))
Remarks: If InVec​::​value_type and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InVec​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
template<in-vector InVec> auto vector_abs_sum(InVec v); template<class ExecutionPolicy, in-vector InVec> auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
Effects: Let T be typename InVec​::​value_type.
Then,
  • the one-parameter overload is equivalent to: return vector_abs_sum(v, T{}); and
  • the two-parameter overload is equivalent to: return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});

29.9.13.11 Index of maximum absolute value of vector elements [linalg.algs.blas1.iamax]

template<in-vector InVec> typename InVec::extents_type vector_idx_abs_max(InVec v); template<class ExecutionPolicy, in-vector InVec> typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
[Note 1: 
These functions correspond to the BLAS function IxAMAX[bib].
— end note]
Let T be decltype(abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) + abs-if-needed(imag-if-needed(declval<typename InVec::value_type>())))
Mandates: declval<T>() < declval<T>() is a valid expression.
Returns:
  • numeric_limits<typename InVec​::​size_type>​::​max() if v has zero elements;
  • otherwise, the index of the first element of v having largest absolute value, if InVec​::​value_type is an arithmetic type;
  • otherwise, the index of the first element of v for which abs-if-needed(real-if-needed()) + abs-if-needed(imag-if-needed()) has the largest value.

29.9.13.12 Frobenius norm of a matrix [linalg.algs.blas1.matfrobnorm]

[Note 1: 
These functions exist in the BLAS standard[bib] but are not part of the reference implementation.
— end note]
template<in-matrix InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
Mandates: Let a be abs-if-needed(declval<typename InMat​::​value_type>()).
Then, decltype(init + a * a) is convertible to Scalar.
Returns: The square root of the sum of squares of init and the absolute values of the elements of A.
[Note 2: 
For init equal to zero, this is the Frobenius norm of the matrix A.
— end note]
Remarks: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InMat​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
template<in-matrix InMat> auto matrix_frob_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
Effects: Let a be abs-if-needed(declval<typename InMat​::​value_type>()).
Let T be decltype(a * a).
Then,
  • the one-parameter overload is equivalent to: return matrix_frob_norm(A, T{}); and
  • the two-parameter overload is equivalent to: return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});

29.9.13.13 One norm of a matrix [linalg.algs.blas1.matonenorm]

[Note 1: 
These functions exist in the BLAS standard[bib] but are not part of the reference implementation.
— end note]
template<in-matrix InMat, class Scalar> Scalar matrix_one_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
Mandates: decltype(abs-if-needed(declval<typename InMat​::​value_type>())) is convertible to Scalar.
Returns:
  • init if A.extent(1) is zero;
  • otherwise, the sum of init and the one norm of the matrix A.
[Note 2: 
The one norm of the matrix A is the maximum over all columns of A, of the sum of the absolute values of the elements of the column.
— end note]
Remarks: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InMat​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
template<in-matrix InMat> auto matrix_one_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
Effects: Let T be decltype(abs-if-needed(declval<typename InMat​::​value_type>()).
Then,
  • the one-parameter overload is equivalent to: return matrix_one_norm(A, T{}); and
  • the two-parameter overload is equivalent to: return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});

29.9.13.14 Infinity norm of a matrix [linalg.algs.blas1.matinfnorm]

[Note 1: 
These functions exist in the BLAS standard[bib] but are not part of the reference implementation.
— end note]
template<in-matrix InMat, class Scalar> Scalar matrix_inf_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
Mandates: decltype(abs-if-needed(declval<typename InMat​::​value_type>())) is convertible to Scalar.
Returns:
  • init if A.extent(0) is zero;
  • otherwise, the sum of init and the infinity norm of the matrix A.
[Note 2: 
The infinity norm of the matrix A is the maximum over all rows of A, of the sum of the absolute values of the elements of the row.
— end note]
Remarks: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex, and if Scalar has higher precision than InMat​::​value_type, then intermediate terms in the sum use Scalar's precision or greater.
template<in-matrix InMat> auto matrix_inf_norm(InMat A); template<class ExecutionPolicy, in-matrix InMat> auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
Effects: Let T be decltype(abs-if-needed(declval<typename InMat​::​value_type>()).
Then,
  • the one-parameter overload is equivalent to: return matrix_inf_norm(A, T{}); and
  • the two-parameter overload is equivalent to: return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});

29.9.14 BLAS 2 algorithms [linalg.algs.blas2]

29.9.14.1 General matrix-vector product [linalg.algs.blas2.gemv]

[Note 1: 
These functions correspond to the BLAS function xGEMV.
— end note]
The following elements apply to all functions in [linalg.algs.blas2.gemv].
Mandates:
  • possibly-multipliable<decltype(A), decltype(x), decltype(y)>() is true, and
  • possibly-addable<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter.
Preconditions:
  • multipliable(A,x,y) is true, and
  • addable(x,y,z) is true for those overloads that take a z parameter.
Complexity: .
template<in-matrix InMat, in-vector InVec, out-vector OutVec> void matrix_vector_product(InMat A, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, in-vector InVec, out-vector OutVec> void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
These functions perform an overwriting matrix-vector product.
Effects: Computes .
[Example 1: constexpr size_t num_rows = 5; constexpr size_t num_cols = 6; // y = 3.0 * A * x void scaled_matvec_1(mdspan<double, extents<size_t, num_rows, num_cols>> A, mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) { matrix_vector_product(scaled(3.0, A), x, y); } // z = 7.0 times the transpose of A, times y void scaled_transposed_matvec(mdspan<double, extents<size_t, num_rows, num_cols>> A, mdspan<double, extents<size_t, num_rows>> y, mdspan<double, extents<size_t, num_cols>> z) { matrix_vector_product(scaled(7.0, transposed(A)), y, z); } — end example]
template<in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec> void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec> void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec1 x, InVec2 y, OutVec z);
These functions performs an updating matrix-vector product.
Effects: Computes .
Remarks: z may alias y.
[Example 2: // y = 3.0 * A * x + 2.0 * y void scaled_matvec_2(mdspan<double, extents<size_t, num_rows, num_cols>> A, mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) { matrix_vector_product(scaled(3.0, A), x, scaled(2.0, y), y); } — end example]

29.9.14.2 Symmetric matrix-vector product [linalg.algs.blas2.symv]

[Note 1: 
These functions correspond to the BLAS functions xSYMV and xSPMV[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas2.symv].
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true;
  • possibly-multipliable<decltype(A), decltype(x), decltype(y)>() is true; and
  • possibly-addable<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter.
Preconditions:
  • A.extent(0) equals A.extent(1),
  • multipliable(A,x,y) is true, and
  • addable(x,y,z) is true for those overloads that take a z parameter.
Complexity: .
template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void symmetric_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y);
These functions perform an overwriting symmetric matrix-vector product, taking into account the Triangle parameter that applies to the symmetric matrix A ([linalg.general]).
Effects: Computes .
template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void symmetric_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
These functions perform an updating symmetric matrix-vector product, taking into account the Triangle parameter that applies to the symmetric matrix A ([linalg.general]).
Effects: Computes .
Remarks: z may alias y.

29.9.14.3 Hermitian matrix-vector product [linalg.algs.blas2.hemv]

[Note 1: 
These functions correspond to the BLAS functions xHEMV and xHPMV[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas2.hemv].
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true;
  • possibly-multipliable<decltype(A), decltype(x), decltype(y)>() is true; and
  • possibly-addable<decltype(x), decltype(y), decltype(z)>() is true for those overloads that take a z parameter.
Preconditions:
  • A.extent(0) equals A.extent(1),
  • multipliable(A, x, y) is true, and
  • addable(x, y, z) is true for those overloads that take a z parameter.
Complexity: .
template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec> void hermitian_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec x, OutVec y);
These functions perform an overwriting Hermitian matrix-vector product, taking into account the Triangle parameter that applies to the Hermitian matrix A ([linalg.general]).
Effects: Computes .
template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec> void hermitian_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
These functions perform an updating Hermitian matrix-vector product, taking into account the Triangle parameter that applies to the Hermitian matrix A ([linalg.general]).
Effects: Computes .
Remarks: z may alias y.

29.9.14.4 Triangular matrix-vector product [linalg.algs.blas2.trmv]

[Note 1: 
These functions correspond to the BLAS functions xTRMV and xTPMV[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas2.trmv].
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true;
  • compatible-static-extents<decltype(A), decltype(y)>(0, 0) is true;
  • compatible-static-extents<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter; and
  • compatible-static-extents<decltype(A), decltype(z)>(0, 0) is true for those overloads that take a z parameter.
Preconditions:
  • A.extent(0) equals A.extent(1),
  • A.extent(0) equals y.extent(0),
  • A.extent(0) equals x.extent(0) for those overloads that take an x parameter, and
  • A.extent(0) equals z.extent(0) for those overloads that take a z parameter.
template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
These functions perform an overwriting triangular matrix-vector product, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Effects: Computes .
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec y);
These functions perform an in-place triangular matrix-vector product, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
[Note 2: 
Performing this operation in place hinders parallelization.
However, other ExecutionPolicy specific optimizations, such as vectorization, are still possible.
— end note]
Effects: Computes a vector such that , and assigns each element of to the corresponding element of y.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec1, in-vector InVec2, out-vector OutVec> void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec1, in-vector InVec2, out-vector OutVec> void triangular_matrix_vector_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec1 x, InVec2 y, OutVec z);
These functions perform an updating triangular matrix-vector product, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Effects: Computes .
Complexity: .
Remarks: z may alias y.

29.9.14.5 Solve a triangular linear system [linalg.algs.blas2.trsv]

[Note 1: 
These functions correspond to the BLAS functions xTRSV and xTPSV[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas2.trsv].
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true;
  • compatible-static-extents<decltype(A), decltype(b)>(0, 0) is true; and
  • compatible-static-extents<decltype(A), decltype(x)>(0, 0) is true for those overloads that take an x parameter.
Preconditions:
  • A.extent(0) equals A.extent(1),
  • A.extent(0) equals b.extent(0), and
  • A.extent(0) equals x.extent(0) for those overloads that take an x parameter.
template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x, BinaryDivideOp divide);
These functions perform a triangular solve, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Effects: Computes a vector such that , and assigns each element of to the corresponding element of x.
If no such exists, then the elements of x are valid but unspecified.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
Effects: Equivalent to: triangular_matrix_vector_solve(A, t, d, b, x, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec, out-vector OutVec> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
Effects: Equivalent to: triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec), A, t, d, b, x, divides<void>{});
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec, class BinaryDivideOp> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec b, BinaryDivideOp divide);
These functions perform an in-place triangular solve, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
[Note 2: 
Performing triangular solve in place hinders parallelization.
However, other ExecutionPolicy specific optimizations, such as vectorization, are still possible.
— end note]
Effects: Computes a vector such that , and assigns each element of to the corresponding element of b.
If no such exists, then the elements of b are valid but unspecified.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
Effects: Equivalent to: triangular_matrix_vector_solve(A, t, d, b, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec> void triangular_matrix_vector_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutVec b);
Effects: Equivalent to: triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec), A, t, d, b, divides<void>{});

29.9.14.6 Rank-1 (outer product) update of a matrix [linalg.algs.blas2.rank1]

template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
These functions perform a nonsymmetric nonconjugated rank-1 update.
[Note 1: 
These functions correspond to the BLAS functions xGER (for real element types) and xGERU (for complex element types)[bib].
— end note]
Mandates: possibly-multipliable<InOutMat, InVec2, InVec1>() is true.
Preconditions: multipliable(A, y, x) is true.
Effects: Computes a matrix such that , and assigns each element of to the corresponding element of A.
Complexity: .
template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat> void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
These functions perform a nonsymmetric conjugated rank-1 update.
[Note 2: 
These functions correspond to the BLAS functions xGER (for real element types) and xGERC (for complex element types)[bib].
— end note]
Effects:
  • For the overloads without an ExecutionPolicy argument, equivalent to: matrix_rank_1_update(x, conjugated(y), A);
  • otherwise, equivalent to: matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), A);

29.9.14.7 Symmetric or Hermitian Rank-1 (outer product) update of a matrix [linalg.algs.blas2.symherrank1]

[Note 1: 
These functions correspond to the BLAS functions xSYR, xSPR, xHER, and xHPR[bib].
They have overloads taking a scaling factor alpha, because it would be impossible to express the update otherwise.
— end note]
The following elements apply to all functions in [linalg.algs.blas2.symherrank1].
Mandates:
  • If InOutMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true; and
  • compatible-static-extents<decltype(A), decltype(x)>(0, 0) is true.
Preconditions:
  • A.extent(0) equals A.extent(1), and
  • A.extent(0) equals x.extent(0).
Complexity: .
template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t);
These functions perform a symmetric rank-1 update of the symmetric matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes a matrix such that , where the scalar α is alpha, and assigns each element of to the corresponding element of A.
template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
These functions perform a symmetric rank-1 update of the symmetric matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes a matrix such that and assigns each element of to the corresponding element of A.
template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, Scalar alpha, InVec x, InOutMat A, Triangle t);
These functions perform a Hermitian rank-1 update of the Hermitian matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes such that , where the scalar α is alpha, and assigns each element of to the corresponding element of A.
template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
These functions perform a Hermitian rank-1 update of the Hermitian matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes a matrix such that and assigns each element of to the corresponding element of A.

29.9.14.8 Symmetric and Hermitian rank-2 matrix updates [linalg.algs.blas2.rank2]

[Note 1: 
These functions correspond to the BLAS functions xSYR2,xSPR2, xHER2 and xHPR2[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas2.rank2].
Mandates:
  • If InOutMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true; and
  • possibly-multipliable<decltype(A), decltype(x), decltype(y)>() is true.
Preconditions:
  • A.extent(0) equals A.extent(1), and
  • multipliable(A, x, y) is true.
Complexity: .
template<in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A, Triangle t);
These functions perform a symmetric rank-2 update of the symmetric matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes such that and assigns each element of to the corresponding element of A.
template<in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A, Triangle t);
These functions perform a Hermitian rank-2 update of the Hermitian matrix A, taking into account the Triangle parameter that applies to A ([linalg.general]).
Effects: Computes such that and assigns each element of to the corresponding element of A.

29.9.15 BLAS 3 algorithms [linalg.algs.blas3]

29.9.15.1 General matrix-matrix product [linalg.algs.blas3.gemm]

[Note 1: 
These functions correspond to the BLAS function xGEMM[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas3.gemm] in addition to function-specific elements.
Mandates: possibly-multipliable<decltype(A), decltype(B), decltype(C)>() is true.
Preconditions: multipliable(A, B, C) is true.
Complexity: .
template<in-matrix InMat1, in-matrix InMat2, out-matrix OutMat> void matrix_product(InMat1 A, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, out-matrix OutMat> void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C);
Effects: Computes .
template<in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C);
Mandates: possibly-addable<InMat3, InMat3, OutMat>() is true.
Preconditions: addable(E, E, C) is true.
Effects: Computes .
Remarks: C may alias E.

29.9.15.2 Symmetric, Hermitian, and triangular matrix-matrix product [linalg.algs.blas3.xxmm]

[Note 1: 
These functions correspond to the BLAS functions xSYMM, xHEMM, and xTRMM[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas3.xxmm] in addition to function-specific elements.
Mandates:
  • possibly-multipliable<decltype(A), decltype(B), decltype(C)>() is true, and
  • possibly-addable<decltype(E), decltype(E), decltype(C)>() is true for those overloads that take an E parameter.
Preconditions:
  • multipliable(A, B, C) is true, and
  • addable(E, E, C) is true for those overloads that take an E parameter.
Complexity: .
template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
These functions perform a matrix-matrix multiply, taking into account the Triangle and DiagonalStorage (if applicable) parameters that apply to the symmetric, Hermitian, or triangular (respectively) matrix A ([linalg.general]).
Mandates:
  • If InMat1 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument; and
  • compatible-static-extents<InMat1, InMat1>(0, 1) is true.
Preconditions: A.extent(0) == A.extent(1) is true.
Effects: Computes .
template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, out-matrix OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
These functions perform a matrix-matrix multiply, taking into account the Triangle and DiagonalStorage (if applicable) parameters that apply to the symmetric, Hermitian, or triangular (respectively) matrix B ([linalg.general]).
Mandates:
  • If InMat2 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument; and
  • compatible-static-extents<InMat2, InMat2>(0, 1) is true.
Preconditions: B.extent(0) == B.extent(1) is true.
Effects: Computes .
template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, OutMat C);
These functions perform a potentially overwriting matrix-matrix multiply-add, taking into account the Triangle and DiagonalStorage (if applicable) parameters that apply to the symmetric, Hermitian, or triangular (respectively) matrix A ([linalg.general]).
Mandates:
  • If InMat1 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument; and
  • compatible-static-extents<InMat1, InMat1>(0, 1) is true.
Preconditions: A.extent(0) == A.extent(1) is true.
Effects: Computes .
Remarks: C may alias E.
template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3, out-matrix OutMat> void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage, in-matrix InMat3, out-matrix OutMat> void triangular_matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, OutMat C);
These functions perform a potentially overwriting matrix-matrix multiply-add, taking into account the Triangle and DiagonalStorage (if applicable) parameters that apply to the symmetric, Hermitian, or triangular (respectively) matrix B ([linalg.general]).
Mandates:
  • If InMat2 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument; and
  • compatible-static-extents<InMat2, InMat2>(0, 1) is true.
Preconditions: B.extent(0) == B.extent(1) is true.
Effects: Computes .
Remarks: C may alias E.

29.9.15.3 In-place triangular matrix-matrix product [linalg.algs.blas3.trmm]

These functions perform an in-place matrix-matrix multiply, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
[Note 1: 
These functions correspond to the BLAS function xTRMM[bib].
— end note]
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_left_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C);
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<InMat, InOutMat, InOutMat>() is true; and
  • compatible-static-extents<InMat, InMat>(0, 1) is true.
Preconditions:
  • multipliable(A, C, C) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes a matrix such that and assigns each element of to the corresponding element of C.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_right_product(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat C);
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<InOutMat, InMat, InOutMat>() is true; and
  • compatible-static-extents<InMat, InMat>(0, 1) is true.
Preconditions:
  • multipliable(C, A, C) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes a matrix such that and assigns each element of to the corresponding element of C.
Complexity: .

29.9.15.4 Rank-k update of a symmetric or Hermitian matrix [linalg.algs.blas3.rankk]

[Note 1: 
These functions correspond to the BLAS functions xSYRK and xHERK[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas3.rankk].
Mandates:
  • If InOutMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true;
  • compatible-static-extents<decltype(C), decltype(C)>(0, 1) is true; and
  • compatible-static-extents<decltype(A), decltype(C)>(0, 0) is true.
Preconditions:
  • A.extent(0) equals A.extent(1),
  • C.extent(0) equals C.extent(1), and
  • A.extent(0) equals C.extent(0).
Complexity: .
template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t);
Effects: Computes a matrix such that , where the scalar α is alpha, and assigns each element of to the corresponding element of C.
template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t);
Effects: Computes a matrix such that , and assigns each element of to the corresponding element of C.
template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, Scalar alpha, InMat A, InOutMat C, Triangle t);
Effects: Computes a matrix such that , where the scalar α is alpha, and assigns each element of to the corresponding element of C.
template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, InMat A, InOutMat C, Triangle t);
Effects: Computes a matrix such that , and assigns each element of to the corresponding element of C.

29.9.15.5 Rank-2k update of a symmetric or Hermitian matrix [linalg.algs.blas3.rank2k]

[Note 1: 
These functions correspond to the BLAS functions xSYR2K and xHER2K[bib].
— end note]
The following elements apply to all functions in [linalg.algs.blas3.rank2k].
Mandates:
  • If InOutMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-addable<decltype(A), decltype(B), decltype(C)>() is true; and
  • compatible-static-extents<decltype(A), decltype(A)>(0, 1) is true.
Preconditions:
  • addable(A, B, C) is true, and
  • A.extent(0) equals A.extent(1).
Complexity: .
template<in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InOutMat C, Triangle t);
Effects: Computes a matrix such that , and assigns each element of to the corresponding element of C.
template<in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, possibly-packed-inout-matrix InOutMat, class Triangle> void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InOutMat C, Triangle t);
Effects: Computes a matrix such that , and assigns each element of to the corresponding element of C.

29.9.15.6 Solve multiple triangular linear systems [linalg.algs.blas3.trsm]

[Note 1: 
These functions correspond to the BLAS function xTRSM[bib].
— end note]
template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide);
These functions perform multiple matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Mandates:
  • If InMat1 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<InMat1, OutMat, InMat2>() is true; and
  • compatible-static-extents<InMat1, InMat1>(0, 1) is true.
Preconditions:
  • multipliable(A, X, B) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of X.
If no such exists, then the elements of X are valid but unspecified.
Complexity: .
[Note 2: 
Since the triangular matrix is on the left, the desired divide implementation in the case of noncommutative multiplication is mathematically equivalent to , where x is the first argument and y is the second argument, and denotes the multiplicative inverse of y.
— end note]
template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X);
Effects: Equivalent to: triangular_matrix_matrix_left_solve(A, t, d, B, X, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X);
Effects: Equivalent to: triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, X, divides<void>{});
template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X, BinaryDivideOp divide);
These functions perform multiple matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
Mandates:
  • If InMat1 has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<OutMat, InMat1, InMat2>() is true; and
  • compatible-static-extents<InMat1, InMat1>(0,1) is true.
Preconditions:
  • multipliable(X, A, B) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of X.
If no such exists, then the elements of X are valid but unspecified.
Complexity: O( B.extent(0) B.extent(1) A.extent(1) )
[Note 3: 
Since the triangular matrix is on the right, the desired divide implementation in the case of noncommutative multiplication is mathematically equivalent to , where x is the first argument and y is the second argument, and denotes the multiplicative inverse of y.
— end note]
template<in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X);
Effects: Equivalent to: triangular_matrix_matrix_right_solve(A, t, d, B, X, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage, in-matrix InMat2, out-matrix OutMat> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat X);
Effects: Equivalent to: triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, X, divides<void>{});

29.9.15.7 Solve multiple triangular linear systems in-place [linalg.algs.blas3.inplacetrsm]

[Note 1: 
These functions correspond to the BLAS function xTRSM[bib].
— end note]
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide);
These functions perform multiple in-place matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
[Note 2: 
This algorithm makes it possible to compute factorizations like Cholesky and LU in place.
Performing triangular solve in place hinders parallelization.
However, other ExecutionPolicy specific optimizations, such as vectorization, are still possible.
— end note]
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<InMat, InOutMat, InOutMat>() is true; and
  • compatible-static-extents<InMat, InMat>(0, 1) is true.
Preconditions:
  • multipliable(A, B, B) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of B.
If so such exists, then the elements of B are valid but unspecified.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B);
Effects: Equivalent to: triangular_matrix_matrix_left_solve(A, t, d, B, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B);
Effects: Equivalent to: triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, divides<void>{});
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide); template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat, class BinaryDivideOp> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B, BinaryDivideOp divide);
These functions perform multiple in-place matrix solves, taking into account the Triangle and DiagonalStorage parameters that apply to the triangular matrix A ([linalg.general]).
[Note 3: 
This algorithm makes it possible to compute factorizations like Cholesky and LU in place.
Performing triangular solve in place hinders parallelization.
However, other ExecutionPolicy specific optimizations, such as vectorization, are still possible.
— end note]
Mandates:
  • If InMat has layout_blas_packed layout, then the layout's Triangle template argument has the same type as the function's Triangle template argument;
  • possibly-multipliable<InOutMat, InMat, InOutMat>() is true; and
  • compatible-static-extents<InMat, InMat>(0, 1) is true.
Preconditions:
  • multipliable(B, A, B) is true, and
  • A.extent(0) == A.extent(1) is true.
Effects: Computes such that , and assigns each element of to the corresponding element of B.
If so such exists, then the elements of B are valid but unspecified.
Complexity: .
template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B);
Effects: Equivalent to: triangular_matrix_matrix_right_solve(A, t, d, B, divides<void>{});
template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat> void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, InMat A, Triangle t, DiagonalStorage d, InOutMat B);
Effects: Equivalent to: triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec), A, t, d, B, divides<void>{});

29.10 Data-parallel types [simd]

29.10.1 General [simd.general]

Subclause [simd] defines data-parallel types and operations on these types.
[Note 1: 
The intent is to support acceleration through data-parallel execution resources where available, such as SIMD registers and instructions or execution units driven by a common instruction decoder.
SIMD stands for “Single Instruction Stream – Multiple Data Stream”; it is defined in Flynn 1966[bib].
— end note]
The set of vectorizable types comprises all standard integer types, character types, and the types float and double ([basic.fundamental]).
In addition, std​::​float16_t, std​::​float32_t, and std​::​float64_t are vectorizable types if defined ([basic.extended.fp]).
The term data-parallel type refers to all enabled specializations of the basic_simd and basic_simd_mask class templates.
A data-parallel object is an object of data-parallel type.
Each specialization of basic_simd or basic_simd_mask is either enabled or disabled, as described in [simd.overview] and [simd.mask.overview].
A data-parallel type consists of one or more elements of an underlying vectorizable type, called the element type.
The number of elements is a constant for each data-parallel type and called the width of that type.
The elements in a data-parallel type are indexed from 0 to .
An element-wise operation applies a specified operation to the elements of one or more data-parallel objects.
Each such application is unsequenced with respect to the others.
A unary element-wise operation is an element-wise operation that applies a unary operation to each element of a data-parallel object.
A binary element-wise operation is an element-wise operation that applies a binary operation to corresponding elements of two data-parallel objects.
Given a basic_simd_mask<Bytes, Abi> object mask, the selected indices signify the integers i in the range [0, mask.size()) for which mask[i] is true.
Given a data-parallel object data, the selected elements signify the elements data[i] for all selected indices i.
The conversion from an arithmetic type U to a vectorizable type T is value-preserving if all possible values of U can be represented with type T.

29.10.2 Exposition-only types, variables, and concepts [simd.expos]

using simd-size-type = see below; // exposition only template<size_t Bytes> using integer-from = see below; // exposition only template<class T, class Abi> constexpr simd-size-type simd-size-v = see below; // exposition only template<class T> constexpr size_t mask-element-size = see below; // exposition only template<class T> concept constexpr-wrapper-like = // exposition only convertible_to<T, decltype(T::value)> && equality_comparable_with<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value; template<class T> using deduced-simd-t = see below; // exposition only template<class V, class T> using make-compatible-simd-t = see below; // exposition only template<class V> concept simd-floating-point = // exposition only same_as<V, basic_simd<typename V::value_type, typename V::abi_type>> && is_default_constructible_v<V> && floating_point<typename V::value_type>; template<class... Ts> concept math-floating-point = // exposition only (simd-floating-point<deduced-simd-t<Ts>> || ...); template<class... Ts> requires math-floating-point<Ts...> using math-common-simd-t = see below; // exposition only template<class BinaryOperation, class T> concept reduction-binary-operation = see below; // exposition only // [simd.expos.abi], simd ABI tags template<class T> using native-abi = see below; // exposition only template<class T, simd-size-type N> using deduce-abi-t = see below; // exposition only // [simd.flags], Load and store flags struct convert-flag; // exposition only struct aligned-flag; // exposition only template<size_t N> struct overaligned-flag; // exposition only

29.10.2.1 Exposition-only helpers [simd.expos.defn]

using simd-size-type = see below;
simd-size-type is an alias for a signed integer type.
template<size_t Bytes> using integer-from = see below;
integer-from<Bytes> is an alias for a signed integer type T such that sizeof(T) equals Bytes.
template<class T, class Abi> constexpr simd-size-type simd-size-v = see below;
simd-size-v<T, Abi> denotes the width of basic_simd<T, Abi> if the specialization basic_simd<T, Abi> is enabled, or 0 otherwise.
template<class T> constexpr size_t mask-element-size = see below;
mask-element-size<basic_simd_mask<Bytes, Abi>> has the value Bytes.
template<class T> using deduced-simd-t = see below;
Let x denote an lvalue of type const T.
deduced-simd-t<T> is an alias for
  • decltype(x + x), if the type of x + x is an enabled specialization of basic_simd; otherwise
  • void.
template<class V, class T> using make-compatible-simd-t = see below;
Let x denote an lvalue of type const T.
make-compatible-simd-t<V, T> is an alias for
  • deduced-simd-t<T>, if that type is not void, otherwise
  • simd<decltype(x + x), V​::​size()>.
template<class... Ts> requires math-floating-point<Ts...> using math-common-simd-t = see below;
Let T0 denote Ts...[0].
Let T1 denote Ts...[1].
Let TRest denote a pack such that T0, T1, TRest... is equivalent to Ts....
Let math-common-simd-t<Ts...> be an alias for
  • deduced-simd-t<T0>, if sizeof...(Ts) equals 1; otherwise
  • common_type_t<deduced-simd-t<T0>, deduced-simd-t<T1>>, if sizeof...(Ts) equals 2 and math-floating-point<T0> && math-floating-point<T1> is true; otherwise
  • common_type_t<deduced-simd-t<T0>, T1>, if sizeof...(Ts) equals 2 and math-floating-​point<​T0> is true; otherwise
  • common_type_t<T0, deduced-simd-t<T1>>, if sizeof...(Ts) equals 2; otherwise
  • common_type_t<math-common-simd-t<T0, T1>, TRest...>, if math-common-simd-t<T0, T1> is valid and denotes a type; otherwise
  • common_type_t<math-common-simd-t<TRest...>, T0, T1>.
template<class BinaryOperation, class T> concept reduction-binary-operation = requires (const BinaryOperation binary_op, const simd<T, 1> v) { { binary_op(v, v) } -> same_as<simd<T, 1>>; };
Types BinaryOperation and T model reduction-binary-operation<BinaryOperation, T> only if:
  • BinaryOperation is a binary element-wise operation and the operation is commutative.
  • An object of type BinaryOperation can be invoked with two arguments of type basic_simd<T, Abi>, with unspecified ABI tag Abi, returning a basic_simd<T, Abi>.

29.10.2.2 simd ABI tags [simd.expos.abi]

template<class T> using native-abi = see below; template<class T, simd-size-type N> using deduce-abi-t = see below;
An ABI tag is a type that indicates a choice of size and binary representation for objects of data-parallel type.
[Note 1: 
The intent is for the size and binary representation to depend on the target architecture and compiler flags.
The ABI tag, together with a given element type, implies the width.
— end note]
[Note 2: 
The ABI tag is orthogonal to selecting the machine instruction set.
The selected machine instruction set limits the usable ABI tag types, though (see [simd.overview]).
The ABI tags enable users to safely pass objects of data-parallel type between translation unit boundaries (e.g., function calls or I/O).
— end note]
An implementation defines ABI tag types as necessary for the following aliases.
deduce-abi-t<T, N> is defined if
  • T is a vectorizable type,
  • N is greater than zero, and
  • N is not larger than an implementation-defined maximum.
The implementation-defined maximum for N is not smaller than 64 and can differ depending on T.
Where present, deduce-abi-t<T, N> names an ABI tag type such that
  • simd-size-v<T, deduce-abi-t<T, N>> equals N,
  • basic_simd<T, deduce-abi-t<T, N>> is enabled ([simd.overview]), and
  • basic_simd_mask<sizeof(T), deduce-abi-t<integer-from<sizeof(T)>, N>> is enabled.
native-abi<T> is an implementation-defined alias for an ABI tag.
basic_simd<T, native-abi<T>> is an enabled specialization.
[Note 3: 
The intent is to use the ABI tag producing the most efficient data-parallel execution for the element type T on the currently targeted system.
For target architectures with ISA extensions, compiler flags can change the type of the native-abi<T> alias.
— end note]
[Example 1: 
Consider a target architecture supporting the ABI tags __simd128 and __simd256, where hardware support for __simd256 exists only for floating-point types.
The implementation therefore defines native-abi<T> as an alias for
  • __simd256 if T is a floating-point type, and
  • __simd128 otherwise.
— end example]

29.10.3 Header <simd> synopsis [simd.syn]

namespace std { // [simd.traits], simd type traits template<class T, class U = typename T::value_type> struct simd_alignment; template<class T, class U = typename T::value_type> constexpr size_t simd_alignment_v = simd_alignment<T, U>::value; template<class T, class V> struct rebind_simd { using type = see below; }; template<class T, class V> using rebind_simd_t = typename rebind_simd<T, V>::type; template<simd-size-type N, class V> struct resize_simd { using type = see below; }; template<simd-size-type N, class V> using resize_simd_t = typename resize_simd<N, V>::type; // [simd.flags], Load and store flags template<class... Flags> struct simd_flags; inline constexpr simd_flags<> simd_flag_default{}; inline constexpr simd_flags<convert-flag> simd_flag_convert{}; inline constexpr simd_flags<aligned-flag> simd_flag_aligned{}; template<size_t N> requires (has_single_bit(N)) constexpr simd_flags<overaligned-flag<N>> simd_flag_overaligned{}; // [simd.class], Class template basic_simd template<class T, class Abi = native-abi<T>> class basic_simd; template<class T, simd-size-type N = simd-size-v<T, native-abi<T>>> using simd = basic_simd<T, deduce-abi-t<T, N>>; // [simd.mask.class], Class template basic_simd_mask template<size_t Bytes, class Abi = native-abi<integer-from<Bytes>>> class basic_simd_mask; template<class T, simd-size-type N = simd-size-v<T, native-abi<T>>> using simd_mask = basic_simd_mask<sizeof(T), deduce-abi-t<T, N>>; // [simd.loadstore], basic_simd load and store functions template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, const typename V::mask_type& k, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store( const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store( const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); // [simd.creation], basic_simd and basic_simd_mask creation template<class T, class Abi> constexpr auto simd_split(const basic_simd<typename T::value_type, Abi>& x) noexcept; template<class T, class Abi> constexpr auto simd_split(const basic_simd_mask<mask-element-size<T>, Abi>& x) noexcept; template<class T, class... Abis> constexpr basic_simd<T, deduce-abi-t<T, (basic_simd<T, Abis>::size() + ...)>> simd_cat(const basic_simd<T, Abis>&...) noexcept; template<size_t Bytes, class... Abis> constexpr basic_simd_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_simd_mask<Bytes, Abis>::size() + ...)>> simd_cat(const basic_simd_mask<Bytes, Abis>&...) noexcept; // [simd.mask.reductions], basic_simd_mask reductions template<size_t Bytes, class Abi> constexpr bool all_of(const basic_simd_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi> constexpr bool any_of(const basic_simd_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi> constexpr bool none_of(const basic_simd_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi> constexpr simd-size-type reduce_count(const basic_simd_mask<Bytes, Abi>&) noexcept; template<size_t Bytes, class Abi> constexpr simd-size-type reduce_min_index(const basic_simd_mask<Bytes, Abi>&); template<size_t Bytes, class Abi> constexpr simd-size-type reduce_max_index(const basic_simd_mask<Bytes, Abi>&); constexpr bool all_of(same_as<bool> auto) noexcept; constexpr bool any_of(same_as<bool> auto) noexcept; constexpr bool none_of(same_as<bool> auto) noexcept; constexpr simd-size-type reduce_count(same_as<bool> auto) noexcept; constexpr simd-size-type reduce_min_index(same_as<bool> auto); constexpr simd-size-type reduce_max_index(same_as<bool> auto); // [simd.reductions], basic_simd reductions template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce(const basic_simd<T, Abi>&, BinaryOperation = {}); template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce( const basic_simd<T, Abi>& x, const typename basic_simd<T, Abi>::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below); template<class T, class Abi> constexpr T reduce_min(const basic_simd<T, Abi>&) noexcept; template<class T, class Abi> constexpr T reduce_min(const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept; template<class T, class Abi> constexpr T reduce_max(const basic_simd<T, Abi>&) noexcept; template<class T, class Abi> constexpr T reduce_max(const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept; // [simd.alg], Algorithms template<class T, class Abi> constexpr basic_simd<T, Abi> min(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept; template<class T, class Abi> constexpr basic_simd<T, Abi> max(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept; template<class T, class Abi> constexpr pair<basic_simd<T, Abi>, basic_simd<T, Abi>> minmax(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept; template<class T, class Abi> constexpr basic_simd<T, Abi> clamp(const basic_simd<T, Abi>& v, const basic_simd<T, Abi>& lo, const basic_simd<T, Abi>& hi); template<class T, class U> constexpr auto simd_select(bool c, const T& a, const U& b) -> remove_cvref_t<decltype(c ? a : b)>; template<size_t Bytes, class Abi, class T, class U> constexpr auto simd_select(const basic_simd_mask<Bytes, Abi>& c, const T& a, const U& b) noexcept -> decltype(simd-select-impl(c, a, b)); // [simd.math], Mathematical functions template<math-floating-point V> constexpr deduced-simd-t<V> acos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asin(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> atan(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x); template<math-floating-point V> constexpr deduced-simd-t<V> cos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sin(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tan(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> acosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> atanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> cosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> expm1(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> frexp(const V& value, rebind_simd_t<int, deduced-simd-t<V>>* exp); template<math-floating-point V> constexpr rebind_simd_t<int, deduced-simd-t<V>> ilogb(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ldexp(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& exp); template<math-floating-point V> constexpr deduced-simd-t<V> log(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log10(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log1p(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> logb(const V& x); template<class T, class Abi> constexpr basic_simd<T, Abi> modf(const type_identity_t<basic_simd<T, Abi>>& value, basic_simd<T, Abi>* iptr); template<math-floating-point V> constexpr deduced-simd-t<V> scalbn(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& n); template<math-floating-point V> constexpr deduced-simd-t<V> scalbln( const V& x, const rebind_simd_t<long int, deduced-simd-t<V>>& n); template<math-floating-point V> constexpr deduced-simd-t<V> cbrt(const V& x); template<signed_integral T, class Abi> constexpr basic_simd<T, Abi> abs(const basic_simd<T, Abi>& j); template<math-floating-point V> constexpr deduced-simd-t<V> abs(const V& j); template<math-floating-point V> constexpr deduced-simd-t<V> fabs(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y); template<math-floating-point V> constexpr deduced-simd-t<V> sqrt(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erf(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erfc(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> lgamma(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tgamma(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ceil(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> floor(const V& x); template<math-floating-point V> deduced-simd-t<V> nearbyint(const V& x); template<math-floating-point V> deduced-simd-t<V> rint(const V& x); template<math-floating-point V> rebind_simd_t<long int, deduced-simd-t<V>> lrint(const V& x); template<math-floating-point V> rebind_simd_t<long long int, V> llrint(const deduced-simd-t<V>& x); template<math-floating-point V> constexpr deduced-simd-t<V> round(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long int, deduced-simd-t<V>> lround(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long long int, deduced-simd-t<V>> llround(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> trunc(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remquo(const V0& x, const V1& y, rebind_simd_t<int, math-common-simd-t<V0, V1>>* quo); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept; template<math-floating-point V> constexpr rebind_simd_t<int, deduced-simd-t<V>> fpclassify(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isfinite(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isinf(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnan(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnormal(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type signbit(const V& x); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreaterequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isless(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isunordered(const V0& x, const V1& y); template<math-floating-point V> deduced-simd-t<V> assoc_laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& x); template<math-floating-point V> deduced-simd-t<V> assoc_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& x); template<class V0, class V1> math-common-simd-t<V0, V1> beta(const V0& x, const V1& y); template<math-floating-point V> deduced-simd-t<V> comp_ellint_1(const V& k); template<math-floating-point V> deduced-simd-t<V> comp_ellint_2(const V& k); template<class V0, class V1> math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi); template<class V0, class V1, class V2> math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi); template<math-floating-point V> deduced-simd-t<V> expint(const V& x); template<math-floating-point V> deduced-simd-t<V> hermite(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const V& x); template<math-floating-point V> deduced-simd-t<V> riemann_zeta(const V& x); template<math-floating-point V> deduced-simd-t<V> sph_bessel( const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> sph_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& theta); template<math-floating-point V> deduced-simd-t<V> sph_neumann(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); }

29.10.4 simd type traits [simd.traits]

template<class T, class U = typename T::value_type> struct simd_alignment { see below };
simd_alignment<T, U> has a member value if and only if
  • T is a specialization of basic_simd_mask and U is bool, or
  • T is a specialization of basic_simd and U is a vectorizable type.
If value is present, the type simd_alignment<T, U> is a BinaryTypeTrait with a base characteristic of integral_constant<size_t, N> for some unspecified N ([simd.ctor], [simd.loadstore])).
[Note 1: 
value identifies the alignment restrictions on pointers used for (converting) loads and stores for the given type T on arrays of type U.
— end note]
The behavior of a program that adds specializations for simd_alignment is undefined.
template<class T, class V> struct rebind_simd { using type = see below; };
The member type is present if and only if
  • V is a data-parallel type,
  • T is a vectorizable type, and
  • deduce-abi-t<T, V​::​size()> has a member type type.
If V is a specialization of basic_simd, let Abi1 denote an ABI tag such that basic_simd<T, Abi1>​::​​size() equals V​::​size().
If V is a specialization of basic_simd_mask, let Abi1 denote an ABI tag such that basic_simd_mask<sizeof(T), Abi1>​::​​size() equals V​::​size().
Where present, the member typedef type names basic_simd<T, Abi1> if V is a specialization of basic_simd or basic_simd_mask<sizeof(T), Abi1> if V is a specialization of basic_simd_mask.
template<simd-size-type N, class V> struct resize_simd { using type = see below; };
Let T denote
  • typename V​::​value_type if V is a specialization of basic_simd,
  • otherwise integer-from<mask-element-size<V>> if V is a specialization of basic_simd_mask.
The member type is present if and only if
  • V is a data-parallel type, and
  • deduce-abi-t<T, N> has a member type type.
If V is a specialization of basic_simd, let Abi1 denote an ABI tag such that basic_simd<T, Abi1>​::​​size() equals V​::​size().
If V is a specialization of basic_simd_mask, let Abi1 denote an ABI tag such that basic_simd_mask<sizeof(T), Abi1>​::​​size() equals V​::​size().
Where present, the member typedef type names basic_simd<T, Abi1> if V is a specialization of basic_simd or basic_simd_mask<sizeof(T), Abi1> if V is a specialization of basic_simd_mask.

29.10.5 Load and store flags [simd.flags]

29.10.5.1 Class template simd_flags overview [simd.flags.overview]

namespace std { template<class... Flags> struct simd_flags { // [simd.flags.oper], simd_flags operators template<class... Other> friend consteval auto operator|(simd_flags, simd_flags<Other...>); }; }
[Note 1: 
The class template simd_flags acts like an integer bit-flag for types.
— end note]
Constraints: Every type in the parameter pack Flags is one of convert-flag, aligned-flag, or overaligned-​flag<N>.

29.10.5.2 simd_flags operators [simd.flags.oper]

template<class... Other> friend consteval auto operator|(simd_flags a, simd_flags<Other...> b);
Returns: A default-initialized object of type simd_flags<Flags2...> for some Flags2 where every type in Flags2 is present either in template parameter pack Flags or in template parameter pack Other, and every type in template parameter packs Flags and Other is present in Flags2.
If the packs Flags and Other contain two different specializations overaligned-flag<N1> and overaligned-flag<N2>, Flags2 is not required to contain the specialization overaligned-flag<std​::​min(N1, N2)>.

29.10.6 Class template basic_simd [simd.class]

29.10.6.1 Class template basic_simd overview [simd.overview]

namespace std { template<class T, class Abi> class basic_simd { public: using value_type = T; using mask_type = basic_simd_mask<sizeof(T), Abi>; using abi_type = Abi; static constexpr integral_constant<simd-size-type, simd-size-v<T, Abi>> size {}; constexpr basic_simd() noexcept = default; // [simd.ctor], basic_simd constructors template<class U> constexpr basic_simd(U&& value) noexcept; template<class U, class UAbi> constexpr explicit(see below) basic_simd(const basic_simd<U, UAbi>&) noexcept; template<class G> constexpr explicit basic_simd(G&& gen) noexcept; template<class R, class... Flags> constexpr basic_simd(R&& range, simd_flags<Flags...> = {}); template<class R, class... Flags> constexpr basic_simd(R&& range, const mask_type& mask, simd_flags<Flags...> = {}); // [simd.subscr], basic_simd subscript operators constexpr value_type operator[](simd-size-type) const; // [simd.unary], basic_simd unary operators constexpr basic_simd& operator++() noexcept; constexpr basic_simd operator++(int) noexcept; constexpr basic_simd& operator--() noexcept; constexpr basic_simd operator--(int) noexcept; constexpr mask_type operator!() const noexcept; constexpr basic_simd operator~() const noexcept; constexpr basic_simd operator+() const noexcept; constexpr basic_simd operator-() const noexcept; // [simd.binary], basic_simd binary operators friend constexpr basic_simd operator+(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator-(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator*(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator/(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator%(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator&(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator|(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator^(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator<<(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator>>(const basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd operator<<(const basic_simd&, simd-size-type) noexcept; friend constexpr basic_simd operator>>(const basic_simd&, simd-size-type) noexcept; // [simd.cassign], basic_simd compound assignment friend constexpr basic_simd& operator+=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator-=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator*=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator/=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator%=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator&=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator|=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator^=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator<<=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator>>=(basic_simd&, const basic_simd&) noexcept; friend constexpr basic_simd& operator<<=(basic_simd&, simd-size-type) noexcept; friend constexpr basic_simd& operator>>=(basic_simd&, simd-size-type) noexcept; // [simd.comparison], basic_simd compare operators friend constexpr mask_type operator==(const basic_simd&, const basic_simd&) noexcept; friend constexpr mask_type operator!=(const basic_simd&, const basic_simd&) noexcept; friend constexpr mask_type operator>=(const basic_simd&, const basic_simd&) noexcept; friend constexpr mask_type operator<=(const basic_simd&, const basic_simd&) noexcept; friend constexpr mask_type operator>(const basic_simd&, const basic_simd&) noexcept; friend constexpr mask_type operator<(const basic_simd&, const basic_simd&) noexcept; // [simd.cond], basic_simd exposition only conditional operators friend constexpr basic_simd simd-select-impl( // exposition only const mask_type&, const basic_simd&, const basic_simd&) noexcept; }; template<class R, class... Ts> basic_simd(R&& r, Ts...) -> see below; }
Every specialization of basic_simd is a complete type.
The specialization of basic_simd<T, Abi> is
  • enabled, if T is a vectorizable type, and there exists value N in the range [1, 64], such that Abi is deduce-abi-t<T, N>,
  • otherwise, disabled, if T is not a vectorizable type,
  • otherwise, it is implementation-defined if such a specialization is enabled.
If basic_simd<T, Abi> is disabled, the specialization has a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment.
In addition only the value_type, abi_type, and mask_type members are present.
If basic_simd<T, Abi> is enabled, basic_simd<T, Abi> is trivially copyable.
Recommended practice: Implementations should support explicit conversions between specializations of basic_simd and appropriate implementation-defined types.
[Note 1: 
Appropriate types are non-standard vector types which are available in the implementation.
— end note]

29.10.6.2 basic_simd constructors [simd.ctor]

template<class U> constexpr basic_simd(U&&) noexcept;
Let From denote the type remove_cvref_t<U>.
Constraints: From satisfies convertible_to<value_type>, and either
Effects: Initializes each element to the value of the argument after conversion to value_type.
template<class U, class UAbi> constexpr explicit(see below) basic_simd(const basic_simd<U, UAbi>& x) noexcept;
Constraints: simd-size-v<U, UAbi> == size() is true.
Effects: Initializes the element with static_cast<T>(x[i]) for all i in the range of [0, size()).
Remarks: The expression inside explicit evaluates to true if either
  • the conversion from U to value_type is not value-preserving, or
  • both U and value_type are integral types and the integer conversion rank ([conv.rank]) of U is greater than the integer conversion rank of value_type, or
  • both U and value_type are floating-point types and the floating-point conversion rank ([conv.rank]) of U is greater than the floating-point conversion rank of value_type.
template<class G> constexpr explicit basic_simd(G&& gen) noexcept;
Let From denote the type decltype(gen(integral_constant<simd-size-type, i>())).
Constraints: From satisfies convertible_to<value_type> for all i in the range of [0, size()).
In addition, for all i in the range of [0, size()), if From is an arithmetic type, conversion from From to value_type is value-preserving.
Effects: Initializes the element with static_cast<value_type>(gen(integral_constant<simd-​size-​type, i>())) for all i in the range of [0, size()).
Remarks: The calls to gen are unsequenced with respect to each other.
Vectorization-unsafe ([algorithms.parallel.defns]) standard library functions may not be invoked by gen.
gen is invoked exactly once for each i.
template<class R, class... Flags> constexpr basic_simd(R&& r, simd_flags<Flags...> = {}); template<class R, class... Flags> constexpr basic_simd(R&& r, const mask_type& mask, simd_flags<Flags...> = {});
Let mask be mask_type(true) for the overload with no mask parameter.
Constraints:
  • R models ranges​::​contiguous_range and ranges​::​sized_range,
  • ranges​::​size(r) is a constant expression, and
  • ranges​::​size(r) is equal to size().
Mandates:
  • ranges​::​range_value_t<R> is a vectorizable type, and
  • if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges​::​range_value_t<R> to value_type is value-preserving.
Preconditions:
  • If the template parameter pack Flags contains aligned-flag, ranges​::​data(range) points to storage aligned by simd_alignment_v<basic_simd, ranges​::​range_value_t<R>>.
  • If the template parameter pack Flags contains overaligned-flag<N>, ranges​::​data(range) points to storage aligned by N.
Effects: Initializes the element with mask[i] ? static_cast<T>(​ranges​::​​data(range)[i]) : T() for all i in the range of [0, size()).
template<class R, class... Ts> basic_simd(R&& r, Ts...) -> see below;
Constraints:
  • R models ranges​::​contiguous_range and ranges​::​sized_range, and
  • ranges​::​size(r) is a constant expression.
Remarks: The deduced type is equivalent to simd<ranges​::​range_value_t<R>, ranges​::​size(r)>.

29.10.6.3 basic_simd subscript operator [simd.subscr]

constexpr value_type operator[](simd-size-type i) const;
Preconditions: i >= 0 && i < size() is true.
Returns: The value of the element.
Throws: Nothing.

29.10.6.4 basic_simd unary operators [simd.unary]

Effects in [simd.unary] are applied as unary element-wise operations.
constexpr basic_simd& operator++() noexcept;
Constraints: requires (value_type a) { ++a; } is true.
Effects: Increments every element by one.
Returns: *this.
constexpr basic_simd operator++(int) noexcept;
Constraints: requires (value_type a) { a++; } is true.
Effects: Increments every element by one.
Returns: A copy of *this before incrementing.
constexpr basic_simd& operator--() noexcept;
Constraints: requires (value_type a) { --a; } is true.
Effects: Decrements every element by one.
Returns: *this.
constexpr basic_simd operator--(int) noexcept;
Constraints: requires (value_type a) { a--; } is true.
Effects: Decrements every element by one.
Returns: A copy of *this before decrementing.
constexpr mask_type operator!() const noexcept;
Constraints: requires (const value_type a) { !a; } is true.
Returns: A basic_simd_mask object with the element set to !operator[](i) for all i in the range of [0, size()).
constexpr basic_simd operator~() const noexcept;
Constraints: requires (const value_type a) { ~a; } is true.
Returns: A basic_simd object with the element set to ~operator[](i) for all i in the range of [0, size()).
constexpr basic_simd operator+() const noexcept;
Constraints: requires (const value_type a) { +a; } is true.
Returns: *this.
constexpr basic_simd operator-() const noexcept;
Constraints: requires (const value_type a) { -a; } is true.
Returns: A basic_simd object where the element is initialized to -operator[](i) for all i in the range of [0, size()).

29.10.7 basic_simd non-member operations [simd.nonmembers]

29.10.7.1 basic_simd binary operators [simd.binary]

friend constexpr basic_simd operator+(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator-(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator*(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator/(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator%(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator&(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator|(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator^(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator<<(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd operator>>(const basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Returns: A basic_simd object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.
friend constexpr basic_simd operator<<(const basic_simd& v, simd-size-type n) noexcept; friend constexpr basic_simd operator>>(const basic_simd& v, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { a op b; } is true.
Returns: A basic_simd object where the element is initialized to the result of applying op to v[i] and n for all i in the range of [0, size()).

29.10.7.2 basic_simd compound assignment [simd.cassign]

friend constexpr basic_simd& operator+=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator-=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator*=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator/=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator%=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator&=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator|=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator^=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator<<=(basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr basic_simd& operator>>=(basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Effects: These operators apply the indicated operator to lhs and rhs as an element-wise operation.
Returns: lhs.
friend constexpr basic_simd& operator<<=(basic_simd& lhs, simd-size-type n) noexcept; friend constexpr basic_simd& operator>>=(basic_simd& lhs, simd-size-type n) noexcept;
Let op be the operator.
Constraints: requires (value_type a, simd-size-type b) { a op b; } is true.
Effects: Equivalent to: return operator op (lhs, basic_simd(n));

29.10.7.3 basic_simd compare operators [simd.comparison]

friend constexpr mask_type operator==(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator!=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator>=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator<=(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator>(const basic_simd& lhs, const basic_simd& rhs) noexcept; friend constexpr mask_type operator<(const basic_simd& lhs, const basic_simd& rhs) noexcept;
Let op be the operator.
Constraints: requires (value_type a, value_type b) { a op b; } is true.
Returns: A basic_simd_mask object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.

29.10.7.4 basic_simd exposition only conditional operators [simd.cond]

friend constexpr basic_simd simd-select-impl(const mask_type& mask, const basic_simd& a, const basic_simd& b) noexcept;
Returns: A basic_simd object where the element equals mask[i] ? a[i] : b[i] for all i in the range of [0, size()).

29.10.7.5 basic_simd reductions [simd.reductions]

template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce(const basic_simd<T, Abi>& x, BinaryOperation binary_op = {});
Constraints: BinaryOperation models reduction-binary-operation<T>.
Preconditions: binary_op does not modify x.
Returns: GENERALIZED_SUM(binary_op, simd<T, 1>(x[0]), , simd<T, 1>(x[x.size() - 1]))[0] ([numerics.defns]).
Throws: Any exception thrown from binary_op.
template<class T, class Abi, class BinaryOperation = plus<>> constexpr T reduce( const basic_simd<T, Abi>& x, const typename basic_simd<T, Abi>::mask_type& mask, BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below);
Constraints:
  • BinaryOperation models reduction-binary-operation<T>.
  • An argument for identity_element is provided for the invocation, unless BinaryOperation is one of plus<>, multiplies<>, bit_and<>, bit_or<>, or bit_xor<>.
Preconditions:
  • binary_op does not modify x.
  • For all finite values y representable by T, the results of y == binary_op(simd<T, 1>(identity_element), simd<T, 1>(y))[0] and y == binary_op(simd<T, 1>(y), simd<T, 1>(identity_element))[0] are true.
Returns: If none_of(mask) is true, returns identity_element.
Otherwise, returns GENERALIZED_SUM(binary_op, simd<T, 1>(x[]), , simd<T, 1>(x[]))[0] where are the selected indices of mask.
Throws: Any exception thrown from binary_op.
Remarks: The default argument for identity_element is equal to
  • T() if BinaryOperation is plus<>,
  • T(1) if BinaryOperation is multiplies<>,
  • T(~T()) if BinaryOperation is bit_and<>,
  • T() if BinaryOperation is bit_or<>, or
  • T() if BinaryOperation is bit_xor<>.
template<class T, class Abi> constexpr T reduce_min(const basic_simd<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[i] < x[j] is false for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr T reduce_min( const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returns numeric_limits<T>​::​max().
Otherwise, returns the value of a selected element x[j] for which x[i] < x[j] is false for all selected indices i of mask.
template<class T, class Abi> constexpr T reduce_max(const basic_simd<T, Abi>& x) noexcept;
Constraints: T models totally_ordered.
Returns: The value of an element x[j] for which x[j] < x[i] is false for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr T reduce_max( const basic_simd<T, Abi>&, const typename basic_simd<T, Abi>::mask_type&) noexcept;
Constraints: T models totally_ordered.
Returns: If none_of(mask) is true, returns numeric_limits<V​::​value_type>​::​lowest().
Otherwise, returns the value of a selected element x[j] for which x[j] < x[i] is false for all selected indices i of mask.

29.10.7.6 basic_simd load and store functions [simd.loadstore]

template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_unchecked_load(R&& r, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_unchecked_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_unchecked_load(I first, S last, const typename V::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be V​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<const iter_value_t<I>> for the overloads with no template parameter R;
  • r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates: If ranges​::​size(r) is a constant expression then ranges​::​size(r)  ≥  V​::​size().
Preconditions:
  • [first, first + n) is a valid range for the overloads with an n parameter.
  • [first, last) is a valid range for the overloads with a last parameter.
  • ranges​::​size(r)  ≥  V​::​size()
Effects: Equivalent to: return simd_partial_load<V>(r, mask, f);
Remarks: The default argument for template parameter V is basic_simd<ranges​::​range_value_t<R>>.
template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, simd_flags<Flags...> f = {}); template<class V = see below, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> constexpr V simd_partial_load(R&& r, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, class... Flags> constexpr V simd_partial_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, simd_flags<Flags...> f = {}); template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> constexpr V simd_partial_load(I first, S last, const typename V::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be V​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<const iter_value_t<I>> for the overloads with no template parameter R;
  • r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates:
  • ranges​::​range_value_t<R> is a vectorizable type,
  • same_as<remove_cvref_t<V>, V> is true,
  • V is an enabled specialization of basic_simd, and
  • if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges​::​range_value_t<R> to V​::​value_type is value-preserving.
Preconditions:
  • [first, first + n) is a valid range for the overloads with an n parameter.
  • [first, last) is a valid range for the overloads with a last parameter.
  • If the template parameter pack Flags contains aligned-flag, ranges​::​data(r) points to storage aligned by simd_alignment_v<V, ranges​::​range_value_t<R>>.
  • If the template parameter pack Flags contains overaligned-flag<N>, ranges​::​data(r) points to storage aligned by N.
Effects: Initializes the element with
mask[i] && i < ranges​::​size(r) ? static_cast<T>(​ranges​::​data(r)[i]) : T() for all i in the range of [0, V​::​size()).
Remarks: The default argument for template parameter V is basic_simd<ranges​::​range_value_t<R>>.
template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_unchecked_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be basic_simd<T, Abi>​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<iter_value_t<I>> for the overloads with no template parameter R;
  • r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates: If ranges​::​size(r) is a constant expression then ranges​::​size(r)  ≥  simd-size-v<T, Abi>.
Preconditions:
  • [first, first + n) is a valid range for the overloads with an n parameter.
  • [first, last) is a valid range for the overloads with a last parameter.
  • ranges​::​size(r)  ≥  simd-size-v<T, Abi>
Effects: Equivalent to: simd_partial_store(v, r, mask, f).
template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, simd_flags<Flags...> f = {}); template<class T, class Abi, ranges::contiguous_range R, class... Flags> requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, R&& r, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, iter_difference_t<I> n, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, simd_flags<Flags...> f = {}); template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags> requires indirectly_writable<I, T> constexpr void simd_partial_store(const basic_simd<T, Abi>& v, I first, S last, const typename basic_simd<T, Abi>::mask_type& mask, simd_flags<Flags...> f = {});
Let
  • mask be basic_simd<T, Abi>​::​mask_type(true) for the overloads with no mask parameter;
  • R be span<iter_value_t<I>> for the overloads with no template parameter R;
  • r be R(first, n) for the overloads with an n parameter and R(first, last) for the overloads with a last parameter.
Mandates:
  • ranges​::​range_value_t<R> is a vectorizable type, and
  • if the template parameter pack Flags does not contain convert-flag, then the conversion from T to ranges​::​range_value_t<R> is value-preserving.
Preconditions:
  • [first, first + n) is a valid range for the overloads with an n parameter.
  • [first, last) is a valid range for the overloads with a last parameter.
  • If the template parameter pack Flags contains aligned-flag, ranges​::​data(r) points to storage aligned by simd_alignment_v<basic_simd<T, Abi>, ranges​::​range_value_t<R>>.
  • If the template parameter pack Flags contains overaligned-flag<N>, ranges​::​data(r) points to storage aligned by N.
Effects: For all i in the range of [0, basic_simd<T, Abi>​::​size()), if mask[i] && i < ranges​::​​size(r) is true, evaluates ranges​::​data(r)[i] = v[i].

29.10.7.7 basic_simd and basic_simd_mask creation [simd.creation]

template<class T, class Abi> constexpr auto simd_split(const basic_simd<typename T::value_type, Abi>& x) noexcept; template<class T, class Abi> constexpr auto simd_split(const basic_simd_mask<mask-element-size<T>, Abi>& x) noexcept;
Constraints:
  • For the first overload T is an enabled specialization of basic_simd.
    If basic_simd<typename T​::​​value_type, Abi>​::​size() % T​::​size() is not 0 then resize_simd_t<basic_simd<typename T​::​​value_type, Abi>​::​size() % T​::​size(), T> is valid and denotes a type.
  • For the second overload T is an enabled specialization of basic_simd_mask.
    If basic_simd_mask<mask-element-size<T>, Abi>​::​size() % T​::​size() is not 0 then resize_simd_t<​basic_simd_mask<mask-element-size<T>, Abi>​::​size() % T​::​size(), T> is valid and denotes a type.
Let N be x.size() / T​::​size().
Returns:
  • If x.size() % T​::​size() == 0 is true, an array<T, N> with the basic_simd or basic_simd_mask element of the array element initialized to the value of the element in x with index i + j * T​::​size().
  • Otherwise, a tuple of N objects of type T and one object of type resize_simd_t<x.size() % T​::​size(), T>.
    The basic_simd or basic_simd_mask element of the tuple element of type T is initialized to the value of the element in x with index i + j * T​::​size().
    The basic_simd or basic_simd_mask element of the tuple element is initialized to the value of the element in x with index i + N * T​::​size().
template<class T, class... Abis> constexpr simd<T, (basic_simd<T, Abis>::size() + ...)> simd_cat(const basic_simd<T, Abis>&... xs) noexcept; template<size_t Bytes, class... Abis> constexpr basic_simd_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_simd_mask<Bytes, Abis>::size() + ...)>> simd_cat(const basic_simd_mask<Bytes, Abis>&... xs) noexcept;
Constraints:
  • For the first overload simd<T, (basic_simd<T, Abis>​::​size() + ...)> is enabled.
  • For the second overload basic_simd_mask<Bytes, deduce-abi-t<integer-from<Bytes>, (basic_simd_mask<Bytes, Abis>​::​size() + ...)>> is enabled.
Returns: A data-parallel object initialized with the concatenated values in the xs pack of data-parallel objects: The basic_simd/basic_simd_mask element of the parameter in the xs pack is copied to the return value's element with index i + the sum of the width of the first j parameters in the xs pack.

29.10.7.8 Algorithms [simd.alg]

template<class T, class Abi> constexpr basic_simd<T, Abi> min(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept;
Constraints: T models totally_ordered.
Returns: The result of the element-wise application of min(a[i], b[i]) for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr basic_simd<T, Abi> max(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept;
Constraints: T models totally_ordered.
Returns: The result of the element-wise application of max(a[i], b[i]) for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class Abi> constexpr pair<basic_simd<T, Abi>, basic_simd<T, Abi>> minmax(const basic_simd<T, Abi>& a, const basic_simd<T, Abi>& b) noexcept;
Effects: Equivalent to: return pair{min(a, b), max(a, b)};
template<class T, class Abi> constexpr basic_simd<T, Abi> clamp( const basic_simd<T, Abi>& v, const basic_simd<T, Abi>& lo, const basic_simd<T, Abi>& hi);
Constraints: T models totally_ordered.
Preconditions: No element in lo shall be greater than the corresponding element in hi.
Returns: The result of element-wise application of clamp(v[i], lo[i], hi[i]) for all i in the range of [0, basic_simd<T, Abi>​::​size()).
template<class T, class U> constexpr auto simd_select(bool c, const T& a, const U& b) -> remove_cvref_t<decltype(c ? a : b)>;
Effects: Equivalent to: return c ? a : b;
template<size_t Bytes, class Abi, class T, class U> constexpr auto simd_select(const basic_simd_mask<Bytes, Abi>& c, const T& a, const U& b) noexcept -> decltype(simd-select-impl(c, a, b));
Effects: Equivalent to: return simd-select-impl(c, a, b); where simd-select-impl is found by argument-dependent lookup ([basic.lookup.argdep]) contrary to [contents].

29.10.7.9 Mathematical functions [simd.math]

template<math-floating-point V> constexpr rebind_simd_t<int, deduced-simd-t<V>> ilogb(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ldexp(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& exp); template<math-floating-point V> constexpr deduced-simd-t<V> scalbn(const V& x, const rebind_simd_t<int, deduced-simd-t<V>>& n); template<math-floating-point V> constexpr deduced-simd-t<V> scalbln(const V& x, const rebind_simd_t<long int, deduced-simd-t<V>>& n); template<signed_integral T, class Abi> constexpr basic_simd<T, Abi> abs(const basic_simd<T, Abi>& j); template<math-floating-point V> constexpr deduced-simd-t<V> abs(const V& j); template<math-floating-point V> constexpr deduced-simd-t<V> fabs(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> ceil(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> floor(const V& x); template<math-floating-point V> deduced-simd-t<V> nearbyint(const V& x); template<math-floating-point V> deduced-simd-t<V> rint(const V& x); template<math-floating-point V> rebind_simd_t<long int, deduced-simd-t<V>> lrint(const V& x); template<math-floating-point V> rebind_simd_t<long long int, deduced-simd-t<V>> llrint(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> round(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long int, deduced-simd-t<V>> lround(const V& x); template<math-floating-point V> constexpr rebind_simd_t<long long int, deduced-simd-t<V>> llround(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y); template<math-floating-point V> constexpr deduced-simd-t<V> trunc(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z); template<math-floating-point V> constexpr rebind_simd_t<int, deduced-simd-t<V>> fpclassify(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isfinite(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isinf(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnan(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type isnormal(const V& x); template<math-floating-point V> constexpr typename deduced-simd-t<V>::mask_type signbit(const V& x); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isgreaterequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isless(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessequal(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type islessgreater(const V0& x, const V1& y); template<class V0, class V1> constexpr typename math-common-simd-t<V0, V1>::mask_type isunordered(const V0& x, const V1& y);
Let Ret denote the return type of the specialization of a function template with the name math-func.
Let math-func-simd denote: template<class... Args> Ret math-func-simd(Args... args) { return Ret([&](simd-size-type i) { math-func(make-compatible-simd-t<Ret, Args>(args)[i]...); }); }
Returns: A value ret of type Ret, that is element-wise equal to the result of calling math-func-simd with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for index i in math-func-simd a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<math-floating-point V> constexpr deduced-simd-t<V> acos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asin(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> atan(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x); template<math-floating-point V> constexpr deduced-simd-t<V> cos(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sin(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tan(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> acosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> asinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> atanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> cosh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> sinh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tanh(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> exp2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> expm1(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log10(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log1p(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> log2(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> logb(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> cbrt(const V& x); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z); template<class V0, class V1> constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y); template<math-floating-point V> constexpr deduced-simd-t<V> sqrt(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erf(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> erfc(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> lgamma(const V& x); template<math-floating-point V> constexpr deduced-simd-t<V> tgamma(const V& x); template<class V0, class V1, class V2> constexpr math-common-simd-t<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept; template<math-floating-point V> deduced-simd-t<V> assoc_laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& x); template<math-floating-point V> deduced-simd-t<V> assoc_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& x); template<class V0, class V1> math-common-simd-t<V0, V1> beta(const V0& x, const V1& y); template<math-floating-point V> deduced-simd-t<V> comp_ellint_1(const V& k); template<math-floating-point V> deduced-simd-t<V> comp_ellint_2(const V& k); template<class V0, class V1> math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi); template<class V0, class V1> math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi); template<class V0, class V1, class V2> math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi); template<math-floating-point V> deduced-simd-t<V> expint(const V& x); template<math-floating-point V> deduced-simd-t<V> hermite(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> laguerre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const V& x); template<math-floating-point V> deduced-simd-t<V> riemann_zeta(const V& x); template<math-floating-point V> deduced-simd-t<V> sph_bessel(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x); template<math-floating-point V> deduced-simd-t<V> sph_legendre(const rebind_simd_t<unsigned, deduced-simd-t<V>>& l, const rebind_simd_t<unsigned, deduced-simd-t<V>>& m, const V& theta); template<math-floating-point V> deduced-simd-t<V> sph_neumann(const rebind_simd_t<unsigned, deduced-simd-t<V>>& n, const V& x);
Let Ret denote the return type of the specialization of a function template with the name math-func.
Let math-func-simd denote: template<class... Args> Ret math-func-simd(Args... args) { return Ret([&](simd-size-type i) { math-func(make-compatible-simd-t<Ret, Args>(args)[i]...); }); }
Returns: A value ret of type Ret, that is element-wise approximately equal to the result of calling math-func-simd with the arguments of the above functions.
If in an invocation of a scalar overload of math-func for index i in math-func-simd a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<math-floating-point V> constexpr deduced-simd-t<V> frexp(const V& value, rebind_simd_t<int, deduced-simd-t<V>>* exp);
Let Ret be deduced-simd-t<V>.
Let frexp-simd denote: template<class V> pair<Ret, rebind_simd_t<int, Ret>> frexp-simd(const V& x) { int r1[Ret::size()]; Ret r0([&](simd-size-type i) { frexp(make-compatible-simd-t<Ret, V>(x)[i], &r1[i]); }); return {r0, rebind_simd_t<int, Ret>(r1)}; }
Let ret be a value of type pair<Ret, rebind_simd_t<int, Ret>> that is the same value as the result of calling frexp-simd(x).
Effects: Sets *exp to ret.second.
Returns: ret.first.
template<class V0, class V1> constexpr math-common-simd-t<V0, V1> remquo(const V0& x, const V1& y, rebind_simd_t<int, math-common-simd-t<V0, V1>>* quo);
Let Ret be math-common-simd-t<V0, V1>.
Let remquo-simd denote: template<class V0, class V1> pair<Ret, rebind_simd_t<int, Ret>> remquo-simd(const V0& x, const V1& y) { int r1[Ret::size()]; Ret r0([&](simd-size-type i) { remquo(make-compatible-simd-t<Ret, V0>(x)[i], make-compatible-simd-t<Ret, V1>(y)[i], &r1[i]); }); return {r0, rebind_simd_t<int, Ret>(r1)}; }
Let ret be a value of type pair<Ret, rebind_simd_t<int, Ret>> that is the same value as the result of calling remquo-simd(x, y).
If in an invocation of a scalar overload of remquo for index i in remquo-simd a domain, pole, or range error would occur, the value of ret[i] is unspecified.
Effects: Sets *quo to ret.second.
Returns: ret.first.
Remarks: It is unspecified whether errno ([errno]) is accessed.
template<class T, class Abi> constexpr basic_simd<T, Abi> modf(const type_identity_t<basic_simd<T, Abi>>& value, basic_simd<T, Abi>* iptr);
Let V be basic_simd<T, Abi>.
Let modf-simd denote: pair<V, V> modf-simd(const V& x) { T r1[Ret::size()]; V r0([&](simd-size-type i) { modf(V(x)[i], &r1[i]); }); return {r0, V(r1)}; }
Let ret be a value of type pair<V, V> that is the same value as the result of calling modf-simd(value).
Effects: Sets *iptr to ret.second.
Returns: ret.first.

29.10.8 Class template basic_simd_mask [simd.mask.class]

29.10.8.1 Class template basic_simd_mask overview [simd.mask.overview]

namespace std { template<size_t Bytes, class Abi> class basic_simd_mask { public: using value_type = bool; using abi_type = Abi; static constexpr integral_constant<simd-size-type, simd-size-v<integer-from<Bytes>, Abi>> size {}; constexpr basic_simd_mask() noexcept = default; // [simd.mask.ctor], basic_simd_mask constructors constexpr explicit basic_simd_mask(value_type) noexcept; template<size_t UBytes, class UAbi> constexpr explicit basic_simd_mask(const basic_simd_mask<UBytes, UAbi>&) noexcept; template<class G> constexpr explicit basic_simd_mask(G&& gen) noexcept; // [simd.mask.subscr], basic_simd_mask subscript operators constexpr value_type operator[](simd-size-type) const; // [simd.mask.unary], basic_simd_mask unary operators constexpr basic_simd_mask operator!() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator+() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator-() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator~() const noexcept; // [simd.mask.conv], basic_simd_mask conversion operators template<class U, class A> constexpr explicit(sizeof(U) != Bytes) operator basic_simd<U, A>() const noexcept; // [simd.mask.binary], basic_simd_mask binary operators friend constexpr basic_simd_mask operator&&(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator||(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator&(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator|(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator^(const basic_simd_mask&, const basic_simd_mask&) noexcept; // [simd.mask.cassign], basic_simd_mask compound assignment friend constexpr basic_simd_mask& operator&=(basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask& operator|=(basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask& operator^=(basic_simd_mask&, const basic_simd_mask&) noexcept; // [simd.mask.comparison], basic_simd_mask comparisons friend constexpr basic_simd_mask operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept; // [simd.mask.cond], basic_simd_mask exposition only conditional operators friend constexpr basic_simd_mask simd-select-impl( // exposition only const basic_simd_mask&, const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask simd-select-impl( // exposition only const basic_simd_mask&, same_as<bool> auto, same_as<bool> auto) noexcept; template<class T0, class T1> friend constexpr simd<see below, size()> simd-select-impl(const basic_simd_mask&, const T0&, const T1&) noexcept; // exposition only }; }
Every specialization of basic_simd_mask is a complete type.
The specialization of basic_simd_mask<Bytes, Abi> is:
  • disabled, if there is no vectorizable type T such that Bytes is equal to sizeof(T),
  • otherwise, enabled, if there exists a vectorizable type T and a value N in the range [1, 64] such that Bytes is equal to sizeof(T) and Abi is deduce-abi-t<T, N>,
  • otherwise, it is implementation-defined if such a specialization is enabled.
If basic_simd_mask<Bytes, Abi> is disabled, the specialization has a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment.
In addition only the value_type and abi_type members are present.
If basic_simd_mask<Bytes, Abi> is enabled, basic_simd_mask<Bytes, Abi> is trivially copyable.
Recommended practice: Implementations should support explicit conversions between specializations of basic_simd_mask and appropriate implementation-defined types.
[Note 1: 
Appropriate types are non-standard vector types which are available in the implementation.
— end note]

29.10.8.2 basic_simd_mask constructors [simd.mask.ctor]

constexpr explicit basic_simd_mask(value_type x) noexcept;
Effects: Initializes each element with x.
template<size_t UBytes, class UAbi> constexpr explicit basic_simd_mask(const basic_simd_mask<UBytes, UAbi>& x) noexcept;
Constraints: basic_simd_mask<UBytes, UAbi>​::​size() == size() is true.
Effects: Initializes the element with x[i] for all i in the range of [0, size()).
template<class G> constexpr explicit basic_simd_mask(G&& gen) noexcept;
Constraints: The expression gen(integral_constant<simd-size-type, i>()) is well-formed and its type is bool for all i in the range of [0, size()).
Effects: Initializes the element with gen(integral_constant<simd-size-type, i>()) for all i in the range of [0, size()).
Remarks: The calls to gen are unsequenced with respect to each other.
Vectorization-unsafe ([algorithms.parallel.defns]) standard library functions may not be invoked by gen.
gen is invoked exactly once for each i.

29.10.8.3 basic_simd_mask subscript operator [simd.mask.subscr]

constexpr value_type operator[](simd-size-type i) const;
Preconditions: i >= 0 && i < size() is true.
Returns: The value of the element.
Throws: Nothing.

29.10.8.4 basic_simd_mask unary operators [simd.mask.unary]

constexpr basic_simd_mask operator!() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator+() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator-() const noexcept; constexpr basic_simd<integer-from<Bytes>, Abi> operator~() const noexcept;
Let op be the operator.
Returns: A data-parallel object where the element is initialized to the results of applying op to operator[](i) for all i in the range of [0, size()).

29.10.8.5 basic_simd_mask conversion operators [simd.mask.conv]

template<class U, class A> constexpr explicit(sizeof(U) != Bytes) operator basic_simd<U, A>() const noexcept;
Constraints: simd-size-v<U, A> == simd-size-v<T, Abi>.
Returns: A data-parallel object where the element is initialized to static_cast<U>(operator[](i)).

29.10.9 Non-member operations [simd.mask.nonmembers]

29.10.9.1 basic_simd_mask binary operators [simd.mask.binary]

friend constexpr basic_simd_mask operator&&(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask operator||(const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask operator& (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask operator| (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask operator^ (const basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept;
Let op be the operator.
Returns: A basic_simd_mask object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.

29.10.9.2 basic_simd_mask compound assignment [simd.mask.cassign]

friend constexpr basic_simd_mask& operator&=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask& operator|=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept; friend constexpr basic_simd_mask& operator^=(basic_simd_mask& lhs, const basic_simd_mask& rhs) noexcept;
Let op be the operator.
Effects: These operators apply op to lhs and rhs as a binary element-wise operation.
Returns: lhs.

29.10.9.3 basic_simd_mask comparisons [simd.mask.comparison]

friend constexpr basic_simd_mask operator==(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator!=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator>=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator<=(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator>(const basic_simd_mask&, const basic_simd_mask&) noexcept; friend constexpr basic_simd_mask operator<(const basic_simd_mask&, const basic_simd_mask&) noexcept;
Let op be the operator.
Returns: A basic_simd_mask object initialized with the results of applying op to lhs and rhs as a binary element-wise operation.

29.10.9.4 basic_simd_mask exposition only conditional operators [simd.mask.cond]

friend constexpr basic_simd_mask simd-select-impl( const basic_simd_mask& mask, const basic_simd_mask& a, const basic_simd_mask& b) noexcept;
Returns: A basic_simd_mask object where the element equals mask[i] ? a[i] : b[i] for all i in the range of [0, size()).
friend constexpr basic_simd_mask simd-select-impl(const basic_simd_mask& mask, same_as<bool> auto a, same_as<bool> auto b) noexcept;
Returns: A basic_simd_mask object where the element equals mask[i] ? a : b for all i in the range of [0, size()).
template<class T0, class T1> friend constexpr simd<see below, size()> simd-select-impl(const basic_simd_mask& mask, const T0& a, const T1& b) noexcept;
Constraints:
  • same_as<T0, T1> is true,
  • T0 is a vectorizable type, and
  • sizeof(T0) == Bytes.
Returns: A simd<T0, size()> object where the element equals mask[i] ? a : b for all i in the range of [0, size()).

29.10.9.5 basic_simd_mask reductions [simd.mask.reductions]

template<size_t Bytes, class Abi> constexpr bool all_of(const basic_simd_mask<Bytes, Abi>& k) noexcept;
Returns: true if all boolean elements in k are true, otherwise false.
template<size_t Bytes, class Abi> constexpr bool any_of(const basic_simd_mask<Bytes, Abi>& k) noexcept;
Returns: true if at least one boolean element in k is true, otherwise false.
template<size_t Bytes, class Abi> constexpr bool none_of(const basic_simd_mask<Bytes, Abi>& k) noexcept;
Returns: !any_of(k).
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_count(const basic_simd_mask<Bytes, Abi>& k) noexcept;
Returns: The number of boolean elements in k that are true.
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_min_index(const basic_simd_mask<Bytes, Abi>& k);
Preconditions: any_of(k) is true.
Returns: The lowest element index i where k[i] is true.
template<size_t Bytes, class Abi> constexpr simd-size-type reduce_max_index(const basic_simd_mask<Bytes, Abi>& k);
Preconditions: any_of(k) is true.
Returns: The greatest element index i where k[i] is true.
constexpr bool all_of(same_as<bool> auto x) noexcept; constexpr bool any_of(same_as<bool> auto x) noexcept; constexpr simd-size-type reduce_count(same_as<bool> auto x) noexcept;
Returns: x.
constexpr bool none_of(same_as<bool> auto x) noexcept;
Returns: !x.
constexpr simd-size-type reduce_min_index(same_as<bool> auto x); constexpr simd-size-type reduce_max_index(same_as<bool> auto x);
Preconditions: x is true.
Returns: 0.

29.11 C compatibility [numerics.c]

29.11.1 Header <stdckdint.h> synopsis [stdckdint.h.syn]

#define __STDC_VERSION_STDCKDINT_H__ 202311L template<class type1, class type2, class type3> bool ckd_add(type1* result, type2 a, type3 b); template<class type1, class type2, class type3> bool ckd_sub(type1* result, type2 a, type3 b); template<class type1, class type2, class type3> bool ckd_mul(type1* result, type2 a, type3 b);
See also: ISO/IEC 9899:2024, 7.20

29.11.2 Checked integer operations [numerics.c.ckdint]

template<class type1, class type2, class type3> bool ckd_add(type1* result, type2 a, type3 b); template<class type1, class type2, class type3> bool ckd_sub(type1* result, type2 a, type3 b); template<class type1, class type2, class type3> bool ckd_mul(type1* result, type2 a, type3 b);
Mandates: Each of the types type1, type2, and type3 is a cv-unqualified signed or unsigned integer type.
Remarks: Each function template has the same semantics as the corresponding type-generic macro with the same name specified in ISO/IEC 9899:2024, 7.20.

30 Time library [time]

30.1 General [time.general]

This Clause describes the chrono library ([time.syn]) and various C functions ([ctime.syn]) that provide generally useful time utilities, as summarized in Table 125.
Table 125 — Time library summary [tab:time.summary]
Subclause
Header
Cpp17Clock requirements
Time-related traits
<chrono>
Class template duration
Class template time_point
Clocks
Civil calendar
Class template hh_mm_ss
12/24 hour functions
Time zones
Formatting
Parsing
Hash support
C library time utilities
<ctime>
Let STATICALLY-WIDEN<charT>("...") be "..." if charT is char and L"..." if charT is wchar_t.

30.2 Header <chrono> synopsis [time.syn]

#include <compare> // see [compare.syn] namespace std::chrono { // [time.duration], class template duration template<class Rep, class Period = ratio<1>> class duration; // [time.point], class template time_point template<class Clock, class Duration = typename Clock::duration> class time_point; } namespace std { // [time.traits.specializations], common_type specializations template<class Rep1, class Period1, class Rep2, class Period2> struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>>; template<class Clock, class Duration1, class Duration2> struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>>; } namespace std::chrono { // [time.traits], customization traits template<class Rep> struct treat_as_floating_point; template<class Rep> constexpr bool treat_as_floating_point_v = treat_as_floating_point<Rep>::value; template<class Rep> struct duration_values; template<class T> struct is_clock; template<class T> constexpr bool is_clock_v = is_clock<T>::value; // [time.duration.nonmember], duration arithmetic template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<Rep1, Rep2> operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s); template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // [time.duration.comparisons], duration comparisons template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Rep2, class Period2> requires see below constexpr auto operator<=>(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // [time.duration.cast], conversions template<class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration floor(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d); template<class ToDuration, class Rep, class Period> constexpr ToDuration round(const duration<Rep, Period>& d); // [time.duration.io], duration I/O template<class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d); template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // convenience typedefs using nanoseconds = duration<signed integer type of at least 64 bits, nano>; using microseconds = duration<signed integer type of at least 55 bits, micro>; using milliseconds = duration<signed integer type of at least 45 bits, milli>; using seconds = duration<signed integer type of at least 35 bits>; using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; using days = duration<signed integer type of at least 25 bits, ratio_multiply<ratio<24>, hours::period>>; using weeks = duration<signed integer type of at least 22 bits, ratio_multiply<ratio<7>, days::period>>; using years = duration<signed integer type of at least 17 bits, ratio_multiply<ratio<146097, 400>, days::period>>; using months = duration<signed integer type of at least 20 bits, ratio_divide<years::period, ratio<12>>>; // [time.point.nonmember], time_point arithmetic template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template<class Rep1, class Period1, class Clock, class Duration2> constexpr time_point<Clock, common_type_t<duration<Rep1, Period1>, Duration2>> operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr common_type_t<Duration1, Duration2> operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // [time.point.comparisons], time_point comparisons template<class Clock, class Duration1, class Duration2> constexpr bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, class Duration2> constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template<class Clock, class Duration1, three_way_comparable_with<Duration1> Duration2> constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // [time.point.cast], conversions template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp); template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> round(const time_point<Clock, Duration>& tp); // [time.duration.alg], specialized algorithms template<class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d); // [time.clock.system], class system_clock class system_clock; template<class Duration> using sys_time = time_point<system_clock, Duration>; using sys_seconds = sys_time<seconds>; using sys_days = sys_time<days>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_days& dp); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.clock.utc], class utc_clock class utc_clock; template<class Duration> using utc_time = time_point<utc_clock, Duration>; using utc_seconds = utc_time<seconds>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const utc_time<Duration>& t); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); struct leap_second_info; template<class Duration> leap_second_info get_leap_second_info(const utc_time<Duration>& ut); // [time.clock.tai], class tai_clock class tai_clock; template<class Duration> using tai_time = time_point<tai_clock, Duration>; using tai_seconds = tai_time<seconds>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.clock.gps], class gps_clock class gps_clock; template<class Duration> using gps_time = time_point<gps_clock, Duration>; using gps_seconds = gps_time<seconds>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.clock.file], type file_clock using file_clock = see below; template<class Duration> using file_time = time_point<file_clock, Duration>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& tp); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.clock.steady], class steady_clock class steady_clock; // [time.clock.hires], class high_resolution_clock class high_resolution_clock; // [time.clock.local], local time struct local_t {}; template<class Duration> using local_time = time_point<local_t, Duration>; using local_seconds = local_time<seconds>; using local_days = local_time<days>; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& tp); template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.clock.cast], time_point conversions template<class DestClock, class SourceClock> struct clock_time_conversion; template<class DestClock, class SourceClock, class Duration> auto clock_cast(const time_point<SourceClock, Duration>& t); // [time.cal.last], class last_spec struct last_spec; // [time.cal.day], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.month], class 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; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month& m); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.year], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year& y); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.wd], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.wdidx], class weekday_indexed class weekday_indexed; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi); // [time.cal.wdlast], class weekday_last class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl); // [time.cal.md], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day& md); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.mdlast], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl); // [time.cal.mwd], class month_weekday class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd); // [time.cal.mwdlast], class month_weekday_last class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl); // [time.cal.ym], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month& ym); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.ymd], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd); template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // [time.cal.ymdlast], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl); // [time.cal.ymwd], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwd); // [time.cal.ymwdlast], class 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<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl); // [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; // [time.hms], class template hh_mm_ss template<class Duration> class hh_mm_ss; template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const hh_mm_ss<Duration>& hms); // [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; // [time.zone.db], time zone database struct tzdb; class tzdb_list; // [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(); // [time.zone.db.remote], remote time zone database support const tzdb& reload_tzdb(); string remote_version(); // [time.zone.exception], exception classes class nonexistent_local_time; class ambiguous_local_time; // [time.zone.info], information classes struct sys_info; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_info& si); struct local_info; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_info& li); // [time.zone.timezone], class 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; // [time.zone.zonedtraits], class template zoned_traits template<class T> struct zoned_traits; // [time.zone.zonedtime], class template zoned_time template<class Duration, class TimeZonePtr = const time_zone*> class zoned_time; using zoned_seconds = zoned_time<seconds>; template<class Duration1, class Duration2, class TimeZonePtr> bool operator==(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y); template<class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const zoned_time<Duration, TimeZonePtr>& t); // [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<class Duration> constexpr bool operator==(const leap_second& x, const sys_time<Duration>& y); template<class Duration> constexpr bool operator< (const leap_second& x, const sys_time<Duration>& y); template<class Duration> constexpr bool operator< (const sys_time<Duration>& x, const leap_second& y); template<class Duration> constexpr bool operator> (const leap_second& x, const sys_time<Duration>& y); template<class Duration> constexpr bool operator> (const sys_time<Duration>& x, const leap_second& y); template<class Duration> constexpr bool operator<=(const leap_second& x, const sys_time<Duration>& y); template<class Duration> constexpr bool operator<=(const sys_time<Duration>& x, const leap_second& y); template<class Duration> constexpr bool operator>=(const leap_second& x, const sys_time<Duration>& y); template<class Duration> constexpr bool operator>=(const sys_time<Duration>& x, const leap_second& y); template<class Duration> requires three_way_comparable_with<sys_seconds, sys_time<Duration>> constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y); // [time.zone.link], class 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); // [time.format], formatting template<class Duration> struct local-time-format-t; // exposition only template<class Duration> local-time-format-t<Duration> local_time_format(local_time<Duration> time, const string* abbrev = nullptr, const seconds* offset_sec = nullptr); } namespace std { template<class Rep, class Period, class charT> struct formatter<chrono::duration<Rep, Period>, charT>; template<class Duration, class charT> struct formatter<chrono::sys_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::utc_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::tai_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::gps_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::file_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::local_time<Duration>, charT>; template<class Duration, class charT> struct formatter<chrono::local-time-format-t<Duration>, charT>; template<class charT> struct formatter<chrono::day, charT>; template<class charT> struct formatter<chrono::month, charT>; template<class charT> struct formatter<chrono::year, charT>; template<class charT> struct formatter<chrono::weekday, charT>; template<class charT> struct formatter<chrono::weekday_indexed, charT>; template<class charT> struct formatter<chrono::weekday_last, charT>; template<class charT> struct formatter<chrono::month_day, charT>; template<class charT> struct formatter<chrono::month_day_last, charT>; template<class charT> struct formatter<chrono::month_weekday, charT>; template<class charT> struct formatter<chrono::month_weekday_last, charT>; template<class charT> struct formatter<chrono::year_month, charT>; template<class charT> struct formatter<chrono::year_month_day, charT>; template<class charT> struct formatter<chrono::year_month_day_last, charT>; template<class charT> struct formatter<chrono::year_month_weekday, charT>; template<class charT> struct formatter<chrono::year_month_weekday_last, charT>; template<class Rep, class Period, class charT> struct formatter<chrono::hh_mm_ss<duration<Rep, Period>>, charT>; template<class charT> struct formatter<chrono::sys_info, charT>; template<class charT> struct formatter<chrono::local_info, charT>; template<class Duration, class TimeZonePtr, class charT> struct formatter<chrono::zoned_time<Duration, TimeZonePtr>, charT>; } namespace std::chrono { // [time.parse], parsing template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& 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::inline literals::inline chrono_literals { // [time.duration.literals], suffixes for duration literals constexpr chrono::hours operator""h(unsigned long long); constexpr chrono::duration<unspecified, ratio<3600, 1>> operator""h(long double); constexpr chrono::minutes operator""min(unsigned long long); constexpr chrono::duration<unspecified, ratio<60, 1>> operator""min(long double); constexpr chrono::seconds operator""s(unsigned long long); constexpr chrono::duration<unspecified> operator""s(long double); constexpr chrono::milliseconds operator""ms(unsigned long long); constexpr chrono::duration<unspecified, milli> operator""ms(long double); constexpr chrono::microseconds operator""us(unsigned long long); constexpr chrono::duration<unspecified, micro> operator""us(long double); constexpr chrono::nanoseconds operator""ns(unsigned long long); constexpr chrono::duration<unspecified, nano> operator""ns(long double); // [time.cal.day.nonmembers], non-member functions constexpr chrono::day operator""d(unsigned long long d) noexcept; // [time.cal.year.nonmembers], non-member functions constexpr chrono::year operator""y(unsigned long long y) noexcept; } namespace std::chrono { using namespace literals::chrono_literals; } namespace std { // [time.hash], hash support template<class T> struct hash; template<class Rep, class Period> struct hash<chrono::duration<Rep, Period>>; template<class Clock, class Duration> struct hash<chrono::time_point<Clock, Duration>>; template<> struct hash<chrono::day>; template<> struct hash<chrono::month>; template<> struct hash<chrono::year>; template<> struct hash<chrono::weekday>; template<> struct hash<chrono::weekday_indexed>; template<> struct hash<chrono::weekday_last>; template<> struct hash<chrono::month_day>; template<> struct hash<chrono::month_day_last>; template<> struct hash<chrono::month_weekday>; template<> struct hash<chrono::month_weekday_last>; template<> struct hash<chrono::year_month>; template<> struct hash<chrono::year_month_day>; template<> struct hash<chrono::year_month_day_last>; template<> struct hash<chrono::year_month_weekday>; template<> struct hash<chrono::year_month_weekday_last>; template<class Duration, class TimeZonePtr> struct hash<chrono::zoned_time<Duration, TimeZonePtr>>; template<> struct hash<chrono::leap_second>; }

30.3 Cpp17Clock requirements [time.clock.req]

A clock is a bundle consisting of a duration, a time_point, and a function now() to get the current time_point.
The origin of the clock's time_point is referred to as the clock's epoch.
A clock shall meet the requirements in Table 126.
In Table 126 C1 and C2 denote clock types.
t1 and t2 are values returned by C1​::​now() where the call returning t1 happens before ([intro.multithread]) the call returning t2 and both of these calls occur before C1​::​time_point​::​max().
[Note 1: 
This means C1 did not wrap around between t1 and t2.
— end note]
Table 126Cpp17Clock requirements [tab:time.clock]
Expression
Return type
Operational semantics
C1​::​rep
An arithmetic type or a class emulating an arithmetic type
The representation type of C1​::​duration.
C1​::​period
a specialization of ratio
The tick period of the clock in seconds.
C1​::​duration
chrono​::​duration<C1​::​rep, C1​::​period>
The duration type of the clock.
C1​::​time_point
chrono​::​time_point<C1> or chrono​::​time_point<C2, C1​::​duration>
The time_point type of the clock.
C1 and C2 shall refer to the same epoch.
C1​::​is_steady
const bool
true if t1 <= t2 is always true and the time between clock ticks is constant, otherwise false.
C1​::​now()
C1​::​time_point
Returns a time_point object representing the current point in time.
[Note 2: 
The relative difference in durations between those reported by a given clock and the SI definition is a measure of the quality of implementation.
— end note]
A type TC meets the Cpp17TrivialClock requirements if

30.4 Time-related traits [time.traits]

30.4.1 treat_as_floating_point [time.traits.is.fp]

template<class Rep> struct treat_as_floating_point : is_floating_point<Rep> { };
The duration template uses the treat_as_floating_point trait to help determine if a duration object can be converted to another duration with a different tick period.
If treat_as_floating_point_v<Rep> is true, then implicit conversions are allowed among durations.
Otherwise, the implicit convertibility depends on the tick periods of the durations.
[Note 1: 
The intention of this trait is to indicate whether a given class behaves like a floating-point type, and thus allows division of one value by another with acceptable loss of precision.
If treat_as_floating_point_v<Rep> is false, Rep will be treated as if it behaved like an integral type for the purpose of these conversions.
— end note]

30.4.2 duration_values [time.traits.duration.values]

template<class Rep> struct duration_values { public: static constexpr Rep zero() noexcept; static constexpr Rep min() noexcept; static constexpr Rep max() noexcept; };
The duration template uses the duration_values trait to construct special values of the duration's representation (Rep).
This is done because the representation can be a class type with behavior that requires some other implementation to return these special values.
In that case, the author of that class type should specialize duration_values to return the indicated values.
static constexpr Rep zero() noexcept;
Returns: Rep(0).
[Note 1: 
Rep(0) is specified instead of Rep() because Rep() can have some other meaning, such as an uninitialized value.
— end note]
Remarks: The value returned shall be the additive identity.
static constexpr Rep min() noexcept;
Returns: numeric_limits<Rep>​::​lowest().
Remarks: The value returned shall compare less than or equal to zero().
static constexpr Rep max() noexcept;
Returns: numeric_limits<Rep>​::​max().
Remarks: The value returned shall compare greater than zero().

30.4.3 Specializations of common_type [time.traits.specializations]

template<class Rep1, class Period1, class Rep2, class Period2> struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> { using type = chrono::duration<common_type_t<Rep1, Rep2>, see below>; };
The period of the duration indicated by this specialization of common_type is the greatest common divisor of Period1 and Period2.
[Note 1: 
This can be computed by forming a ratio of the greatest common divisor of Period1​::​num and Period2​::​num and the least common multiple of Period1​::​den and Period2​::​den.
— end note]
[Note 2: 
The typedef name type is a synonym for the duration with the largest tick period possible where both duration arguments will convert to it without requiring a division operation.
The representation of this type is intended to be able to hold any value resulting from this conversion with no truncation error, although floating-point durations can have round-off errors.
— end note]
template<class Clock, class Duration1, class Duration2> struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>> { using type = chrono::time_point<Clock, common_type_t<Duration1, Duration2>>; };
The common type of two time_point types is a time_point with the same clock as the two types and the common type of their two durations.

30.4.4 Class template is_clock [time.traits.is.clock]

template<class T> struct is_clock;
is_clock is a Cpp17UnaryTypeTrait ([meta.rqmts]) with a base characteristic of true_type if T meets the Cpp17Clock requirements ([time.clock.req]), otherwise false_type.
For the purposes of the specification of this trait, the extent to which an implementation determines that a type cannot meet the Cpp17Clock requirements is unspecified, except that as a minimum a type T shall not qualify as a Cpp17Clock unless it meets all of the following conditions:
  • the qualified-ids T​::​rep, T​::​period, T​::​duration, and T​::​time_point are valid and each denotes a type ([temp.deduct]),
  • the expression T​::​is_steady is well-formed when treated as an unevaluated operand,
  • the expression T​::​now() is well-formed when treated as an unevaluated operand.
The behavior of a program that adds specializations for is_clock is undefined.

30.5 Class template duration [time.duration]

30.5.1 General [time.duration.general]

A duration type measures time between two points in time (time_points).
A duration has a representation which holds a count of ticks and a tick period.
The tick period is the amount of time which occurs from one tick to the next, in units of seconds.
It is expressed as a rational constant using the template ratio.
namespace std::chrono { template<class Rep, class Period = ratio<1>> class duration { public: using rep = Rep; using period = typename Period::type; private: rep rep_; // exposition only public: // [time.duration.cons], construct/copy/destroy constexpr duration() = default; template<class Rep2> constexpr explicit duration(const Rep2& r); template<class Rep2, class Period2> constexpr duration(const duration<Rep2, Period2>& d); ~duration() = default; duration(const duration&) = default; duration& operator=(const duration&) = default; // [time.duration.observer], observer constexpr rep count() const; // [time.duration.arithmetic], arithmetic constexpr common_type_t<duration> operator+() const; constexpr common_type_t<duration> operator-() const; constexpr duration& operator++(); constexpr duration operator++(int); constexpr duration& operator--(); constexpr duration operator--(int); constexpr duration& operator+=(const duration& d); constexpr duration& operator-=(const duration& d); constexpr duration& operator*=(const rep& rhs); constexpr duration& operator/=(const rep& rhs); constexpr duration& operator%=(const rep& rhs); constexpr duration& operator%=(const duration& rhs); // [time.duration.special], special values static constexpr duration zero() noexcept; static constexpr duration min() noexcept; static constexpr duration max() noexcept; }; }
Rep shall be an arithmetic type or a class emulating an arithmetic type.
If duration is instantiated with a duration type as the argument for the template parameter Rep, the program is ill-formed.
If Period is not a specialization of ratio, the program is ill-formed.
If Period​::​num is not positive, the program is ill-formed.
Members of duration do not throw exceptions other than those thrown by the indicated operations on their representations.
The defaulted copy constructor of duration shall be a constexpr function if and only if the required initialization of the member rep_ for copy and move, respectively, would be constexpr-suitable ([dcl.constexpr]).
[Example 1: duration<long, ratio<60>> d0; // holds a count of minutes using a long duration<long long, milli> d1; // holds a count of milliseconds using a long long duration<double, ratio<1, 30>> d2; // holds a count with a tick period of of a second // (30 Hz) using a double — end example]

30.5.2 Constructors [time.duration.cons]

template<class Rep2> constexpr explicit duration(const Rep2& r);
Constraints: is_convertible_v<const Rep2&, rep> is true and
  • treat_as_floating_point_v<rep> is true or
  • treat_as_floating_point_v<Rep2> is false.
[Example 1: duration<int, milli> d(3); // OK duration<int, milli> d2(3.5); // error — end example]
Effects: Initializes rep_ with r.
template<class Rep2, class Period2> constexpr duration(const duration<Rep2, Period2>& d);
Constraints: No overflow is induced in the conversion and treat_as_floating_point_v<rep> is true or both ratio_divide<Period2, period>​::​den is 1 and treat_as_floating_point_v<Rep2> is false.
[Note 1: 
This requirement prevents implicit truncation error when converting between integral-based duration types.
Such a construction could easily lead to confusion about the value of the duration.
— end note]
[Example 2: duration<int, milli> ms(3); duration<int, micro> us = ms; // OK duration<int, milli> ms2 = us; // error — end example]
Effects: Initializes rep_ with duration_cast<duration>(d).count().

30.5.3 Observer [time.duration.observer]

constexpr rep count() const;
Returns: rep_.

30.5.4 Arithmetic [time.duration.arithmetic]

constexpr common_type_t<duration> operator+() const;
Returns: common_type_t<duration>(*this).
constexpr common_type_t<duration> operator-() const;
Returns: common_type_t<duration>(-rep_).
constexpr duration& operator++();
Effects: Equivalent to: ++rep_.
Returns: *this.
constexpr duration operator++(int);
Effects: Equivalent to: return duration(rep_++);
constexpr duration& operator--();
Effects: Equivalent to: --rep_.
Returns: *this.
constexpr duration operator--(int);
Effects: Equivalent to: return duration(rep_--);
constexpr duration& operator+=(const duration& d);
Effects: Equivalent to: rep_ += d.count().
Returns: *this.
constexpr duration& operator-=(const duration& d);
Effects: Equivalent to: rep_ -= d.count().
Returns: *this.
constexpr duration& operator*=(const rep& rhs);
Effects: Equivalent to: rep_ *= rhs.
Returns: *this.
constexpr duration& operator/=(const rep& rhs);
Effects: Equivalent to: rep_ /= rhs.
Returns: *this.
constexpr duration& operator%=(const rep& rhs);
Effects: Equivalent to: rep_ %= rhs.
Returns: *this.
constexpr duration& operator%=(const duration& rhs);
Effects: Equivalent to: rep_ %= rhs.count().
Returns: *this.

30.5.5 Special values [time.duration.special]

static constexpr duration zero() noexcept;
Returns: duration(duration_values<rep>​::​zero()).
static constexpr duration min() noexcept;
Returns: duration(duration_values<rep>​::​min()).
static constexpr duration max() noexcept;
Returns: duration(duration_values<rep>​::​max()).

30.5.6 Non-member arithmetic [time.duration.nonmember]

In the function descriptions that follow, unless stated otherwise, let CD represent the return type of the function.
template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CD(CD(lhs).count() + CD(rhs).count()).
template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CD(CD(lhs).count() - CD(rhs).count()).
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const duration<Rep1, Period>& d, const Rep2& s);
Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true.
Returns: CD(CD(d).count() * s).
template<class Rep1, class Rep2, class Period> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator*(const Rep1& s, const duration<Rep2, Period>& d);
Constraints: is_convertible_v<const Rep1&, common_type_t<Rep1, Rep2>> is true.
Returns: d * s.
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator/(const duration<Rep1, Period>& d, const Rep2& s);
Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true and Rep2 is not a specialization of duration.
Returns: CD(CD(d).count() / s).
template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<Rep1, Rep2> operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Let CD be common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>.
Returns: CD(lhs).count() / CD(rhs).count().
template<class Rep1, class Period, class Rep2> constexpr duration<common_type_t<Rep1, Rep2>, Period> operator%(const duration<Rep1, Period>& d, const Rep2& s);
Constraints: is_convertible_v<const Rep2&, common_type_t<Rep1, Rep2>> is true and Rep2 is not a specialization of duration.
Returns: CD(CD(d).count() % s).
template<class Rep1, class Period1, class Rep2, class Period2> constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CD(CD(lhs).count() % CD(rhs).count()).

30.5.7 Comparisons [time.duration.comparisons]

In the function descriptions that follow, CT represents common_type_t<A, B>, where A and B are the types of the two arguments to the function.
template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CT(lhs).count() == CT(rhs).count().
template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CT(lhs).count() < CT(rhs).count().
template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: rhs < lhs.
template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: !(rhs < lhs).
template<class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: !(lhs < rhs).
template<class Rep1, class Period1, class Rep2, class Period2> requires three_way_comparable<typename CT::rep> constexpr auto operator<=>(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CT(lhs).count() <=> CT(rhs).count().

30.5.8 Conversions [time.duration.cast]

template<class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Constraints: ToDuration is a specialization of duration.
Returns: Let CF be ratio_divide<Period, typename ToDuration​::​period>, and CR be common_type<typename ToDuration​::​rep, Rep, intmax_t>​::​type.
  • If CF​::​num == 1 and CF​::​den == 1, returns ToDuration(static_cast<typename ToDuration::rep>(d.count()))
  • otherwise, if CF​::​num != 1 and CF​::​den == 1, returns ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) * static_cast<CR>(CF::num)))
  • otherwise, if CF​::​num == 1 and CF​::​den != 1, returns ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) / static_cast<CR>(CF::den)))
  • otherwise, returns ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) * static_cast<CR>(CF::num) / static_cast<CR>(CF::den)))
[Note 1: 
This function does not use any implicit conversions; all conversions are done with static_cast.
It avoids multiplications and divisions when it is known at compile time that one or more arguments is 1.
Intermediate computations are carried out in the widest representation and only converted to the destination representation at the final step.
— end note]
template<class ToDuration, class Rep, class Period> constexpr ToDuration floor(const duration<Rep, Period>& d);
Constraints: ToDuration is a specialization of duration.
Returns: The greatest result t representable in ToDuration for which t <= d.
template<class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d);
Constraints: ToDuration is a specialization of duration.
Returns: The least result t representable in ToDuration for which t >= d.
template<class ToDuration, class Rep, class Period> constexpr ToDuration round(const duration<Rep, Period>& d);
Constraints: ToDuration is a specialization of duration and treat_as_floating_point_v<typename ToDuration​::​rep> is false.
Returns: The value of ToDuration that is closest to d.
If there are two closest values, then return the value t for which t % 2 == 0.

30.5.9 Suffixes for duration literals [time.duration.literals]

This subclause describes literal suffixes for constructing duration literals.
The suffixes h, min, s, ms, us, ns denote duration values of the corresponding types hours, minutes, seconds, milliseconds, microseconds, and nanoseconds respectively if they are applied to integer-literals.
If any of these suffixes are applied to a floating-point-literal the result is a chrono​::​duration literal with an unspecified floating-point representation.
If any of these suffixes are applied to an integer-literal and the resulting chrono​::​duration value cannot be represented in the result type because of overflow, the program is ill-formed.
[Example 1: 
The following code shows some duration literals.
using namespace std::chrono_literals; auto constexpr aday=24h; auto constexpr lesson=45min; auto constexpr halfanhour=0.5h; — end example]
constexpr chrono::hours operator""h(unsigned long long hours); constexpr chrono::duration<unspecified, ratio<3600, 1>> operator""h(long double hours);
Returns: A duration literal representing hours hours.
constexpr chrono::minutes operator""min(unsigned long long minutes); constexpr chrono::duration<unspecified, ratio<60, 1>> operator""min(long double minutes);
Returns: A duration literal representing minutes minutes.
constexpr chrono::seconds operator""s(unsigned long long sec); constexpr chrono::duration<unspecified> operator""s(long double sec);
Returns: A duration literal representing sec seconds.
[Note 1: 
The same suffix s is used for basic_string but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals.
— end note]
constexpr chrono::milliseconds operator""ms(unsigned long long msec); constexpr chrono::duration<unspecified, milli> operator""ms(long double msec);
Returns: A duration literal representing msec milliseconds.
constexpr chrono::microseconds operator""us(unsigned long long usec); constexpr chrono::duration<unspecified, micro> operator""us(long double usec);
Returns: A duration literal representing usec microseconds.
constexpr chrono::nanoseconds operator""ns(unsigned long long nsec); constexpr chrono::duration<unspecified, nano> operator""ns(long double nsec);
Returns: A duration literal representing nsec nanoseconds.

30.5.10 Algorithms [time.duration.alg]

template<class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d);
Constraints: numeric_limits<Rep>​::​is_signed is true.
Returns: If d >= d.zero(), return d, otherwise return -d.

30.5.11 I/O [time.duration.io]

template<class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d);
Effects: Inserts the duration d onto the stream os as if it were implemented as follows: basic_ostringstream<charT, traits> s; s.flags(os.flags()); s.imbue(os.getloc()); s.precision(os.precision()); s << d.count() << units-suffix; return os << s.str(); where units-suffix depends on the type Period​::​type as follows:
  • If Period​::​type is atto, units-suffix is "as".
  • Otherwise, if Period​::​type is femto, units-suffix is "fs".
  • Otherwise, if Period​::​type is pico, units-suffix is "ps".
  • Otherwise, if Period​::​type is nano, units-suffix is "ns".
  • Otherwise, if Period​::​type is micro, it is implementation-defined whether units-suffix is "μs" ("\u00b5\u0073") or "us".
  • Otherwise, if Period​::​type is milli, units-suffix is "ms".
  • Otherwise, if Period​::​type is centi, units-suffix is "cs".
  • Otherwise, if Period​::​type is deci, units-suffix is "ds".
  • Otherwise, if Period​::​type is ratio<1>, units-suffix is "s".
  • Otherwise, if Period​::​type is deca, units-suffix is "das".
  • Otherwise, if Period​::​type is hecto, units-suffix is "hs".
  • Otherwise, if Period​::​type is kilo, units-suffix is "ks".
  • Otherwise, if Period​::​type is mega, units-suffix is "Ms".
  • Otherwise, if Period​::​type is giga, units-suffix is "Gs".
  • Otherwise, if Period​::​type is tera, units-suffix is "Ts".
  • Otherwise, if Period​::​type is peta, units-suffix is "Ps".
  • Otherwise, if Period​::​type is exa, units-suffix is "Es".
  • Otherwise, if Period​::​type is ratio<60>, units-suffix is "min".
  • Otherwise, if Period​::​type is ratio<3600>, units-suffix is "h".
  • Otherwise, if Period​::​type is ratio<86400>, units-suffix is "d".
  • Otherwise, if Period​::​type​::​den == 1, units-suffix is "[num]s".
  • Otherwise, units-suffix is "[num/den]s".
In the list above, the use of num and den refers to the static data members of Period​::​type, which are converted to arrays of charT using a decimal conversion with no leading zeroes.
Returns: os.
template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the duration d using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid duration, is.setstate(ios_base​::​failbit) is called and d is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.6 Class template time_point [time.point]

30.6.1 General [time.point.general]

namespace std::chrono { template<class Clock, class Duration = typename Clock::duration> class time_point { public: using clock = Clock; using duration = Duration; using rep = typename duration::rep; using period = typename duration::period; private: duration d_; // exposition only public: // [time.point.cons], construct constexpr time_point(); // has value epoch constexpr explicit time_point(const duration& d); // same as time_point() + d template<class Duration2> constexpr time_point(const time_point<clock, Duration2>& t); // [time.point.observer], observer constexpr duration time_since_epoch() const; // [time.point.arithmetic], arithmetic constexpr time_point& operator++(); constexpr time_point operator++(int); constexpr time_point& operator--(); constexpr time_point operator--(int); constexpr time_point& operator+=(const duration& d); constexpr time_point& operator-=(const duration& d); // [time.point.special], special values static constexpr time_point min() noexcept; static constexpr time_point max() noexcept; }; }
If Duration is not a specialization of duration, the program is ill-formed.

30.6.2 Constructors [time.point.cons]

constexpr time_point();
Effects: Initializes d_ with duration​::​zero().
Such a time_point object represents the epoch.
constexpr explicit time_point(const duration& d);
Effects: Initializes d_ with d.
Such a time_point object represents the epoch + d.
template<class Duration2> constexpr time_point(const time_point<clock, Duration2>& t);
Constraints: is_convertible_v<Duration2, duration> is true.
Effects: Initializes d_ with t.time_since_epoch().

30.6.3 Observer [time.point.observer]

constexpr duration time_since_epoch() const;
Returns: d_.

30.6.4 Arithmetic [time.point.arithmetic]

constexpr time_point& operator++();
Effects: Equivalent to: ++d_.
Returns: *this.
constexpr time_point operator++(int);
Effects: Equivalent to: return time_point{d_++};
constexpr time_point& operator--();
Effects: Equivalent to: --d_.
Returns: *this.
constexpr time_point operator--(int);
Effects: Equivalent to: return time_point{d_--};
constexpr time_point& operator+=(const duration& d);
Effects: Equivalent to: d_ += d.
Returns: *this.
constexpr time_point& operator-=(const duration& d);
Effects: Equivalent to: d_ -= d.
Returns: *this.

30.6.5 Special values [time.point.special]

static constexpr time_point min() noexcept;
Returns: time_point(duration​::​min()).
static constexpr time_point max() noexcept;
Returns: time_point(duration​::​max()).

30.6.6 Non-member arithmetic [time.point.nonmember]

template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CT(lhs.time_since_epoch() + rhs), where CT is the type of the return value.
template<class Rep1, class Period1, class Clock, class Duration2> constexpr time_point<Clock, common_type_t<duration<Rep1, Period1>, Duration2>> operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: rhs + lhs.
template<class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
Returns: CT(lhs.time_since_epoch() - rhs), where CT is the type of the return value.
template<class Clock, class Duration1, class Duration2> constexpr common_type_t<Duration1, Duration2> operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: lhs.time_since_epoch() - rhs.time_since_epoch().

30.6.7 Comparisons [time.point.comparisons]

template<class Clock, class Duration1, class Duration2> constexpr bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: lhs.time_since_epoch() == rhs.time_since_epoch().
template<class Clock, class Duration1, class Duration2> constexpr bool operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: lhs.time_since_epoch() < rhs.time_since_epoch().
template<class Clock, class Duration1, class Duration2> constexpr bool operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: rhs < lhs.
template<class Clock, class Duration1, class Duration2> constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: !(rhs < lhs).
template<class Clock, class Duration1, class Duration2> constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: !(lhs < rhs).
template<class Clock, class Duration1, three_way_comparable_with<Duration1> Duration2> constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
Returns: lhs.time_since_epoch() <=> rhs.time_since_epoch().

30.6.8 Conversions [time.point.cast]

template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t);
Constraints: ToDuration is a specialization of duration.
Returns: time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch()))
template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp);
Constraints: ToDuration is a specialization of duration.
Returns: time_point<Clock, ToDuration>(floor<ToDuration>(tp.time_since_epoch())).
template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp);
Constraints: ToDuration is a specialization of duration.
Returns: time_point<Clock, ToDuration>(ceil<ToDuration>(tp.time_since_epoch())).
template<class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> round(const time_point<Clock, Duration>& tp);
Constraints: ToDuration is a specialization of duration, and treat_as_floating_point_v<typename ToDuration​::​rep> is false.
Returns: time_point<Clock, ToDuration>(round<ToDuration>(tp.time_since_epoch())).

30.7 Clocks [time.clock]

30.7.1 General [time.clock.general]

The types defined in [time.clock] meet the Cpp17TrivialClock requirements ([time.clock.req]) unless otherwise specified.

30.7.2 Class system_clock [time.clock.system]

30.7.2.1 Overview [time.clock.system.overview]

namespace std::chrono { class system_clock { public: using rep = see below; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<system_clock>; static constexpr bool is_steady = unspecified; static time_point now() noexcept; // mapping to/from C type time_t static time_t to_time_t (const time_point& t) noexcept; static time_point from_time_t(time_t t) noexcept; }; }
Objects of type system_clock represent wall clock time from the system-wide realtime clock.
Objects of type sys_time<Duration> measure time since 1970-01-01 00:00:00 UTC excluding leap seconds.
This measure is commonly referred to as Unix time.
This measure facilitates an efficient mapping between sys_time and calendar types ([time.cal]).
[Example 1: 
sys_seconds{sys_days{1970y/January/1}}.time_since_epoch() is 0s.

sys_seconds{sys_days{2000y/January/1}}.time_since_epoch() is 946'684'800s, which is 10'957 * 86'400s.

— end example]

30.7.2.2 Members [time.clock.system.members]

using system_clock::rep = unspecified;
Constraints: system_clock​::​duration​::​min() < system_clock​::​duration​::​zero() is true.
[Note 1: 
This implies that rep is a signed type.
— end note]
static time_t to_time_t(const time_point& t) noexcept;
Returns: A time_t object that represents the same point in time as t when both values are restricted to the coarser of the precisions of time_t and time_point.
It is implementation-defined whether values are rounded or truncated to the required precision.
static time_point from_time_t(time_t t) noexcept;
Returns: A time_point object that represents the same point in time as t when both values are restricted to the coarser of the precisions of time_t and time_point.
It is implementation-defined whether values are rounded or truncated to the required precision.

30.7.2.3 Non-member functions [time.clock.system.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);
Constraints: treat_as_floating_point_v<typename Duration​::​rep> is false, and Duration{1} < days{1} is true.
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T}"), tp);
[Example 1: cout << sys_seconds{0s} << '\n'; // 1970-01-01 00:00:00 cout << sys_seconds{946'684'800s} << '\n'; // 2000-01-01 00:00:00 cout << sys_seconds{946'688'523s} << '\n'; // 2000-01-01 01:02:03 — end example]
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);
Effects: os << year_month_day{dp}.
Returns: os.
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the sys_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Additionally, the parsed offset will be subtracted from the successfully parsed timestamp prior to assigning that difference to tp.
Returns: is.

30.7.3 Class utc_clock [time.clock.utc]

30.7.3.1 Overview [time.clock.utc.overview]

namespace std::chrono { class utc_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<utc_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template<class Duration> static sys_time<common_type_t<Duration, seconds>> to_sys(const utc_time<Duration>& t); template<class Duration> static utc_time<common_type_t<Duration, seconds>> from_sys(const sys_time<Duration>& t); }; }
In contrast to sys_time, which does not take leap seconds into account, utc_clock and its associated time_point, utc_time, count time, including leap seconds, since 1970-01-01 00:00:00 UTC.
[Note 1: 
The UTC time standard began on 1972-01-01 00:00:10 TAI. To measure time since this epoch instead, one can add/subtract the constant sys_days{1972y/1/1} - sys_days{1970y/1/1} (63'072'000s) from the utc_time.
— end note]
[Example 1: 
clock_cast<utc_clock>(sys_seconds{sys_days{1970y/January/1}}).time_since_epoch() is 0s.

clock_cast<utc_clock>(sys_seconds{sys_days{2000y/January/1}}).time_since_epoch() is 946'684'822s,
which is 10'957 * 86'400s + 22s.

— end example]
utc_clock is not a Cpp17TrivialClock unless the implementation can guarantee that utc_clock​::​now() does not propagate an exception.
[Note 2: 
noexcept(from_sys(system_clock​::​now())) is false.
— end note]

30.7.3.2 Member functions [time.clock.utc.members]

static time_point now();
Returns: from_sys(system_clock​::​now()), or a more accurate value of utc_time.
template<class Duration> static sys_time<common_type_t<Duration, seconds>> to_sys(const utc_time<Duration>& u);
Returns: A sys_time t, such that from_sys(t) == u if such a mapping exists.
Otherwise u represents a time_point during a positive leap second insertion, the conversion counts that leap second as not inserted, and the last representable value of sys_time prior to the insertion of the leap second is returned.
template<class Duration> static utc_time<common_type_t<Duration, seconds>> from_sys(const sys_time<Duration>& t);
Returns: A utc_time u, such that u.time_since_epoch() - t.time_since_epoch() is equal to the sum of leap seconds that were inserted between t and 1970-01-01.
If t is exactly the date of leap second insertion, then the conversion counts that leap second as inserted.
[Example 1: auto t = sys_days{July/1/2015} - 2ns; auto u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 25s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 25s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 26s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 26s); — end example]

30.7.3.3 Non-member functions [time.clock.utc.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const utc_time<Duration>& t);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T}"), t);
[Example 1: auto t = sys_days{July/1/2015} - 500ms; auto u = clock_cast<utc_clock>(t); for (auto i = 0; i < 8; ++i, u += 250ms) cout << u << " UTC\n";
Produces this output:
2015-06-30 23:59:59.500 UTC
2015-06-30 23:59:59.750 UTC
2015-06-30 23:59:60.000 UTC
2015-06-30 23:59:60.250 UTC
2015-06-30 23:59:60.500 UTC
2015-06-30 23:59:60.750 UTC
2015-07-01 00:00:00.000 UTC
2015-07-01 00:00:00.250 UTC
— end example]
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the utc_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Additionally, the parsed offset will be subtracted from the successfully parsed timestamp prior to assigning that difference to tp.
Returns: is.
struct leap_second_info { bool is_leap_second; seconds elapsed; };
The type leap_second_info has data members and special members specified above.
It has no base classes or members other than those specified.
template<class Duration> leap_second_info get_leap_second_info(const utc_time<Duration>& ut);
Returns: A leap_second_info lsi, where lsi.is_leap_second is true if ut is during a positive leap second insertion, and otherwise false.
lsi.elapsed is the sum of leap seconds between 1970-01-01 and ut.
If lsi.is_leap_second is true, the leap second referred to by ut is included in the sum.

30.7.4 Class tai_clock [time.clock.tai]

30.7.4.1 Overview [time.clock.tai.overview]

namespace std::chrono { class tai_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<tai_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template<class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const tai_time<Duration>&) noexcept; template<class Duration> static tai_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>&) noexcept; }; }
The clock tai_clock measures seconds since 1958-01-01 00:00:00 and is offset 10s ahead of UTC at this date.
That is, 1958-01-01 00:00:00 TAI is equivalent to 1957-12-31 23:59:50 UTC.
Leap seconds are not inserted into TAI.
Therefore every time a leap second is inserted into UTC, UTC shifts another second with respect to TAI.
For example by 2000-01-01 there had been 22 positive and 0 negative leap seconds inserted so 2000-01-01 00:00:00 UTC is equivalent to 2000-01-01 00:00:32 TAI (22s plus the initial 10s offset).
tai_clock is not a Cpp17TrivialClock unless the implementation can guarantee that tai_clock​::​now() does not propagate an exception.
[Note 1: 
noexcept(from_utc(utc_clock​::​now())) is false.
— end note]

30.7.4.2 Member functions [time.clock.tai.members]

static time_point now();
Returns: from_utc(utc_clock​::​now()), or a more accurate value of tai_time.
template<class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const tai_time<Duration>& t) noexcept;
Returns: utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 378691210s
[Note 1: 378691210s == sys_days{1970y/January/1} - sys_days{1958y/January/1} + 10s — end note]
template<class Duration> static tai_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>& t) noexcept;
Returns: tai_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 378691210s
[Note 2: 378691210s == sys_days{1970y/January/1} - sys_days{1958y/January/1} + 10s — end note]

30.7.4.3 Non-member functions [time.clock.tai.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T}"), t);
[Example 1: auto st = sys_days{2000y/January/1}; auto tt = clock_cast<tai_clock>(st); cout << format("{0:%F %T %Z} == {1:%F %T %Z}\n", st, tt);
Produces this output:
2000-01-01 00:00:00 UTC == 2000-01-01 00:00:32 TAI
— end example]
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the tai_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Additionally, the parsed offset will be subtracted from the successfully parsed timestamp prior to assigning that difference to tp.
Returns: is.

30.7.5 Class gps_clock [time.clock.gps]

30.7.5.1 Overview [time.clock.gps.overview]

namespace std::chrono { class gps_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<gps_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template<class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const gps_time<Duration>&) noexcept; template<class Duration> static gps_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>&) noexcept; }; }
The clock gps_clock measures seconds since the first Sunday of January, 1980 00:00:00 UTC.
Leap seconds are not inserted into GPS.
Therefore every time a leap second is inserted into UTC, UTC shifts another second with respect to GPS.
Aside from the offset from 1958y/January/1 to 1980y/January/Sunday[1], GPS is behind TAI by 19s due to the 10s offset between 1958 and 1970 and the additional 9 leap seconds inserted between 1970 and 1980.
gps_clock is not a Cpp17TrivialClock unless the implementation can guarantee that gps_clock​::​now() does not propagate an exception.
[Note 1: 
noexcept(from_utc(utc_clock​::​now())) is false.
— end note]

30.7.5.2 Member functions [time.clock.gps.members]

static time_point now();
Returns: from_utc(utc_clock​::​now()), or a more accurate value of gps_time.
template<class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const gps_time<Duration>& t) noexcept;
Returns: utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 315964809s
[Note 1: 315964809s == sys_days{1980y/January/Sunday[1]} - sys_days{1970y/January/1} + 9s — end note]
template<class Duration> static gps_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>& t) noexcept;
Returns: gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 315964809s
[Note 2: 315964809s == sys_days{1980y/January/Sunday[1]} - sys_days{1970y/January/1} + 9s — end note]

30.7.5.3 Non-member functions [time.clock.gps.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T}"), t);
[Example 1: auto st = sys_days{2000y/January/1}; auto gt = clock_cast<gps_clock>(st); cout << format("{0:%F %T %Z} == {1:%F %T %Z}\n", st, gt);
Produces this output:
2000-01-01 00:00:00 UTC == 2000-01-01 00:00:13 GPS
— end example]
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the gps_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Additionally, the parsed offset will be subtracted from the successfully parsed timestamp prior to assigning that difference to tp.
Returns: is.

30.7.6 Type file_clock [time.clock.file]

30.7.6.1 Overview [time.clock.file.overview]

namespace std::chrono { using file_clock = see below; }
file_clock is an alias for a type meeting the Cpp17TrivialClock requirements ([time.clock.req]), and using a signed arithmetic type for file_clock​::​rep.
file_clock is used to create the time_point system used for file_time_type ([filesystems]).
Its epoch is unspecified, and noexcept(file_clock​::​now()) is true.
[Note 1: 
The type that file_clock denotes can be in a different namespace than std​::​chrono, such as std​::​filesystem.
— end note]

30.7.6.2 Member functions [time.clock.file.members]

The type denoted by file_clock provides precisely one of the following two sets of static member functions: template<class Duration> static sys_time<see below> to_sys(const file_time<Duration>&); template<class Duration> static file_time<see below> from_sys(const sys_time<Duration>&); or: template<class Duration> static utc_time<see below> to_utc(const file_time<Duration>&); template<class Duration> static file_time<see below> from_utc(const utc_time<Duration>&);
These member functions shall provide time_point conversions consistent with those specified by utc_clock, tai_clock, and gps_clock.
The Duration of the resultant time_point is computed from the Duration of the input time_point.

30.7.6.3 Non-member functions [time.clock.file.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& t);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T}"), t);
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the file_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Additionally, the parsed offset will be subtracted from the successfully parsed timestamp prior to assigning that difference to tp.
Returns: is.

30.7.7 Class steady_clock [time.clock.steady]

namespace std::chrono { class steady_clock { public: using rep = unspecified; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<unspecified, duration>; static constexpr bool is_steady = true; static time_point now() noexcept; }; }
Objects of class steady_clock represent clocks for which values of time_point never decrease as physical time advances and for which values of time_point advance at a steady rate relative to real time.
That is, the clock may not be adjusted.

30.7.8 Class high_resolution_clock [time.clock.hires]

namespace std::chrono { class high_resolution_clock { public: using rep = unspecified; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<unspecified, duration>; static constexpr bool is_steady = unspecified; static time_point now() noexcept; }; }
Objects of class high_resolution_clock represent clocks with the shortest tick period.
high_resolution_clock may be a synonym for system_clock or steady_clock.

30.7.9 Local time [time.clock.local]

The family of time points denoted by local_time<Duration> are based on the pseudo clock local_t.
local_t has no member now() and thus does not meet the clock requirements.
Nevertheless local_time<Duration> serves the vital role of representing local time with respect to a not-yet-specified time zone.
Aside from being able to get the current time, the complete time_point algebra is available for local_time<Duration> (just as for sys_time<Duration>).
template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& lt);
Effects: os << sys_time<Duration>{lt.time_since_epoch()};
Returns: os.
template<class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the local_time tp using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid date, is.setstate(ios_base​::​failbit) is called and tp is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.7.10 time_point conversions [time.clock.cast]

30.7.10.1 Class template clock_time_conversion [time.clock.conv]

namespace std::chrono { template<class DestClock, class SourceClock> struct clock_time_conversion {}; }
clock_time_conversion serves as a trait which can be used to specify how to convert a source time_point of type time_point<SourceClock, Duration> to a destination time_point of type time_point<DestClock, Duration> via a specialization: clock_time_conversion<DestClock, SourceClock>.
A specialization of clock_time_conversion<DestClock, SourceClock> shall provide a const-qualified operator() that takes a parameter of type time_point<SourceClock, Duration> and returns a time_point<DestClock, OtherDuration> representing an equivalent point in time.
OtherDuration is a chrono​::​duration whose specialization is computed from the input Duration in a manner which can vary for each clock_time_conversion specialization.
A program may specialize clock_time_conversion if at least one of the template parameters is a user-defined clock type.
Several specializations are provided by the implementation, as described in [time.clock.cast.id], [time.clock.cast.sys.utc], [time.clock.cast.sys], and [time.clock.cast.utc].

30.7.10.2 Identity conversions [time.clock.cast.id]

template<class Clock> struct clock_time_conversion<Clock, Clock> { template<class Duration> time_point<Clock, Duration> operator()(const time_point<Clock, Duration>& t) const; };
template<class Duration> time_point<Clock, Duration> operator()(const time_point<Clock, Duration>& t) const;
Returns: t.
template<> struct clock_time_conversion<system_clock, system_clock> { template<class Duration> sys_time<Duration> operator()(const sys_time<Duration>& t) const; };
template<class Duration> sys_time<Duration> operator()(const sys_time<Duration>& t) const;
Returns: t.
template<> struct clock_time_conversion<utc_clock, utc_clock> { template<class Duration> utc_time<Duration> operator()(const utc_time<Duration>& t) const; };
template<class Duration> utc_time<Duration> operator()(const utc_time<Duration>& t) const;
Returns: t.

30.7.10.3 Conversions between system_clock and utc_clock [time.clock.cast.sys.utc]

template<> struct clock_time_conversion<utc_clock, system_clock> { template<class Duration> utc_time<common_type_t<Duration, seconds>> operator()(const sys_time<Duration>& t) const; };
template<class Duration> utc_time<common_type_t<Duration, seconds>> operator()(const sys_time<Duration>& t) const;
Returns: utc_clock​::​from_sys(t).
template<> struct clock_time_conversion<system_clock, utc_clock> { template<class Duration> sys_time<common_type_t<Duration, seconds>> operator()(const utc_time<Duration>& t) const; };
template<class Duration> sys_time<common_type_t<Duration, seconds>> operator()(const utc_time<Duration>& t) const;
Returns: utc_clock​::​to_sys(t).

30.7.10.4 Conversions between system_clock and other clocks [time.clock.cast.sys]

template<class SourceClock> struct clock_time_conversion<system_clock, SourceClock> { template<class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_sys(t)); };
template<class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_sys(t));
Constraints: SourceClock​::​to_sys(t) is well-formed.
Mandates: SourceClock​::​to_sys(t) returns a sys_time<Duration2> for some type Duration2 ([time.point.general]).
Returns: SourceClock​::​to_sys(t).
template<class DestClock> struct clock_time_conversion<DestClock, system_clock> { template<class Duration> auto operator()(const sys_time<Duration>& t) const -> decltype(DestClock::from_sys(t)); };
template<class Duration> auto operator()(const sys_time<Duration>& t) const -> decltype(DestClock::from_sys(t));
Constraints: DestClock​::​from_sys(t) is well-formed.
Mandates: DestClock​::​from_sys(t) returns a time_point<DestClock, Duration2> for some type Duration2 ([time.point.general]).
Returns: DestClock​::​from_sys(t).

30.7.10.5 Conversions between utc_clock and other clocks [time.clock.cast.utc]

template<class SourceClock> struct clock_time_conversion<utc_clock, SourceClock> { template<class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_utc(t)); };
template<class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_utc(t));
Constraints: SourceClock​::​to_utc(t) is well-formed.
Mandates: SourceClock​::​to_utc(t) returns a utc_time<Duration2> for some type Duration2 ([time.point.general]).
Returns: SourceClock​::​to_utc(t).
template<class DestClock> struct clock_time_conversion<DestClock, utc_clock> { template<class Duration> auto operator()(const utc_time<Duration>& t) const -> decltype(DestClock::from_utc(t)); };
template<class Duration> auto operator()(const utc_time<Duration>& t) const -> decltype(DestClock::from_utc(t));
Constraints: DestClock​::​from_utc(t) is well-formed.
Mandates: DestClock​::​from_utc(t) returns a time_point<DestClock, Duration2> for some type Duration2 ([time.point.general]).
Returns: DestClock​::​from_utc(t).

30.7.10.6 Function template clock_cast [time.clock.cast.fn]

template<class DestClock, class SourceClock, class Duration> auto clock_cast(const time_point<SourceClock, Duration>& t);
Constraints: At least one of the following clock time conversion expressions is well-formed:
  • clock_time_conversion<DestClock, SourceClock>{}(t)
  • clock_time_conversion<DestClock, system_clock>{}( clock_time_conversion<system_clock, SourceClock>{}(t))
  • clock_time_conversion<DestClock, utc_clock>{}( clock_time_conversion<utc_clock, SourceClock>{}(t))
  • clock_time_conversion<DestClock, utc_clock>{}( clock_time_conversion<utc_clock, system_clock>{}( clock_time_conversion<system_clock, SourceClock>{}(t)))
  • clock_time_conversion<DestClock, system_clock>{}( clock_time_conversion<system_clock, utc_clock>{}( clock_time_conversion<utc_clock, SourceClock>{}(t)))
A clock time conversion expression is considered better than another clock time conversion expression if it involves fewer operator() calls on clock_time_conversion specializations.
Mandates: Among the well-formed clock time conversion expressions from the above list, there is a unique best expression.
Returns: The best well-formed clock time conversion expression in the above list.

30.8 The civil calendar [time.cal]

30.8.1 General [time.cal.general]

The types in [time.cal] describe the civil (Gregorian) calendar and its relationship to sys_days and local_days.

30.8.2 Class last_spec [time.cal.last]

namespace std::chrono { struct last_spec { explicit last_spec() = default; }; }
The type last_spec is used in conjunction with other calendar types to specify the last in a sequence.
For example, depending on context, it can represent the last day of a month, or the last day of the week of a month.

30.8.3 Class day [time.cal.day]

30.8.3.1 Overview [time.cal.day.overview]

namespace std::chrono { class day { unsigned char d_; // exposition only public: day() = default; constexpr explicit day(unsigned d) noexcept; constexpr day& operator++() noexcept; constexpr day operator++(int) noexcept; constexpr day& operator--() noexcept; constexpr day operator--(int) noexcept; constexpr day& operator+=(const days& d) noexcept; constexpr day& operator-=(const days& d) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; }
day represents a day of a month.
It normally holds values in the range 1 to 31, but may hold non-negative values outside this range.
It can be constructed with any unsigned value, which will be subsequently truncated to fit into day's unspecified internal storage.
day meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements, and participates in basic arithmetic with days objects, which represent a difference between two day objects.
day is a trivially copyable and standard-layout class type.

30.8.3.2 Member functions [time.cal.day.members]

constexpr explicit day(unsigned d) noexcept;
Effects: Initializes d_ with d.
The value held is unspecified if d is not in the range [0, 255].
constexpr day& operator++() noexcept;
Effects: ++d_.
Returns: *this.
constexpr day operator++(int) noexcept;
Effects: ++(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr day& operator--() noexcept;
Effects: Equivalent to: --d_.
Returns: *this.
constexpr day operator--(int) noexcept;
Effects: --(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr day& operator+=(const days& d) noexcept;
Effects: *this = *this + d.
Returns: *this.
constexpr day& operator-=(const days& d) noexcept;
Effects: *this = *this - d.
Returns: *this.
constexpr explicit operator unsigned() const noexcept;
Returns: d_.
constexpr bool ok() const noexcept;
Returns: 1 <= d_ && d_ <= 31.

30.8.3.3 Non-member functions [time.cal.day.nonmembers]

constexpr bool operator==(const day& x, const day& y) noexcept;
Returns: unsigned{x} == unsigned{y}.
constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept;
Returns: unsigned{x} <=> unsigned{y}.
constexpr day operator+(const day& x, const days& y) noexcept;
Returns: day(unsigned{x} + y.count()).
constexpr day operator+(const days& x, const day& y) noexcept;
Returns: y + x.
constexpr day operator-(const day& x, const days& y) noexcept;
Returns: x + -y.
constexpr days operator-(const day& x, const day& y) noexcept;
Returns: days{int(unsigned{x}) - int(unsigned{y})}.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d);
Effects: Equivalent to: return os << (d.ok() ? format(STATICALLY-WIDEN<charT>("{:%d}"), d) : format(STATICALLY-WIDEN<charT>("{:%d} is not a valid day"), d));
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the day d using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid day, is.setstate(ios_base​::​failbit) is called and d is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.
constexpr chrono::day operator""d(unsigned long long d) noexcept;
Returns: day{static_cast<unsigned>(d)}.

30.8.4 Class month [time.cal.month]

30.8.4.1 Overview [time.cal.month.overview]

namespace std::chrono { class month { unsigned char m_; // exposition only public: month() = default; constexpr explicit month(unsigned m) noexcept; constexpr month& operator++() noexcept; constexpr month operator++(int) noexcept; constexpr month& operator--() noexcept; constexpr month operator--(int) noexcept; constexpr month& operator+=(const months& m) noexcept; constexpr month& operator-=(const months& m) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; }
month represents a month of a year.
It normally holds values in the range 1 to 12, but may hold non-negative values outside this range.
It can be constructed with any unsigned value, which will be subsequently truncated to fit into month's unspecified internal storage.
month meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements, and participates in basic arithmetic with months objects, which represent a difference between two month objects.
month is a trivially copyable and standard-layout class type.

30.8.4.2 Member functions [time.cal.month.members]

constexpr explicit month(unsigned m) noexcept;
Effects: Initializes m_ with m.
The value held is unspecified if m is not in the range [0, 255].
constexpr month& operator++() noexcept;
Effects: *this += months{1}.
Returns: *this.
constexpr month operator++(int) noexcept;
Effects: ++(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr month& operator--() noexcept;
Effects: *this -= months{1}.
Returns: *this.
constexpr month operator--(int) noexcept;
Effects: --(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr month& operator+=(const months& m) noexcept;
Effects: *this = *this + m.
Returns: *this.
constexpr month& operator-=(const months& m) noexcept;
Effects: *this = *this - m.
Returns: *this.
constexpr explicit operator unsigned() const noexcept;
Returns: m_.
constexpr bool ok() const noexcept;
Returns: 1 <= m_ && m_ <= 12.

30.8.4.3 Non-member functions [time.cal.month.nonmembers]

constexpr bool operator==(const month& x, const month& y) noexcept;
Returns: unsigned{x} == unsigned{y}.
constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept;
Returns: unsigned{x} <=> unsigned{y}.
constexpr month operator+(const month& x, const months& y) noexcept;
Returns: month{modulo(static_cast<long long>(unsigned{x}) + (y.count() - 1), 12) + 1} where modulo(n, 12) computes the remainder of n divided by 12 using Euclidean division.
[Note 1: 
Given a divisor of 12, Euclidean division truncates towards negative infinity and always produces a remainder in the range of [0, 11].
Assuming no overflow in the signed summation, this operation results in a month holding a value in the range [1, 12] even if !x.ok().
— end note]
[Example 1: 
February + months{11} == January.
— end example]
constexpr month operator+(const months& x, const month& y) noexcept;
Returns: y + x.
constexpr month operator-(const month& x, const months& y) noexcept;
Returns: x + -y.
constexpr months operator-(const month& x, const month& y) noexcept;
Returns: If x.ok() == true and y.ok() == true, returns a value m in the range [months{0}, months{11}] satisfying y + m == x.
Otherwise the value returned is unspecified.
[Example 2: 
January - February == months{11}.
— end example]
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month& m);
Effects: Equivalent to: return os << (m.ok() ? format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%b}"), m) : format(os.getloc(), STATICALLY-WIDEN<charT>("{} is not a valid month"), static_cast<unsigned>(m)));
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the month m using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid month, is.setstate(ios_base​::​failbit) is called and m is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.8.5 Class year [time.cal.year]

30.8.5.1 Overview [time.cal.year.overview]

namespace std::chrono { class year { short y_; // exposition only public: year() = default; constexpr explicit year(int y) noexcept; constexpr year& operator++() noexcept; constexpr year operator++(int) noexcept; constexpr year& operator--() noexcept; constexpr year operator--(int) noexcept; constexpr year& operator+=(const years& y) noexcept; constexpr year& operator-=(const years& y) noexcept; constexpr year operator+() const noexcept; constexpr year operator-() const noexcept; constexpr bool is_leap() const noexcept; constexpr explicit operator int() const noexcept; constexpr bool ok() const noexcept; static constexpr year min() noexcept; static constexpr year max() noexcept; }; }
year represents a year in the civil calendar.
It can represent values in the range [min(), max()].
It can be constructed with any int value, which will be subsequently truncated to fit into year's unspecified internal storage.
year meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements, and participates in basic arithmetic with years objects, which represent a difference between two year objects.
year is a trivially copyable and standard-layout class type.

30.8.5.2 Member functions [time.cal.year.members]

constexpr explicit year(int y) noexcept;
Effects: Initializes y_ with y.
The value held is unspecified if y is not in the range [-32767, 32767].
constexpr year& operator++() noexcept;
Effects: ++y_.
Returns: *this.
constexpr year operator++(int) noexcept;
Effects: ++(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr year& operator--() noexcept;
Effects: --y_.
Returns: *this.
constexpr year operator--(int) noexcept;
Effects: --(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr year& operator+=(const years& y) noexcept;
Effects: *this = *this + y.
Returns: *this.
constexpr year& operator-=(const years& y) noexcept;
Effects: *this = *this - y.
Returns: *this.
constexpr year operator+() const noexcept;
Returns: *this.
constexpr year operator-() const noexcept;
Returns: year{-y_}.
constexpr bool is_leap() const noexcept;
Returns: y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0).
constexpr explicit operator int() const noexcept;
Returns: y_.
constexpr bool ok() const noexcept;
Returns: min().y_ <= y_ && y_ <= max().y_.
static constexpr year min() noexcept;
Returns: year{-32767}.
static constexpr year max() noexcept;
Returns: year{32767}.

30.8.5.3 Non-member functions [time.cal.year.nonmembers]

constexpr bool operator==(const year& x, const year& y) noexcept;
Returns: int{x} == int{y}.
constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept;
Returns: int{x} <=> int{y}.
constexpr year operator+(const year& x, const years& y) noexcept;
Returns: year{int{x} + static_cast<int>(y.count())}.
constexpr year operator+(const years& x, const year& y) noexcept;
Returns: y + x.
constexpr year operator-(const year& x, const years& y) noexcept;
Returns: x + -y.
constexpr years operator-(const year& x, const year& y) noexcept;
Returns: years{int{x} - int{y}}.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year& y);
Effects: Equivalent to: return os << (y.ok() ? format(STATICALLY-WIDEN<charT>("{:%Y}"), y) : format(STATICALLY-WIDEN<charT>("{:%Y} is not a valid year"), y));
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the year y using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid year, is.setstate(ios_base​::​failbit) is called and y is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.
constexpr chrono::year operator""y(unsigned long long y) noexcept;
Returns: year{static_cast<int>(y)}.

30.8.6 Class weekday [time.cal.wd]

30.8.6.1 Overview [time.cal.wd.overview]

namespace std::chrono { class weekday { unsigned char wd_; // exposition only public: weekday() = default; constexpr explicit weekday(unsigned wd) noexcept; constexpr weekday(const sys_days& dp) noexcept; constexpr explicit weekday(const local_days& dp) noexcept; constexpr weekday& operator++() noexcept; constexpr weekday operator++(int) noexcept; constexpr weekday& operator--() noexcept; constexpr weekday operator--(int) noexcept; constexpr weekday& operator+=(const days& d) noexcept; constexpr weekday& operator-=(const days& d) noexcept; constexpr unsigned c_encoding() const noexcept; constexpr unsigned iso_encoding() const noexcept; constexpr bool ok() const noexcept; constexpr weekday_indexed operator[](unsigned index) const noexcept; constexpr weekday_last operator[](last_spec) const noexcept; }; }
weekday represents a day of the week in the civil calendar.
It normally holds values in the range 0 to 6, corresponding to Sunday through Saturday, but it may hold non-negative values outside this range.
It can be constructed with any unsigned value, which will be subsequently truncated to fit into weekday's unspecified internal storage.
weekday meets the Cpp17EqualityComparable (Table 28) requirements.
[Note 1: 
weekday is not Cpp17LessThanComparable because there is no universal consensus on which day is the first day of the week.
weekday's arithmetic operations treat the days of the week as a circular range, with no beginning and no end.
— end note]
weekday is a trivially copyable and standard-layout class type.

30.8.6.2 Member functions [time.cal.wd.members]

constexpr explicit weekday(unsigned wd) noexcept;
Effects: Initializes wd_ with wd == 7 ? 0 : wd.
The value held is unspecified if wd is not in the range [0, 255].
constexpr weekday(const sys_days& dp) noexcept;
Effects: Computes what day of the week corresponds to the sys_days dp, and initializes that day of the week in wd_.
[Example 1: 
If dp represents 1970-01-01, the constructed weekday represents Thursday by storing 4 in wd_.
— end example]
constexpr explicit weekday(const local_days& dp) noexcept;
Effects: Computes what day of the week corresponds to the local_days dp, and initializes that day of the week in wd_.
Postconditions: The value is identical to that constructed from sys_days{dp.time_since_epoch()}.
constexpr weekday& operator++() noexcept;
Effects: *this += days{1}.
Returns: *this.
constexpr weekday operator++(int) noexcept;
Effects: ++(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr weekday& operator--() noexcept;
Effects: *this -= days{1}.
Returns: *this.
constexpr weekday operator--(int) noexcept;
Effects: --(*this).
Returns: A copy of *this as it existed on entry to this member function.
constexpr weekday& operator+=(const days& d) noexcept;
Effects: *this = *this + d.
Returns: *this.
constexpr weekday& operator-=(const days& d) noexcept;
Effects: *this = *this - d.
Returns: *this.
constexpr unsigned c_encoding() const noexcept;
Returns: wd_.
constexpr unsigned iso_encoding() const noexcept;
Returns: wd_ == 0u ? 7u : wd_.
constexpr bool ok() const noexcept;
Returns: wd_ <= 6.
constexpr weekday_indexed operator[](unsigned index) const noexcept;
Returns: {*this, index}.
constexpr weekday_last operator[](last_spec) const noexcept;
Returns: weekday_last{*this}.

30.8.6.3 Non-member functions [time.cal.wd.nonmembers]

constexpr bool operator==(const weekday& x, const weekday& y) noexcept;
Returns: x.wd_ == y.wd_.
constexpr weekday operator+(const weekday& x, const days& y) noexcept;
Returns: weekday{modulo(static_cast<long long>(x.wd_) + y.count(), 7)} where modulo(n, 7) computes the remainder of n divided by 7 using Euclidean division.
[Note 1: 
Given a divisor of 7, Euclidean division truncates towards negative infinity and always produces a remainder in the range of [0, 6].
Assuming no overflow in the signed summation, this operation results in a weekday holding a value in the range [0, 6] even if !x.ok().
— end note]
[Example 1: 
Monday + days{6} == Sunday.
— end example]
constexpr weekday operator+(const days& x, const weekday& y) noexcept;
Returns: y + x.
constexpr weekday operator-(const weekday& x, const days& y) noexcept;
Returns: x + -y.
constexpr days operator-(const weekday& x, const weekday& y) noexcept;
Returns: If x.ok() == true and y.ok() == true, returns a value d in the range [days{0}, days{6}] satisfying y + d == x.
Otherwise the value returned is unspecified.
[Example 2: 
Sunday - Monday == days{6}.
— end example]
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd);
Effects: Equivalent to: return os << (wd.ok() ? format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%a}"), wd) : format(os.getloc(), STATICALLY-WIDEN<charT>("{} is not a valid weekday"), static_cast<unsigned>(wd.wd_)));
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the weekday wd using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid weekday, is.setstate(ios_base​::​failbit) is called and wd is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.8.7 Class weekday_indexed [time.cal.wdidx]

30.8.7.1 Overview [time.cal.wdidx.overview]

namespace std::chrono { class weekday_indexed { chrono::weekday wd_; // exposition only unsigned char index_; // exposition only public: weekday_indexed() = default; constexpr weekday_indexed(const chrono::weekday& wd, unsigned index) noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr bool ok() const noexcept; }; }
weekday_indexed represents a weekday and a small index in the range 1 to 5.
This class is used to represent the first, second, third, fourth, or fifth weekday of a month.
[Note 1: 
A weekday_indexed object can be constructed by indexing a weekday with an unsigned.
— end note]
[Example 1: constexpr auto wdi = Sunday[2]; // wdi is the second Sunday of an as yet unspecified month static_assert(wdi.weekday() == Sunday); static_assert(wdi.index() == 2); — end example]
weekday_indexed is a trivially copyable and standard-layout class type.

30.8.7.2 Member functions [time.cal.wdidx.members]

constexpr weekday_indexed(const chrono::weekday& wd, unsigned index) noexcept;
Effects: Initializes wd_ with wd and index_ with index.
The values held are unspecified if !wd.ok() or index is not in the range [0, 7].
constexpr chrono::weekday weekday() const noexcept;
Returns: wd_.
constexpr unsigned index() const noexcept;
Returns: index_.
constexpr bool ok() const noexcept;
Returns: wd_.ok() && 1 <= index_ && index_ <= 5.

30.8.7.3 Non-member functions [time.cal.wdidx.nonmembers]

constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept;
Returns: x.weekday() == y.weekday() && x.index() == y.index().
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi);
Effects: Equivalent to: auto i = wdi.index(); return os << (i >= 1 && i <= 5 ? format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}[{}]"), wdi.weekday(), i) : format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}[{} is not a valid index]"), wdi.weekday(), i));

30.8.8 Class weekday_last [time.cal.wdlast]

30.8.8.1 Overview [time.cal.wdlast.overview]

namespace std::chrono { class weekday_last { chrono::weekday wd_; // exposition only public: constexpr explicit weekday_last(const chrono::weekday& wd) noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr bool ok() const noexcept; }; }
weekday_last represents the last weekday of a month.
[Note 1: 
A weekday_last object can be constructed by indexing a weekday with last.
— end note]
[Example 1: constexpr auto wdl = Sunday[last]; // wdl is the last Sunday of an as yet unspecified month static_assert(wdl.weekday() == Sunday); — end example]
weekday_last is a trivially copyable and standard-layout class type.

30.8.8.2 Member functions [time.cal.wdlast.members]

constexpr explicit weekday_last(const chrono::weekday& wd) noexcept;
Effects: Initializes wd_ with wd.
constexpr chrono::weekday weekday() const noexcept;
Returns: wd_.
constexpr bool ok() const noexcept;
Returns: wd_.ok().

30.8.8.3 Non-member functions [time.cal.wdlast.nonmembers]

constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept;
Returns: x.weekday() == y.weekday().
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}[last]"), wdl.weekday());

30.8.9 Class month_day [time.cal.md]

30.8.9.1 Overview [time.cal.md.overview]

namespace std::chrono { class month_day { chrono::month m_; // exposition only chrono::day d_; // exposition only public: month_day() = default; constexpr month_day(const chrono::month& m, const chrono::day& d) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::day day() const noexcept; constexpr bool ok() const noexcept; }; }
month_day represents a specific day of a specific month, but with an unspecified year.
month_day meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements.
month_day is a trivially copyable and standard-layout class type.

30.8.9.2 Member functions [time.cal.md.members]

constexpr month_day(const chrono::month& m, const chrono::day& d) noexcept;
Effects: Initializes m_ with m, and d_ with d.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::day day() const noexcept;
Returns: d_.
constexpr bool ok() const noexcept;
Returns: true if m_.ok() is true, 1d <= d_, and d_ is less than or equal to the number of days in month m_; otherwise returns false.
When m_ == February, the number of days is considered to be 29.

30.8.9.3 Non-member functions [time.cal.md.nonmembers]

constexpr bool operator==(const month_day& x, const month_day& y) noexcept;
Returns: x.month() == y.month() && x.day() == y.day().
constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept;
Effects: Equivalent to: if (auto c = x.month() <=> y.month(); c != 0) return c; return x.day() <=> y.day();
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day& md);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}/{}"), md.month(), md.day());
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the month_day md using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid month_day, is.setstate(ios_base​::​failbit) is called and md is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.8.10 Class month_day_last [time.cal.mdlast]

namespace std::chrono { class month_day_last { chrono::month m_; // exposition only public: constexpr explicit month_day_last(const chrono::month& m) noexcept; constexpr chrono::month month() const noexcept; constexpr bool ok() const noexcept; }; }
month_day_last represents the last day of a month.
[Note 1: 
A month_day_last object can be constructed using the expression m/last or last/m, where m is an expression of type month.
— end note]
[Example 1: constexpr auto mdl = February/last; // mdl is the last day of February of an as yet unspecified year static_assert(mdl.month() == February); — end example]
month_day_last is a trivially copyable and standard-layout class type.
constexpr explicit month_day_last(const chrono::month& m) noexcept;
Effects: Initializes m_ with m.
constexpr month month() const noexcept;
Returns: m_.
constexpr bool ok() const noexcept;
Returns: m_.ok().
constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept;
Returns: x.month() == y.month().
constexpr strong_ordering operator<=>(const month_day_last& x, const month_day_last& y) noexcept;
Returns: x.month() <=> y.month().
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}/last"), mdl.month());

30.8.11 Class month_weekday [time.cal.mwd]

30.8.11.1 Overview [time.cal.mwd.overview]

namespace std::chrono { class month_weekday { chrono::month m_; // exposition only chrono::weekday_indexed wdi_; // exposition only public: constexpr month_weekday(const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday_indexed weekday_indexed() const noexcept; constexpr bool ok() const noexcept; }; }
month_weekday represents the weekday of a month, of an as yet unspecified year.
To do this the month_weekday stores a month and a weekday_indexed.
[Example 1: constexpr auto mwd = February/Tuesday[3]; // mwd is the third Tuesday of February of an as yet unspecified year static_assert(mwd.month() == February); static_assert(mwd.weekday_indexed() == Tuesday[3]); — end example]
month_weekday is a trivially copyable and standard-layout class type.

30.8.11.2 Member functions [time.cal.mwd.members]

constexpr month_weekday(const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept;
Effects: Initializes m_ with m, and wdi_ with wdi.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::weekday_indexed weekday_indexed() const noexcept;
Returns: wdi_.
constexpr bool ok() const noexcept;
Returns: m_.ok() && wdi_.ok().

30.8.11.3 Non-member functions [time.cal.mwd.nonmembers]

constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept;
Returns: x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed().
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}/{:L}"), mwd.month(), mwd.weekday_indexed());

30.8.12 Class month_weekday_last [time.cal.mwdlast]

30.8.12.1 Overview [time.cal.mwdlast.overview]

namespace std::chrono { class month_weekday_last { chrono::month m_; // exposition only chrono::weekday_last wdl_; // exposition only public: constexpr month_weekday_last(const chrono::month& m, const chrono::weekday_last& wdl) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday_last weekday_last() const noexcept; constexpr bool ok() const noexcept; }; }
month_weekday_last represents the last weekday of a month, of an as yet unspecified year.
To do this the month_weekday_last stores a month and a weekday_last.
[Example 1: constexpr auto mwd = February/Tuesday[last]; // mwd is the last Tuesday of February of an as yet unspecified year static_assert(mwd.month() == February); static_assert(mwd.weekday_last() == Tuesday[last]); — end example]
month_weekday_last is a trivially copyable and standard-layout class type.

30.8.12.2 Member functions [time.cal.mwdlast.members]

constexpr month_weekday_last(const chrono::month& m, const chrono::weekday_last& wdl) noexcept;
Effects: Initializes m_ with m, and wdl_ with wdl.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::weekday_last weekday_last() const noexcept;
Returns: wdl_.
constexpr bool ok() const noexcept;
Returns: m_.ok() && wdl_.ok().

30.8.12.3 Non-member functions [time.cal.mwdlast.nonmembers]

constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept;
Returns: x.month() == y.month() && x.weekday_last() == y.weekday_last().
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L}/{:L}"), mwdl.month(), mwdl.weekday_last());

30.8.13 Class year_month [time.cal.ym]

30.8.13.1 Overview [time.cal.ym.overview]

namespace std::chrono { class year_month { chrono::year y_; // exposition only chrono::month m_; // exposition only public: year_month() = default; constexpr year_month(const chrono::year& y, const chrono::month& m) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr year_month& operator+=(const months& dm) noexcept; constexpr year_month& operator-=(const months& dm) noexcept; constexpr year_month& operator+=(const years& dy) noexcept; constexpr year_month& operator-=(const years& dy) noexcept; constexpr bool ok() const noexcept; }; }
year_month represents a specific month of a specific year, but with an unspecified day.
year_month is a field-based time point with a resolution of months.
year_month meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements.
year_month is a trivially copyable and standard-layout class type.

30.8.13.2 Member functions [time.cal.ym.members]

constexpr year_month(const chrono::year& y, const chrono::month& m) noexcept;
Effects: Initializes y_ with y, and m_ with m.
constexpr chrono::year year() const noexcept;
Returns: y_.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr year_month& operator+=(const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this + dm.
Returns: *this.
constexpr year_month& operator-=(const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this - dm.
Returns: *this.
constexpr year_month& operator+=(const years& dy) noexcept;
Effects: *this = *this + dy.
Returns: *this.
constexpr year_month& operator-=(const years& dy) noexcept;
Effects: *this = *this - dy.
Returns: *this.
constexpr bool ok() const noexcept;
Returns: y_.ok() && m_.ok().

30.8.13.3 Non-member functions [time.cal.ym.nonmembers]

constexpr bool operator==(const year_month& x, const year_month& y) noexcept;
Returns: x.year() == y.year() && x.month() == y.month().
constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept;
Effects: Equivalent to: if (auto c = x.year() <=> y.year(); c != 0) return c; return x.month() <=> y.month();
constexpr year_month operator+(const year_month& ym, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: A year_month value z such that z.ok() && z - ym == dm is true.
Complexity: with respect to the value of dm.
constexpr year_month operator+(const months& dm, const year_month& ym) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ym + dm.
constexpr year_month operator-(const year_month& ym, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ym + -dm.
constexpr months operator-(const year_month& x, const year_month& y) noexcept;
Returns: x.year() - y.year() + months{static_cast<int>(unsigned{x.month()}) - static_cast<int>(unsigned{y.month()})}
constexpr year_month operator+(const year_month& ym, const years& dy) noexcept;
Returns: (ym.year() + dy) / ym.month().
constexpr year_month operator+(const years& dy, const year_month& ym) noexcept;
Returns: ym + dy.
constexpr year_month operator-(const year_month& ym, const years& dy) noexcept;
Returns: ym + -dy.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month& ym);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{}/{:L}"), ym.year(), ym.month());
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the year_month ym using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid year_month, is.setstate(ios_base​::​failbit) is called and ym is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.8.14 Class year_month_day [time.cal.ymd]

30.8.14.1 Overview [time.cal.ymd.overview]

namespace std::chrono { class year_month_day { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::day d_; // exposition only public: year_month_day() = default; constexpr year_month_day(const chrono::year& y, const chrono::month& m, const chrono::day& d) noexcept; constexpr year_month_day(const year_month_day_last& ymdl) noexcept; constexpr year_month_day(const sys_days& dp) noexcept; constexpr explicit year_month_day(const local_days& dp) noexcept; constexpr year_month_day& operator+=(const months& m) noexcept; constexpr year_month_day& operator-=(const months& m) noexcept; constexpr year_month_day& operator+=(const years& y) noexcept; constexpr year_month_day& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; }
year_month_day represents a specific year, month, and day.
year_month_day is a field-based time point with a resolution of days.
[Note 1: 
year_month_day supports years- and months-oriented arithmetic, but not days-oriented arithmetic.
For the latter, there is a conversion to sys_days, which efficiently supports days-oriented arithmetic.
— end note]
year_month_day meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements.
year_month_day is a trivially copyable and standard-layout class type.

30.8.14.2 Member functions [time.cal.ymd.members]

constexpr year_month_day(const chrono::year& y, const chrono::month& m, const chrono::day& d) noexcept;
Effects: Initializes y_ with y, m_ with m, and d_ with d.
constexpr year_month_day(const year_month_day_last& ymdl) noexcept;
Effects: Initializes y_ with ymdl.year(), m_ with ymdl.month(), and d_ with ymdl.day().
[Note 1: 
This conversion from year_month_day_last to year_month_day can be more efficient than converting a year_month_day_last to a sys_days, and then converting that sys_days to a year_month_day.
— end note]
constexpr year_month_day(const sys_days& dp) noexcept;
Effects: Constructs an object of type year_month_day that corresponds to the date represented by dp.
Remarks: For any value ymd of type year_month_day for which ymd.ok() is true, ymd == year_month_day{sys_days{ymd}} is true.
constexpr explicit year_month_day(const local_days& dp) noexcept;
Effects: Equivalent to constructing with sys_days{dp.time_since_epoch()}.
constexpr year_month_day& operator+=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this + m.
Returns: *this.
constexpr year_month_day& operator-=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this - m.
Returns: *this.
constexpr year_month_day& year_month_day::operator+=(const years& y) noexcept;
Effects: *this = *this + y.
Returns: *this.
constexpr year_month_day& year_month_day::operator-=(const years& y) noexcept;
Effects: *this = *this - y.
Returns: *this.
constexpr chrono::year year() const noexcept;
Returns: y_.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::day day() const noexcept;
Returns: d_.
constexpr operator sys_days() const noexcept;
Returns: If ok(), returns a sys_days holding a count of days from the sys_days epoch to *this (a negative value if *this represents a date prior to the sys_days epoch).
Otherwise, if y_.ok() && m_.ok() is true, returns sys_days{y_/m_/1d} + (d_ - 1d).
Otherwise the value returned is unspecified.
Remarks: A sys_days in the range [days{-12687428}, days{11248737}] which is converted to a year_month_day has the same value when converted back to a sys_days.
[Example 1: static_assert(year_month_day{sys_days{2017y/January/0}} == 2016y/December/31); static_assert(year_month_day{sys_days{2017y/January/31}} == 2017y/January/31); static_assert(year_month_day{sys_days{2017y/January/32}} == 2017y/February/1); — end example]
constexpr explicit operator local_days() const noexcept;
Returns: local_days{sys_days{*this}.time_since_epoch()}.
constexpr bool ok() const noexcept;
Returns: If y_.ok() is true, and m_.ok() is true, and d_ is in the range [1d, (y_/m_/last).day()], then returns true; otherwise returns false.

30.8.14.3 Non-member functions [time.cal.ymd.nonmembers]

constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept;
Returns: x.year() == y.year() && x.month() == y.month() && x.day() == y.day().
constexpr strong_ordering operator<=>(const year_month_day& x, const year_month_day& y) noexcept;
Effects: Equivalent to: if (auto c = x.year() <=> y.year(); c != 0) return c; if (auto c = x.month() <=> y.month(); c != 0) return c; return x.day() <=> y.day();
constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: (ymd.year() / ymd.month() + dm) / ymd.day().
[Note 1: 
If ymd.day() is in the range [1d, 28d], ok() will return true for the resultant year_month_day.
— end note]
constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymd + dm.
constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymd + (-dm).
constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;
Returns: (ymd.year() + dy) / ymd.month() / ymd.day().
[Note 2: 
If ymd.month() is February and ymd.day() is not in the range [1d, 28d], ok() can return false for the resultant year_month_day.
— end note]
constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept;
Returns: ymd + dy.
constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept;
Returns: ymd + (-dy).
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd);
Effects: Equivalent to: return os << (ymd.ok() ? format(STATICALLY-WIDEN<charT>("{:%F}"), ymd) : format(STATICALLY-WIDEN<charT>("{:%F} is not a valid date"), ymd));
template<class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
Effects: Attempts to parse the input stream is into the year_month_day ymd using the format flags given in the NTCTS fmt as specified in [time.parse].
If the parse fails to decode a valid year_month_day, is.setstate(ios_base​::​failbit) is called and ymd is not modified.
If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null.
If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.
Returns: is.

30.8.15 Class year_month_day_last [time.cal.ymdlast]

30.8.15.1 Overview [time.cal.ymdlast.overview]

namespace std::chrono { class year_month_day_last { chrono::year y_; // exposition only chrono::month_day_last mdl_; // exposition only public: constexpr year_month_day_last(const chrono::year& y, const chrono::month_day_last& mdl) noexcept; constexpr year_month_day_last& operator+=(const months& m) noexcept; constexpr year_month_day_last& operator-=(const months& m) noexcept; constexpr year_month_day_last& operator+=(const years& y) noexcept; constexpr year_month_day_last& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::month_day_last month_day_last() const noexcept; constexpr chrono::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; }
year_month_day_last represents the last day of a specific year and month.
year_month_day_last is a field-based time point with a resolution of days, except that it is restricted to pointing to the last day of a year and month.
[Note 1: 
year_month_day_last supports years- and months-oriented arithmetic, but not days-oriented arithmetic.
For the latter, there is a conversion to sys_days, which efficiently supports days-oriented arithmetic.
— end note]
year_month_day_last meets the Cpp17EqualityComparable (Table 28) and Cpp17LessThanComparable (Table 29) requirements.
year_month_day_last is a trivially copyable and standard-layout class type.

30.8.15.2 Member functions [time.cal.ymdlast.members]

constexpr year_month_day_last(const chrono::year& y, const chrono::month_day_last& mdl) noexcept;
Effects: Initializes y_ with y and mdl_ with mdl.
constexpr year_month_day_last& operator+=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this + m.
Returns: *this.
constexpr year_month_day_last& operator-=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this - m.
Returns: *this.
constexpr year_month_day_last& operator+=(const years& y) noexcept;
Effects: *this = *this + y.
Returns: *this.
constexpr year_month_day_last& operator-=(const years& y) noexcept;
Effects: *this = *this - y.
Returns: *this.
constexpr chrono::year year() const noexcept;
Returns: y_.
constexpr chrono::month month() const noexcept;
Returns: mdl_.month().
constexpr chrono::month_day_last month_day_last() const noexcept;
Returns: mdl_.
constexpr chrono::day day() const noexcept;
Returns: If ok() is true, returns a day representing the last day of the (year, month) pair represented by *this.
Otherwise, the returned value is unspecified.
[Note 1: 
This value might be computed on demand.
— end note]
constexpr operator sys_days() const noexcept;
Returns: sys_days{year()/month()/day()}.
constexpr explicit operator local_days() const noexcept;
Returns: local_days{sys_days{*this}.time_since_epoch()}.
constexpr bool ok() const noexcept;
Returns: y_.ok() && mdl_.ok().

30.8.15.3 Non-member functions [time.cal.ymdlast.nonmembers]

constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept;
Returns: x.year() == y.year() && x.month_day_last() == y.month_day_last().
constexpr strong_ordering operator<=>(const year_month_day_last& x, const year_month_day_last& y) noexcept;
Effects: Equivalent to: if (auto c = x.year() <=> y.year(); c != 0) return c; return x.month_day_last() <=> y.month_day_last();
constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: (ymdl.year() / ymdl.month() + dm) / last.
constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymdl + dm.
constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymdl + (-dm).
constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept;
Returns: {ymdl.year()+dy, ymdl.month_day_last()}.
constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept;
Returns: ymdl + dy.
constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept;
Returns: ymdl + (-dy).
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{}/{:L}"), ymdl.year(), ymdl.month_day_last());

30.8.16 Class year_month_weekday [time.cal.ymwd]

30.8.16.1 Overview [time.cal.ymwd.overview]

namespace std::chrono { class year_month_weekday { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::weekday_indexed wdi_; // exposition only public: year_month_weekday() = default; constexpr year_month_weekday(const chrono::year& y, const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept; constexpr year_month_weekday(const sys_days& dp) noexcept; constexpr explicit year_month_weekday(const local_days& dp) noexcept; constexpr year_month_weekday& operator+=(const months& m) noexcept; constexpr year_month_weekday& operator-=(const months& m) noexcept; constexpr year_month_weekday& operator+=(const years& y) noexcept; constexpr year_month_weekday& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr chrono::weekday_indexed weekday_indexed() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; }
year_month_weekday represents a specific year, month, and weekday of the month.
year_month_weekday is a field-based time point with a resolution of days.
[Note 1: 
year_month_weekday supports years- and months-oriented arithmetic, but not days-oriented arithmetic.
For the latter, there is a conversion to sys_days, which efficiently supports days-oriented arithmetic.
— end note]
year_month_weekday meets the Cpp17EqualityComparable (Table 28) requirements.
year_month_weekday is a trivially copyable and standard-layout class type.

30.8.16.2 Member functions [time.cal.ymwd.members]

constexpr year_month_weekday(const chrono::year& y, const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept;
Effects: Initializes y_ with y, m_ with m, and wdi_ with wdi.
constexpr year_month_weekday(const sys_days& dp) noexcept;
Effects: Constructs an object of type year_month_weekday which corresponds to the date represented by dp.
Remarks: For any value ymwd of type year_month_weekday for which ymwd.ok() is true, ymwd == year_month_weekday{sys_days{ymwd}} is true.
constexpr explicit year_month_weekday(const local_days& dp) noexcept;
Effects: Equivalent to constructing with sys_days{dp.time_since_epoch()}.
constexpr year_month_weekday& operator+=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this + m.
Returns: *this.
constexpr year_month_weekday& operator-=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this - m.
Returns: *this.
constexpr year_month_weekday& operator+=(const years& y) noexcept;
Effects: *this = *this + y.
Returns: *this.
constexpr year_month_weekday& operator-=(const years& y) noexcept;
Effects: *this = *this - y.
Returns: *this.
constexpr chrono::year year() const noexcept;
Returns: y_.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::weekday weekday() const noexcept;
Returns: wdi_.weekday().
constexpr unsigned index() const noexcept;
Returns: wdi_.index().
constexpr chrono::weekday_indexed weekday_indexed() const noexcept;
Returns: wdi_.
constexpr operator sys_days() const noexcept;
Returns: If y_.ok() && m_.ok() && wdi_.weekday().ok(), returns a sys_days that represents the date (index() - 1) * 7 days after the first weekday() of year()/month().
If index() is 0 the returned sys_days represents the date 7 days prior to the first weekday() of year()/month().
Otherwise the returned value is unspecified.
constexpr explicit operator local_days() const noexcept;
Returns: local_days{sys_days{*this}.time_since_epoch()}.
constexpr bool ok() const noexcept;
Returns: If any of y_.ok(), m_.ok(), or wdi_.ok() is false, returns false.
Otherwise, if *this represents a valid date, returns true.
Otherwise, returns false.

30.8.16.3 Non-member functions [time.cal.ymwd.nonmembers]

constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept;
Returns: x.year() == y.year() && x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed()
constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed().
constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymwd + dm.
constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymwd + (-dm).
constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept;
Returns: {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}.
constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept;
Returns: ymwd + dy.
constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept;
Returns: ymwd + (-dy).
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwd);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{}/{:L}/{:L}"), ymwd.year(), ymwd.month(), ymwd.weekday_indexed());

30.8.17 Class year_month_weekday_last [time.cal.ymwdlast]

30.8.17.1 Overview [time.cal.ymwdlast.overview]

namespace std::chrono { class year_month_weekday_last { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::weekday_last wdl_; // exposition only public: constexpr year_month_weekday_last(const chrono::year& y, const chrono::month& m, const chrono::weekday_last& wdl) noexcept; constexpr year_month_weekday_last& operator+=(const months& m) noexcept; constexpr year_month_weekday_last& operator-=(const months& m) noexcept; constexpr year_month_weekday_last& operator+=(const years& y) noexcept; constexpr year_month_weekday_last& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr chrono::weekday_last weekday_last() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; }
year_month_weekday_last represents a specific year, month, and last weekday of the month.
year_month_weekday_last is a field-based time point with a resolution of days, except that it is restricted to pointing to the last weekday of a year and month.
[Note 1: 
year_month_weekday_last supports years- and months-oriented arithmetic, but not days-oriented arithmetic.
For the latter, there is a conversion to sys_days, which efficiently supports days-oriented arithmetic.
— end note]
year_month_weekday_last meets the Cpp17EqualityComparable (Table 28) requirements.
year_month_weekday_last is a trivially copyable and standard-layout class type.

30.8.17.2 Member functions [time.cal.ymwdlast.members]

constexpr year_month_weekday_last(const chrono::year& y, const chrono::month& m, const chrono::weekday_last& wdl) noexcept;
Effects: Initializes y_ with y, m_ with m, and wdl_ with wdl.
constexpr year_month_weekday_last& operator+=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this + m.
Returns: *this.
constexpr year_month_weekday_last& operator-=(const months& m) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Effects: *this = *this - m.
Returns: *this.
constexpr year_month_weekday_last& operator+=(const years& y) noexcept;
Effects: *this = *this + y.
Returns: *this.
constexpr year_month_weekday_last& operator-=(const years& y) noexcept;
Effects: *this = *this - y.
Returns: *this.
constexpr chrono::year year() const noexcept;
Returns: y_.
constexpr chrono::month month() const noexcept;
Returns: m_.
constexpr chrono::weekday weekday() const noexcept;
Returns: wdl_.weekday().
constexpr chrono::weekday_last weekday_last() const noexcept;
Returns: wdl_.
constexpr operator sys_days() const noexcept;
Returns: If ok() == true, returns a sys_days that represents the last weekday() of year()/month().
Otherwise the returned value is unspecified.
constexpr explicit operator local_days() const noexcept;
Returns: local_days{sys_days{*this}.time_since_epoch()}.
constexpr bool ok() const noexcept;
Returns: y_.ok() && m_.ok() && wdl_.ok().

30.8.17.3 Non-member functions [time.cal.ymwdlast.nonmembers]

constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;
Returns: x.year() == y.year() && x.month() == y.month() && x.weekday_last() == y.weekday_last()
constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last().
constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymwdl + dm.
constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept;
Constraints: If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months ([over.ics.rank]).
Returns: ymwdl + (-dm).
constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept;
Returns: {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}.
constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept;
Returns: ymwdl + dy.
constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept;
Returns: ymwdl + (-dy).
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{}/{:L}/{:L}"), ymwdl.year(), ymwdl.month(), ymwdl.weekday_last());

30.8.18 Conventional syntax operators [time.cal.operators]

A set of overloaded operator/ functions provides a conventional syntax for the creation of civil calendar dates.
[Note 1: 
The year, month, and day are accepted in any of the following 3 orders: year/month/day month/day/year day/month/year
Anywhere a day is needed, any of the following can also be specified: last weekday[i] weekday[last]
— end note]
[Note 2: 
Partial-date types such as year_month and month_day can be created by not applying the second division operator for any of the three orders.
For example: year_month ym = 2015y/April; month_day md1 = April/4; month_day md2 = 4d/April;
— end note]
[Example 1: auto a = 2015/4/4; // a == int(125) auto b = 2015y/4/4; // b == year_month_day{year(2015), month(4), day(4)} auto c = 2015y/4d/April; // error: no viable operator/ for first / auto d = 2015/April/4; // error: no viable operator/ for first / — end example]
constexpr year_month operator/(const year& y, const month& m) noexcept;
Returns: {y, m}.
constexpr year_month operator/(const year& y, int m) noexcept;
Returns: y / month(m).
constexpr month_day operator/(const month& m, const day& d) noexcept;
Returns: {m, d}.
constexpr month_day operator/(const month& m, int d) noexcept;
Returns: m / day(d).
constexpr month_day operator/(int m, const day& d) noexcept;
Returns: month(m) / d.
constexpr month_day operator/(const day& d, const month& m) noexcept;
Returns: m / d.
constexpr month_day operator/(const day& d, int m) noexcept;
Returns: month(m) / d.
constexpr month_day_last operator/(const month& m, last_spec) noexcept;
Returns: month_day_last{m}.
constexpr month_day_last operator/(int m, last_spec) noexcept;
Returns: month(m) / last.
constexpr month_day_last operator/(last_spec, const month& m) noexcept;
Returns: m / last.
constexpr month_day_last operator/(last_spec, int m) noexcept;
Returns: month(m) / last.
constexpr month_weekday operator/(const month& m, const weekday_indexed& wdi) noexcept;
Returns: {m, wdi}.
constexpr month_weekday operator/(int m, const weekday_indexed& wdi) noexcept;
Returns: month(m) / wdi.
constexpr month_weekday operator/(const weekday_indexed& wdi, const month& m) noexcept;
Returns: m / wdi.
constexpr month_weekday operator/(const weekday_indexed& wdi, int m) noexcept;
Returns: month(m) / wdi.
constexpr month_weekday_last operator/(const month& m, const weekday_last& wdl) noexcept;
Returns: {m, wdl}.
constexpr month_weekday_last operator/(int m, const weekday_last& wdl) noexcept;
Returns: month(m) / wdl.
constexpr month_weekday_last operator/(const weekday_last& wdl, const month& m) noexcept;
Returns: m / wdl.
constexpr month_weekday_last operator/(const weekday_last& wdl, int m) noexcept;
Returns: month(m) / wdl.
constexpr year_month_day operator/(const year_month& ym, const day& d) noexcept;
Returns: {ym.year(), ym.month(), d}.
constexpr year_month_day operator/(const year_month& ym, int d) noexcept;
Returns: ym / day(d).
constexpr year_month_day operator/(const year& y, const month_day& md) noexcept;
Returns: y / md.month() / md.day().
constexpr year_month_day operator/(int y, const month_day& md) noexcept;
Returns: year(y) / md.
constexpr year_month_day operator/(const month_day& md, const year& y) noexcept;
Returns: y / md.
constexpr year_month_day operator/(const month_day& md, int y) noexcept;
Returns: year(y) / md.
constexpr year_month_day_last operator/(const year_month& ym, last_spec) noexcept;
Returns: {ym.year(), month_day_last{ym.month()}}.
constexpr year_month_day_last operator/(const year& y, const month_day_last& mdl) noexcept;
Returns: {y, mdl}.
constexpr year_month_day_last operator/(int y, const month_day_last& mdl) noexcept;
Returns: year(y) / mdl.
constexpr year_month_day_last operator/(const month_day_last& mdl, const year& y) noexcept;
Returns: y / mdl.
constexpr year_month_day_last operator/(const month_day_last& mdl, int y) noexcept;
Returns: year(y) / mdl.
constexpr year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) noexcept;
Returns: {ym.year(), ym.month(), wdi}.
constexpr year_month_weekday operator/(const year& y, const month_weekday& mwd) noexcept;
Returns: {y, mwd.month(), mwd.weekday_indexed()}.
constexpr year_month_weekday operator/(int y, const month_weekday& mwd) noexcept;
Returns: year(y) / mwd.
constexpr year_month_weekday operator/(const month_weekday& mwd, const year& y) noexcept;
Returns: y / mwd.
constexpr year_month_weekday operator/(const month_weekday& mwd, int y) noexcept;
Returns: year(y) / mwd.
constexpr year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) noexcept;
Returns: {ym.year(), ym.month(), wdl}.
constexpr year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) noexcept;
Returns: {y, mwdl.month(), mwdl.weekday_last()}.
constexpr year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) noexcept;
Returns: year(y) / mwdl.
constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) noexcept;
Returns: y / mwdl.
constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) noexcept;
Returns: year(y) / mwdl.

30.9 Class template hh_mm_ss [time.hms]

30.9.1 Overview [time.hms.overview]

namespace std::chrono { template<class Duration> class hh_mm_ss { public: static constexpr unsigned fractional_width = see below; using precision = see below; constexpr hh_mm_ss() noexcept : hh_mm_ss{Duration::zero()} {} constexpr explicit hh_mm_ss(Duration d); constexpr bool is_negative() const noexcept; constexpr chrono::hours hours() const noexcept; constexpr chrono::minutes minutes() const noexcept; constexpr chrono::seconds seconds() const noexcept; constexpr precision subseconds() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; private: bool is_neg; // exposition only chrono::hours h; // exposition only chrono::minutes m; // exposition only chrono::seconds s; // exposition only precision ss; // exposition only }; }
The hh_mm_ss class template splits a duration into a multi-field time structure hours:minutes:seconds and possibly subseconds, where subseconds will be a duration unit based on a non-positive power of 10.
The Duration template parameter dictates the precision to which the time is split.
A hh_mm_ss models negative durations with a distinct is_negative getter that returns true when the input duration is negative.
The individual duration fields always return non-negative durations even when is_negative() indicates the structure is representing a negative duration.
If Duration is not a specialization of duration, the program is ill-formed.

30.9.2 Members [time.hms.members]

static constexpr unsigned fractional_width = see below;
fractional_width is the number of fractional decimal digits represented by precision.
fractional_width has the value of the smallest possible integer in the range [0, 18] such that precision will exactly represent all values of Duration.
If no such value of fractional_width exists, then fractional_width is 6.
[Example 1: 
See Table 127 for some durations, the resulting fractional_width, and the formatted fractional second output of Duration{1}.
Table 127 — Examples for fractional_width[tab:time.hms.width]
Duration
fractional_width
Formatted fractional second output
hours, minutes, and seconds
0
milliseconds
3
0.001
microseconds
6
0.000001
nanoseconds
9
0.000000001
duration<int, ratio<1, 2>>
1
0.5
duration<int, ratio<1, 3>>
6
0.333333
duration<int, ratio<1, 4>>
2
0.25
duration<int, ratio<1, 5>>
1
0.2
duration<int, ratio<1, 6>>
6
0.166666
duration<int, ratio<1, 7>>
6
0.142857
duration<int, ratio<1, 8>>
3
0.125
duration<int, ratio<1, 9>>
6
0.111111
duration<int, ratio<1, 10>>
1
0.1
duration<int, ratio<756, 625>>
4
0.2096
— end example]
using precision = see below;
precision is duration<common_type_t<Duration::rep, seconds::rep>, ratio<1, >>
constexpr explicit hh_mm_ss(Duration d);
Effects: Constructs an object of type hh_mm_ss which represents the Duration d with precision precision.
  • Initializes is_neg with d < Duration​::​zero().
  • Initializes h with duration_cast<chrono​::​hours>(abs(d)).
  • Initializes m with duration_cast<chrono​::​minutes>(abs(d) - hours()).
  • Initializes s with duration_cast<chrono​::​seconds>(abs(d) - hours() - minutes()).
  • If treat_as_floating_point_v<precision​::​rep> is true, initializes ss with abs(d) - hours() - minutes() - seconds().
    Otherwise, initializes ss with duration_cast<precision>(abs(d) - hours() - minutes() - seconds()).
[Note 1: 
When precision​::​rep is integral and precision​::​period is ratio<1>, subseconds() always returns a value equal to 0s.
— end note]
Postconditions: If treat_as_floating_point_v<precision​::​rep> is true, to_duration() returns d, otherwise to_duration() returns duration_cast<precision>(d).
constexpr bool is_negative() const noexcept;
Returns: is_neg.
constexpr chrono::hours hours() const noexcept;
Returns: h.
constexpr chrono::minutes minutes() const noexcept;
Returns: m.
constexpr chrono::seconds seconds() const noexcept;
Returns: s.
constexpr precision subseconds() const noexcept;
Returns: ss.
constexpr precision to_duration() const noexcept;
Returns: If is_neg, returns -(h + m + s + ss), otherwise returns h + m + s + ss.
constexpr explicit operator precision() const noexcept;
Returns: to_duration().

30.9.3 Non-members [time.hms.nonmembers]

template<class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const hh_mm_ss<Duration>& hms);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%T}"), hms);
[Example 1: for (auto ms : {-4083007ms, 4083007ms, 65745123ms}) { hh_mm_ss hms{ms}; cout << hms << '\n'; } cout << hh_mm_ss{65745s} << '\n';
Produces the output (assuming the "C" locale): -01:08:03.007 01:08:03.007 18:15:45.123 18:15:45
— end example]

30.10 12/24 hours functions [time.12]

These functions aid in translating between a 12h format time of day and a 24h format time of day.
constexpr bool is_am(const hours& h) noexcept;
Returns: 0h <= h && h <= 11h.
constexpr bool is_pm(const hours& h) noexcept;
Returns: 12h <= h && h <= 23h.
constexpr hours make12(const hours& h) noexcept;
Returns: The 12-hour equivalent of h in the range [1h, 12h].
If h is not in the range [0h, 23h], the value returned is unspecified.
constexpr hours make24(const hours& h, bool is_pm) noexcept;
Returns: If is_pm is false, returns the 24-hour equivalent of h in the range [0h, 11h], assuming h represents an ante meridiem hour.
Otherwise, returns the 24-hour equivalent of h in the range [12h, 23h], assuming h represents a post meridiem hour.
If h is not in the range [1h, 12h], the value returned is unspecified.

30.11 Time zones [time.zone]

30.11.1 General [time.zone.general]

[time.zone] describes an interface for accessing the IANA Time Zone Database[bib] that interoperates with sys_time and local_time.
This interface provides time zone support to both the civil calendar types ([time.cal]) and to user-defined calendars.

30.11.2 Time zone database [time.zone.db]

30.11.2.1 Class tzdb [time.zone.db.tzdb]

namespace std::chrono { struct tzdb { string version; vector<time_zone> zones; vector<time_zone_link> links; vector<leap_second> leap_seconds; const time_zone* locate_zone(string_view tz_name) const; const time_zone* current_zone() const; }; }
Each vector in a tzdb object is sorted to enable fast lookup.
const time_zone* locate_zone(string_view tz_name) const;
Returns:
  • If zones contains an element tz for which tz.name() == tz_name, a pointer to tz;
  • otherwise, if links contains an element tz_l for which tz_l.name() == tz_name, then a pointer to the element tz of zones for which tz.name() == tz_l.target().
[Note 1: 
A time_zone_link specifies an alternative name for a time_zone.
— end note]
Throws: If a const time_zone* cannot be found as described in the Returns: element, throws a runtime_error.
[Note 2: 
On non-exceptional return, the return value is always a pointer to a valid time_zone.
— end note]
const time_zone* current_zone() const;
Returns: A pointer to the time zone which the computer has set as its local time zone.

30.11.2.2 Class tzdb_list [time.zone.db.list]

namespace std::chrono { class tzdb_list { public: tzdb_list(const tzdb_list&) = delete; tzdb_list& operator=(const tzdb_list&) = delete; // unspecified additional constructors class const_iterator; const tzdb& front() const noexcept; const_iterator erase_after(const_iterator p); const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; }; }
The tzdb_list database is a singleton; the unique object of type tzdb_list can be accessed via the get_tzdb_list() function.
[Note 1: 
This access is only needed for those applications that need to have long uptimes and have a need to update the time zone database while running.
Other applications can implicitly access the front() of this list via the read-only namespace scope functions get_tzdb(), locate_zone(), and current_zone().
— end note]
The tzdb_list object contains a list of tzdb objects.
tzdb_list​::​const_iterator is a constant iterator which meets the Cpp17ForwardIterator requirements and has a value type of tzdb.
const tzdb& front() const noexcept;
Synchronization: This operation is thread-safe with respect to reload_tzdb().
[Note 2: 
reload_tzdb() pushes a new tzdb onto the front of this container.
— end note]
Returns: A reference to the first tzdb in the container.
const_iterator erase_after(const_iterator p);
Preconditions: The iterator following p is dereferenceable.
Effects: Erases the tzdb referred to by the iterator following p.
Postconditions: No pointers, references, or iterators are invalidated except those referring to the erased tzdb.
[Note 3: 
It is not possible to erase the tzdb referred to by begin().
— end note]
Returns: An iterator pointing to the element following the one that was erased, or end() if no such element exists.
Throws: Nothing.
const_iterator begin() const noexcept;
Returns: An iterator referring to the first tzdb in the container.
const_iterator end() const noexcept;
Returns: An iterator referring to the position one past the last tzdb in the container.
const_iterator cbegin() const noexcept;
Returns: begin().
const_iterator cend() const noexcept;
Returns: end().

30.11.2.3 Time zone database access [time.zone.db.access]

tzdb_list& get_tzdb_list();
Effects: If this is the first access to the time zone database, initializes the database.
If this call initializes the database, the resulting database will be a tzdb_list holding a single initialized tzdb.
Synchronization: It is safe to call this function from multiple threads at one time.
Returns: A reference to the database.
Throws: runtime_error if for any reason a reference cannot be returned to a valid tzdb_list containing one or more valid tzdbs.
const tzdb& get_tzdb();
Returns: get_tzdb_list().front().
const time_zone* locate_zone(string_view tz_name);
Returns: get_tzdb().locate_zone(tz_name).
[Note 1: 
The time zone database will be initialized if this is the first reference to the database.
— end note]
const time_zone* current_zone();
Returns: get_tzdb().current_zone().

30.11.2.4 Remote time zone database support [time.zone.db.remote]

The local time zone database is that supplied by the implementation when the program first accesses the database, for example via current_zone().
While the program is running, the implementation may choose to update the time zone database.
This update shall not impact the program in any way unless the program calls the functions in this subclause.
This potentially updated time zone database is referred to as the remote time zone database.
const tzdb& reload_tzdb();
Effects: This function first checks the version of the remote time zone database.
If the versions of the local and remote databases are the same, there are no effects.
Otherwise the remote database is pushed to the front of the tzdb_list accessed by get_tzdb_list().
Synchronization: This function is thread-safe with respect to get_tzdb_list().front() and get_tzdb_list().erase_after().
Postconditions: No pointers, references, or iterators are invalidated.
Returns: get_tzdb_list().front().
Throws: runtime_error if for any reason a reference cannot be returned to a valid tzdb.
string remote_version();
Returns: The latest remote database version.
[Note 1: 
This can be compared with get_tzdb().version to discover if the local and remote databases are equivalent.
— end note]

30.11.3 Exception classes [time.zone.exception]

30.11.3.1 Class nonexistent_local_time [time.zone.exception.nonexist]

namespace std::chrono { class nonexistent_local_time : public runtime_error { public: template<class Duration> nonexistent_local_time(const local_time<Duration>& tp, const local_info& i); }; }
nonexistent_local_time is thrown when an attempt is made to convert a non-existent local_time to a sys_time without specifying choose​::​earliest or choose​::​latest.
template<class Duration> nonexistent_local_time(const local_time<Duration>& tp, const local_info& i);
Preconditions: i.result == local_info​::​nonexistent is true.
Effects: Initializes the base class with a sequence of char equivalent to that produced by os.str() initialized as shown below: ostringstream os; os << tp << " is in a gap between\n" << local_seconds{i.first.end.time_since_epoch()} + i.first.offset << ' ' << i.first.abbrev << " and\n" << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' ' << i.second.abbrev << " which are both equivalent to\n" << i.first.end << " UTC";
[Example 1: #include <chrono> #include <iostream> int main() { using namespace std::chrono; try { auto zt = zoned_time{"America/New_York", local_days{Sunday[2]/March/2016} + 2h + 30min}; } catch (const nonexistent_local_time& e) { std::cout << e.what() << '\n'; } }
Produces the output:
2016-03-13 02:30:00 is in a gap between
2016-03-13 02:00:00 EST and
2016-03-13 03:00:00 EDT which are both equivalent to
2016-03-13 07:00:00 UTC
— end example]

30.11.3.2 Class ambiguous_local_time [time.zone.exception.ambig]

namespace std::chrono { class ambiguous_local_time : public runtime_error { public: template<class Duration> ambiguous_local_time(const local_time<Duration>& tp, const local_info& i); }; }
ambiguous_local_time is thrown when an attempt is made to convert an ambiguous local_time to a sys_time without specifying choose​::​earliest or choose​::​latest.
template<class Duration> ambiguous_local_time(const local_time<Duration>& tp, const local_info& i);
Preconditions: i.result == local_info​::​ambiguous is true.
Effects: Initializes the base class with a sequence of char equivalent to that produced by os.str() initialized as shown below: ostringstream os; os << tp << " is ambiguous. It could be\n" << tp << ' ' << i.first.abbrev << " == " << tp - i.first.offset << " UTC or\n" << tp << ' ' << i.second.abbrev << " == " << tp - i.second.offset << " UTC";
[Example 1: #include <chrono> #include <iostream> int main() { using namespace std::chrono; try { auto zt = zoned_time{"America/New_York", local_days{Sunday[1]/November/2016} + 1h + 30min}; } catch (const ambiguous_local_time& e) { std::cout << e.what() << '\n'; } }
Produces the output:
2016-11-06 01:30:00 is ambiguous.  It could be
2016-11-06 01:30:00 EDT == 2016-11-06 05:30:00 UTC or
2016-11-06 01:30:00 EST == 2016-11-06 06:30:00 UTC
— end example]

30.11.4 Information classes [time.zone.info]

30.11.4.1 Class sys_info [time.zone.info.sys]

namespace std::chrono { struct sys_info { sys_seconds begin; sys_seconds end; seconds offset; minutes save; string abbrev; }; }
A sys_info object can be obtained from the combination of a time_zone and either a sys_time or local_time.
It can also be obtained from a zoned_time, which is effectively a pair of a time_zone and sys_time.
[Note 1: 
This type provides a low-level interface to time zone information.
Typical conversions from sys_time to local_time will use this class implicitly, not explicitly.
— end note]
The begin and end data members indicate that, for the associated time_zone and time_point, the offset and abbrev are in effect in the range [begin, end).
This information can be used to efficiently iterate the transitions of a time_zone.
The offset data member indicates the UTC offset in effect for the associated time_zone and time_point.
The relationship between local_time and sys_time is: offset = local_time - sys_time
The save data member is extra information not normally needed for conversion between local_time and sys_time.
If save != 0min, this sys_info is said to be on “daylight saving” time, and offset - save suggests what offset this time_zone might use if it were off daylight saving time.
However, this information should not be taken as authoritative.
The only sure way to get such information is to query the time_zone with a time_point that returns a sys_info where save == 0min.
There is no guarantee what time_point might return such a sys_info except that it is guaranteed not to be in the range [begin, end) (if save != 0min for this sys_info).
The abbrev data member indicates the current abbreviation used for the associated time_zone and time_point.
Abbreviations are not unique among the time_zones, and so one cannot reliably map abbreviations back to a time_zone and UTC offset.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_info& r);
Effects: Streams out the sys_info object r in an unspecified format.
Returns: os.

30.11.4.2 Class local_info [time.zone.info.local]

namespace std::chrono { struct local_info { static constexpr int unique = 0; static constexpr int nonexistent = 1; static constexpr int ambiguous = 2; int result; sys_info first; sys_info second; }; }
[Note 1: 
This type provides a low-level interface to time zone information.
Typical conversions from local_time to sys_time will use this class implicitly, not explicitly.
— end note]
Describes the result of converting a local_time to a sys_time as follows:
  • When a local_time to sys_time conversion is unique, result == unique, first will be filled out with the correct sys_info, and second will be zero-initialized.
  • If the conversion stems from a nonexistent local_time then result == nonexistent, first will be filled out with the sys_info that ends just prior to the local_time, and second will be filled out with the sys_info that begins just after the local_time.
  • If the conversion stems from an ambiguous local_time, then result == ambiguous, first will be filled out with the sys_info that ends just after the local_time, and second will be filled out with the sys_info that starts just before the local_time.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_info& r);
Effects: Streams out the local_info object r in an unspecified format.
Returns: os.

30.11.5 Class time_zone [time.zone.timezone]

30.11.5.1 Overview [time.zone.overview]

namespace std::chrono { class time_zone { public: time_zone(time_zone&&) = default; time_zone& operator=(time_zone&&) = default; // unspecified additional constructors string_view name() const noexcept; template<class Duration> sys_info get_info(const sys_time<Duration>& st) const; template<class Duration> local_info get_info(const local_time<Duration>& tp) const; template<class Duration> sys_time<common_type_t<Duration, seconds>> to_sys(const local_time<Duration>& tp) const; template<class Duration> sys_time<common_type_t<Duration, seconds>> to_sys(const local_time<Duration>& tp, choose z) const; template<class Duration> local_time<common_type_t<Duration, seconds>> to_local(const sys_time<Duration>& tp) const; }; }
A time_zone represents all time zone transitions for a specific geographic area.
time_zone construction is unspecified, and performed as part of database initialization.
[Note 1: 
const time_zone objects can be accessed via functions such as locate_zone.
— end note]

30.11.5.2 Member functions [time.zone.members]

string_view name() const noexcept;
Returns: The name of the time_zone.
[Example 1: 
"America/New_York".
— end example]
template<class Duration> sys_info get_info(const sys_time<Duration>& st) const;
Returns: A sys_info i for which st is in the range [i.begin, i.end).
template<class Duration> local_info get_info(const local_time<Duration>& tp) const;
Returns: A local_info for tp.
template<class Duration> sys_time<common_type_t<Duration, seconds>> to_sys(const local_time<Duration>& tp) const;
Returns: A sys_time that is at least as fine as seconds, and will be finer if the argument tp has finer precision.
This sys_time is the UTC equivalent of tp according to the rules of this time_zone.
Throws: If the conversion from tp to a sys_time is ambiguous, throws ambiguous_local_time.
If the tp represents a non-existent time between two UTC time_points, throws nonexistent_local_time.
template<class Duration> sys_time<common_type_t<Duration, seconds>> to_sys(const local_time<Duration>& tp, choose z) const;
Returns: A sys_time that is at least as fine as seconds, and will be finer if the argument tp has finer precision.
This sys_time is the UTC equivalent of tp according to the rules of this time_zone.
If the conversion from tp to a sys_time is ambiguous, returns the earlier sys_time if z == choose​::​earliest, and returns the later sys_time if z == choose​::​latest.
If the tp represents a non-existent time between two UTC time_points, then the two UTC time_points will be the same, and that UTC time_point will be returned.
template<class Duration> local_time<common_type_t<Duration, seconds>> to_local(const sys_time<Duration>& tp) const;
Returns: The local_time associated with tp and this time_zone.

30.11.5.3 Non-member functions [time.zone.nonmembers]

bool operator==(const time_zone& x, const time_zone& y) noexcept;
Returns: x.name() == y.name().
strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept;
Returns: x.name() <=> y.name().

30.11.6 Class template zoned_traits [time.zone.zonedtraits]

namespace std::chrono { template<class T> struct zoned_traits {}; }
zoned_traits provides a means for customizing the behavior of zoned_time<Duration, TimeZonePtr> for the zoned_time default constructor, and constructors taking string_view.
A specialization for const time_zone* is provided by the implementation: namespace std::chrono { template<> struct zoned_traits<const time_zone*> { static const time_zone* default_zone(); static const time_zone* locate_zone(string_view name); }; }
static const time_zone* default_zone();
Returns: std​::​chrono​::​locate_zone("UTC").
static const time_zone* locate_zone(string_view name);
Returns: std​::​chrono​::​locate_zone(name).

30.11.7 Class template zoned_time [time.zone.zonedtime]

30.11.7.1 Overview [time.zone.zonedtime.overview]

namespace std::chrono { template<class Duration, class TimeZonePtr = const time_zone*> class zoned_time { public: using duration = common_type_t<Duration, seconds>; private: TimeZonePtr zone_; // exposition only sys_time<duration> tp_; // exposition only using traits = zoned_traits<TimeZonePtr>; // exposition only public: zoned_time(); zoned_time(const zoned_time&) = default; zoned_time& operator=(const zoned_time&) = default; zoned_time(const sys_time<Duration>& st); explicit zoned_time(TimeZonePtr z); explicit zoned_time(string_view name); template<class Duration2> zoned_time(const zoned_time<Duration2, TimeZonePtr>& y); zoned_time(TimeZonePtr z, const sys_time<Duration>& st); zoned_time(string_view name, const sys_time<Duration>& st); zoned_time(TimeZonePtr z, const local_time<Duration>& tp); zoned_time(string_view name, const local_time<Duration>& tp); zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c); zoned_time(string_view name, const local_time<Duration>& tp, choose c); template<class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y); template<class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y, choose); template<class Duration2, class TimeZonePtr2> zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y); template<class Duration2, class TimeZonePtr2> zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y, choose c); zoned_time& operator=(const sys_time<Duration>& st); zoned_time& operator=(const local_time<Duration>& lt); operator sys_time<duration>() const; explicit operator local_time<duration>() const; TimeZonePtr get_time_zone() const; local_time<duration> get_local_time() const; sys_time<duration> get_sys_time() const; sys_info get_info() const; }; zoned_time() -> zoned_time<seconds>; template<class Duration> zoned_time(sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>>; template<class TimeZonePtrOrName> using time-zone-representation = // exposition only conditional_t<is_convertible_v<TimeZonePtrOrName, string_view>, const time_zone*, remove_cvref_t<TimeZonePtrOrName>>; template<class TimeZonePtrOrName> zoned_time(TimeZonePtrOrName&&) -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>; template<class TimeZonePtrOrName, class Duration> zoned_time(TimeZonePtrOrName&&, sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>, time-zone-representation<TimeZonePtrOrName>>; template<class TimeZonePtrOrName, class Duration> zoned_time(TimeZonePtrOrName&&, local_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>, time-zone-representation<TimeZonePtrOrName>>; template<class Duration, class TimeZonePtrOrName, class TimeZonePtr2> zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>, time-zone-representation<TimeZonePtrOrName>>; }
zoned_time represents a logical pairing of a time_zone and a time_point with precision Duration.
zoned_time<Duration> maintains the invariant that it always refers to a valid time zone and represents a point in time that exists and is not ambiguous in that time zone.
If Duration is not a specialization of chrono​::​duration, the program is ill-formed.
Every constructor of zoned_time that accepts a string_view as its first parameter does not participate in class template argument deduction ([over.match.class.deduct]).

30.11.7.2 Constructors [time.zone.zonedtime.ctor]

zoned_time();
Constraints: traits​::​default_zone() is a well-formed expression.
Effects: Initializes zone_ with traits​::​default_zone() and default constructs tp_.
zoned_time(const sys_time<Duration>& st);
Constraints: traits​::​default_zone() is a well-formed expression.
Effects: Initializes zone_ with traits​::​default_zone() and tp_ with st.
explicit zoned_time(TimeZonePtr z);
Preconditions: z refers to a time zone.
Effects: Initializes zone_ with std​::​move(z) and default constructs tp_.
explicit zoned_time(string_view name);
Constraints: traits​::​locate_zone(string_view{}) is a well-formed expression and zoned_time is constructible from the return type of traits​::​locate_zone(string_view{}).
Effects: Initializes zone_ with traits​::​locate_zone(name) and default constructs tp_.
template<class Duration2> zoned_time(const zoned_time<Duration2, TimeZonePtr>& y);
Constraints: is_convertible_v<sys_time<Duration2>, sys_time<Duration>> is true.
Effects: Initializes zone_ with y.zone_ and tp_ with y.tp_.
zoned_time(TimeZonePtr z, const sys_time<Duration>& st);
Preconditions: z refers to a time zone.
Effects: Initializes zone_ with std​::​move(z) and tp_ with st.
zoned_time(string_view name, const sys_time<Duration>& st);
Constraints: zoned_time is constructible from the return type of traits​::​locate_zone(name) and st.
Effects: Equivalent to construction with {traits​::​locate_zone(name), st}.
zoned_time(TimeZonePtr z, const local_time<Duration>& tp);
Constraints: is_convertible_v< decltype(declval<TimeZonePtr&>()->to_sys(local_time<Duration>{})), sys_time<duration>> is true.
Preconditions: z refers to a time zone.
Effects: Initializes zone_ with std​::​move(z) and tp_ with zone_->to_sys(tp).
zoned_time(string_view name, const local_time<Duration>& tp);
Constraints: zoned_time is constructible from the return type of traits​::​locate_zone(name) and tp.
Effects: Equivalent to construction with {traits​::​locate_zone(name), tp}.
zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c);
Constraints: is_convertible_v< decltype(declval<TimeZonePtr&>()->to_sys(local_time<Duration>{}, choose::earliest)), sys_time<duration>> is true.
Preconditions: z refers to a time zone.
Effects: Initializes zone_ with std​::​move(z) and tp_ with zone_->to_sys(tp, c).
zoned_time(string_view name, const local_time<Duration>& tp, choose c);
Constraints: zoned_time is constructible from the return type of traits​::​locate_zone(name), local_time<Duration>, and choose.
Effects: Equivalent to construction with {traits​::​locate_zone(name), tp, c}.
template<class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y);
Constraints: is_convertible_v<sys_time<Duration2>, sys_time<Duration>> is true.
Preconditions: z refers to a valid time zone.
Effects: Initializes zone_ with std​::​move(z) and tp_ with y.tp_.
template<class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y, choose);
Constraints: is_convertible_v<sys_time<Duration2>, sys_time<Duration>> is true.
Preconditions: z refers to a valid time zone.
Effects: Equivalent to construction with {z, y}.
[Note 1: 
The choose parameter has no effect.
— end note]
template<class Duration2, class TimeZonePtr2> zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y);
Constraints: zoned_time is constructible from the return type of traits​::​locate_zone(name) and the type zoned_time<Duration2, TimeZonePtr2>.
Effects: Equivalent to construction with {traits​::​locate_zone(name), y}.
template<class Duration2, class TimeZonePtr2> zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y, choose c);
Constraints: zoned_time is constructible from the return type of traits​::​locate_zone(name), the type zoned_time<Duration2, TimeZonePtr2>, and the type choose.
Effects: Equivalent to construction with {traits​::​locate_zone(name), y, c}.
[Note 2: 
The choose parameter has no effect.
— end note]

30.11.7.3 Member functions [time.zone.zonedtime.members]

zoned_time& operator=(const sys_time<Duration>& st);
Effects: After assignment, get_sys_time() == st.
This assignment has no effect on the return value of get_time_zone().
Returns: *this.
zoned_time& operator=(const local_time<Duration>& lt);
Effects: After assignment, get_local_time() == lt.
This assignment has no effect on the return value of get_time_zone().
Returns: *this.
operator sys_time<duration>() const;
Returns: get_sys_time().
explicit operator local_time<duration>() const;
Returns: get_local_time().
TimeZonePtr get_time_zone() const;
Returns: zone_.
local_time<duration> get_local_time() const;
Returns: zone_->to_local(tp_).
sys_time<duration> get_sys_time() const;
Returns: tp_.
sys_info get_info() const;
Returns: zone_->get_info(tp_).

30.11.7.4 Non-member functions [time.zone.zonedtime.nonmembers]

template<class Duration1, class Duration2, class TimeZonePtr> bool operator==(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y);
Returns: x.zone_ == y.zone_ && x.tp_ == y.tp_.
template<class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const zoned_time<Duration, TimeZonePtr>& t);
Effects: Equivalent to: return os << format(os.getloc(), STATICALLY-WIDEN<charT>("{:L%F %T %Z}"), t);

30.11.8 Class leap_second [time.zone.leap]

30.11.8.1 Overview [time.zone.leap.overview]

namespace std::chrono { class leap_second { public: leap_second(const leap_second&) = default; leap_second& operator=(const leap_second&) = default; // unspecified additional constructors constexpr sys_seconds date() const noexcept; constexpr seconds value() const noexcept; }; }
Objects of type leap_second representing the date and value of the leap second insertions are constructed and stored in the time zone database when initialized.
[Example 1: for (auto& l : get_tzdb().leap_seconds) if (l <= sys_days{2018y/March/17d}) cout << l.date() << ": " << l.value() << '\n';
Produces the output:
1972-07-01 00:00:00: 1s
1973-01-01 00:00:00: 1s
1974-01-01 00:00:00: 1s
1975-01-01 00:00:00: 1s
1976-01-01 00:00:00: 1s
1977-01-01 00:00:00: 1s
1978-01-01 00:00:00: 1s
1979-01-01 00:00:00: 1s
1980-01-01 00:00:00: 1s
1981-07-01 00:00:00: 1s
1982-07-01 00:00:00: 1s
1983-07-01 00:00:00: 1s
1985-07-01 00:00:00: 1s
1988-01-01 00:00:00: 1s
1990-01-01 00:00:00: 1s
1991-01-01 00:00:00: 1s
1992-07-01 00:00:00: 1s
1993-07-01 00:00:00: 1s
1994-07-01 00:00:00: 1s
1996-01-01 00:00:00: 1s
1997-07-01 00:00:00: 1s
1999-01-01 00:00:00: 1s
2006-01-01 00:00:00: 1s
2009-01-01 00:00:00: 1s
2012-07-01 00:00:00: 1s
2015-07-01 00:00:00: 1s
2017-01-01 00:00:00: 1s
— end example]

30.11.8.2 Member functions [time.zone.leap.members]

constexpr sys_seconds date() const noexcept;
Returns: The date and time at which the leap second was inserted.
constexpr seconds value() const noexcept;
Returns: +1s to indicate a positive leap second or -1s to indicate a negative leap second.
[Note 1: 
All leap seconds inserted up through 2022 were positive leap seconds.
— end note]

30.11.8.3 Non-member functions [time.zone.leap.nonmembers]

constexpr bool operator==(const leap_second& x, const leap_second& y) noexcept;
Returns: x.date() == y.date().
constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y) noexcept;
Returns: x.date() <=> y.date().
template<class Duration> constexpr bool operator==(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: x.date() == y.
template<class Duration> constexpr bool operator<(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: x.date() < y.
template<class Duration> constexpr bool operator<(const sys_time<Duration>& x, const leap_second& y) noexcept;
Returns: x < y.date().
template<class Duration> constexpr bool operator>(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: y < x.
template<class Duration> constexpr bool operator>(const sys_time<Duration>& x, const leap_second& y) noexcept;
Returns: y < x.
template<class Duration> constexpr bool operator<=(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: !(y < x).
template<class Duration> constexpr bool operator<=(const sys_time<Duration>& x, const leap_second& y) noexcept;
Returns: !(y < x).
template<class Duration> constexpr bool operator>=(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: !(x < y).
template<class Duration> constexpr bool operator>=(const sys_time<Duration>& x, const leap_second& y) noexcept;
Returns: !(x < y).
template<class Duration> requires three_way_comparable_with<sys_seconds, sys_time<Duration>> constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y) noexcept;
Returns: x.date() <=> y.

30.12 Formatting [time.format]

Each formatter ([format.formatter]) specialization in the chrono library ([time.syn]) meets the Formatter requirements ([formatter.requirements]).
The parse member functions of these formatters interpret the format specification as a chrono-format-spec according to the following syntax:
chrono-format-spec:
fill-and-align width precision L chrono-specs
chrono-specs:
conversion-spec
chrono-specs conversion-spec
chrono-specs literal-char
literal-char:
any character other than {, }, or %
conversion-spec:
% modifier type
modifier: one of
E O
type: one of
a A b B c C d D e F g G h H I j m M n
p q Q r R S t T u U V w W x X y Y z Z %
The productions fill-and-align, width, and precision are described in [format.string].
Giving a precision specification in the chrono-format-spec is valid only for types that are specializations of std​::​chrono​::​duration for which the nested typedef-name rep denotes a floating-point type.
For all other types, an exception of type format_error is thrown if the chrono-format-spec contains a precision specification.
All ordinary multibyte characters represented by literal-char are copied unchanged to the output.
A formatting locale is an instance of locale used by a formatting function, defined as
  • the "C" locale if the L option is not present in chrono-format-spec, otherwise
  • the locale passed to the formatting function if any, otherwise
  • the global locale.
Each conversion specifier conversion-spec is replaced by appropriate characters as described in Table 128; the formats specified in ISO 8601-1:2019 shall be used where so described.
Some of the conversion specifiers depend on the formatting locale.
If the string literal encoding is a Unicode encoding form and the locale is among an implementation-defined set of locales, each replacement that depends on the locale is performed as if the replacement character sequence is converted to the string literal encoding.
If the formatted object does not contain the information the conversion specifier refers to, an exception of type format_error is thrown.
The result of formatting a std​::​chrono​::​duration instance holding a negative value, or an hh_mm_ss object h for which h.is_negative() is true, is equivalent to the output of the corresponding positive value, with a STATICALLY-WIDEN<charT>("-") character sequence placed before the replacement of the initial conversion specifier.
[Example 1: cout << format("{:%T}", -10'000s); // prints: -02:46:40 cout << format("{:%H:%M:%S}", -10'000s); // prints: -02:46:40 cout << format("minutes {:%M, hours %H, seconds %S}", -10'000s); // prints: minutes -46, hours 02, seconds 40 — end example]
Unless explicitly requested, the result of formatting a chrono type does not contain time zone abbreviation and time zone offset information.
If the information is available, the conversion specifiers %Z and %z will format this information (respectively).
[Note 1: 
If the information is not available and a %Z or %z conversion specifier appears in the chrono-format-spec, an exception of type format_error is thrown, as described above.
— end note]
If the type being formatted does not contain the information that the format flag needs, an exception of type format_error is thrown.
[Example 2: 
A duration does not contain enough information to format as a weekday.
— end example]
However, if a flag refers to a “time of day” (e.g., %H, %I, %p, etc.)
, then a specialization of duration is interpreted as the time of day elapsed since midnight.
Table 128 — Meaning of conversion specifiers [tab:time.format.spec]
Specifier
Replacement
%a
The locale's abbreviated weekday name.
If the value does not contain a valid weekday, an exception of type format_error is thrown.
%A
The locale's full weekday name.
If the value does not contain a valid weekday, an exception of type format_error is thrown.
%b
The locale's abbreviated month name.
If the value does not contain a valid month, an exception of type format_error is thrown.
%B
The locale's full month name.
If the value does not contain a valid month, an exception of type format_error is thrown.
%c
The locale's date and time representation.
The modified command %Ec produces the locale's alternate date and time representation.
%C
The year divided by 100 using floored division.
If the result is a single decimal digit, it is prefixed with 0.
The modified command %EC produces the locale's alternative representation of the century.
%d
The day of month as a decimal number.
If the result is a single decimal digit, it is prefixed with 0.
The modified command %Od produces the locale's alternative representation.
%D
Equivalent to %m/%d/%y.
%e
The day of month as a decimal number.
If the result is a single decimal digit, it is prefixed with a space.
The modified command %Oe produces the locale's alternative representation.
%F
Equivalent to %Y-%m-%d.
%g
The last two decimal digits of the calendar year as specified in ISO 8601-1:2019 for the week calendar.
If the result is a single digit it is prefixed by 0.
%G
The calendar year as a decimal number, as specified in ISO 8601-1:2019 for the week calendar.
If the result is less than four digits it is left-padded with 0 to four digits.
%h
Equivalent to %b.
%H
The hour (24-hour clock) as a decimal number.
If the result is a single digit, it is prefixed with 0.
The modified command %OH produces the locale's alternative representation.
%I
The hour (12-hour clock) as a decimal number.
If the result is a single digit, it is prefixed with 0.
The modified command %OI produces the locale's alternative representation.
%j
If the type being formatted is a specialization of duration, the decimal number of days without padding.
Otherwise, the day of the year as a decimal number.
January 1 is 001.
If the result is less than three digits, it is left-padded with 0 to three digits.
%m
The month as a decimal number.
Jan is 01.
If the result is a single digit, it is prefixed with 0.
The modified command %Om produces the locale's alternative representation.
%M
The minute as a decimal number.
If the result is a single digit, it is prefixed with 0.
The modified command %OM produces the locale's alternative representation.
%n
A new-line character.
%p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock.
%q
The duration's unit suffix as specified in [time.duration.io].
%Q
The duration's numeric value (as if extracted via .count()).
%r
The locale's 12-hour clock time.
%R
Equivalent to %H:%M.
%S
Seconds as a decimal number.
If the number of seconds is less than 10, the result is prefixed with 0.
If the precision of the input cannot be exactly represented with seconds, then the format is a decimal floating-point number with a fixed format and a precision matching that of the precision of the input (or to a microseconds precision if the conversion to floating-point decimal seconds cannot be made within 18 fractional digits).
The character for the decimal point is localized according to the locale.
The modified command %OS produces the locale's alternative representation.
%t
A horizontal-tab character.
%T
Equivalent to %H:%M:%S.
%u
The calendar day of week as a decimal number (1-7), as specified in ISO 8601-1:2019, where Monday is 1.
The modified command %Ou produces the locale's alternative representation.
%U
The week number of the year as a decimal number.
The first Sunday of the year is the first day of week 01.
Days of the same year prior to that are in week 00.
If the result is a single digit, it is prefixed with 0.
The modified command %OU produces the locale's alternative representation.
%V
The calendar week of year as a decimal number, as specified in ISO 8601-1:2019 for the week calendar.
If the result is a single digit, it is prefixed with 0.
The modified command %OV produces the locale's alternative representation.
%w
The weekday as a decimal number (0-6), where Sunday is 0.
The modified command %Ow produces the locale's alternative representation.
%W
The week number of the year as a decimal number.
The first Monday of the year is the first day of week 01.
Days of the same year prior to that are in week 00.
If the result is a single digit, it is prefixed with 0.
The modified command %OW produces the locale's alternative representation.
%x
The locale's date representation.
The modified command %Ex produces the locale's alternate date representation.
%X
The locale's time representation.
The modified command %EX produces the locale's alternate time representation.
%y
The last two decimal digits of the year.
If the result is a single digit it is prefixed by 0.
The modified command %Oy produces the locale's alternative representation.
The modified command %Ey produces the locale's alternative representation of offset from %EC (year only).
%Y
The year as a decimal number.
If the result is less than four digits it is left-padded with 0 to four digits.
The modified command %EY produces the locale's alternative full year representation.
%z
The offset from UTC as specified in ISO 8601-1:2019, 5.3.4.1.
For example -0430 refers to 4 hours 30 minutes behind UTC.
If the offset is zero, +0000 is used.
The modified commands %Ez and %Oz insert a : between the hours and minutes: -04:30.
If the offset information is not available, an exception of type format_error is thrown.
%Z
The time zone abbreviation.
If the time zone abbreviation is not available, an exception of type format_error is thrown.
%%
A % character.
If the chrono-specs is omitted, the chrono object is formatted as if by streaming it to basic_ostringstream<charT> os with the formatting locale imbued and copying os.str() through the output iterator of the context with additional padding and adjustments as specified by the format specifiers.
[Example 3: string s = format("{:=>8}", 42ms); // value of s is "====42ms" — end example]
For chrono​::​duration the library only provides the following specialization of enable_nonlocking_formatter_optimization: template<class Rep, class Period> constexpr bool enable_nonlocking_formatter_optimization< chrono::duration<Rep, Period>> = enable_nonlocking_formatter_optimization<Rep>;
For chrono​::​zoned_time the library only provides the following specialization of enable_nonlocking_formatter_optimization: template<class Duration> constexpr bool enable_nonlocking_formatter_optimization< chrono::zoned_time<Duration, const std::chrono::time_zone*>> = true;
template<class Duration, class charT> struct formatter<chrono::sys_time<Duration>, charT>;
Remarks: If %Z is used, it is replaced with STATICALLY-WIDEN<charT>("UTC").
If %z (or a modified variant of %z) is used, an offset of 0min is formatted.
template<class Duration, class charT> struct formatter<chrono::utc_time<Duration>, charT>;
Remarks: If %Z is used, it is replaced with STATICALLY-WIDEN<charT>("UTC").
If %z (or a modified variant of %z) is used, an offset of 0min is formatted.
If the argument represents a time during a positive leap second insertion, and if a seconds field is formatted, the integral portion of that format is STATICALLY-WIDEN<charT>("60").
template<class Duration, class charT> struct formatter<chrono::tai_time<Duration>, charT>;
Remarks: If %Z is used, it is replaced with STATICALLY-WIDEN<charT>("TAI").
If %z (or a modified variant of %z) is used, an offset of 0min is formatted.
The date and time formatted are equivalent to those formatted by a sys_time initialized with sys_time<Duration>{tp.time_since_epoch()} - (sys_days{1970y/January/1} - sys_days{1958y/January/1})
template<class Duration, class charT> struct formatter<chrono::gps_time<Duration>, charT>;
Remarks: If %Z is used, it is replaced with STATICALLY-WIDEN<charT>("GPS").
If %z (or a modified variant of %z) is used, an offset of 0min is formatted.
The date and time formatted are equivalent to those formatted by a sys_time initialized with sys_time<Duration>{tp.time_since_epoch()} + (sys_days{1980y/January/Sunday[1]} - sys_days{1970y/January/1})
template<class Duration, class charT> struct formatter<chrono::file_time<Duration>, charT>;
Remarks: If %Z is used, it is replaced with STATICALLY-WIDEN<charT>("UTC").
If %z (or a modified variant of %z) is used, an offset of 0min is formatted.
The date and time formatted are equivalent to those formatted by a sys_time initialized with clock_cast<system_clock>(t), or by a utc_time initialized with clock_cast<utc_clock>(t), where t is the first argument to format.
template<class Duration, class charT> struct formatter<chrono::local_time<Duration>, charT>;
Remarks: If %Z, %z, or a modified version of %z is used, an exception of type format_error is thrown.
template<class Duration> struct local-time-format-t { // exposition only local_time<Duration> time; // exposition only const string* abbrev; // exposition only const seconds* offset_sec; // exposition only };
template<class Duration> local-time-format-t<Duration> local_time_format(local_time<Duration> time, const string* abbrev = nullptr, const seconds* offset_sec = nullptr);
Returns: {time, abbrev, offset_sec}.
template<class Duration, class charT> struct formatter<chrono::local-time-format-t<Duration>, charT>;
Let f be a local-time-format-t<Duration> object passed to formatter​::​format.
Remarks: If the chrono-specs is omitted, the result is equivalent to using %F %T %Z as the chrono-specs.
If %Z is used, it is replaced with *f.abbrev if f.abbrev is not a null pointer value.
If %Z is used and f.abbrev is a null pointer value, an exception of type format_error is thrown.
If %z (or a modified variant of %z) is used, it is formatted with the value of *f.offset_sec if f.offset_sec is not a null pointer value.
If %z (or a modified variant of %z) is used and f.offset_sec is a null pointer value, then an exception of type format_error is thrown.
template<class Duration, class TimeZonePtr, class charT> struct formatter<chrono::zoned_time<Duration, TimeZonePtr>, charT> : formatter<chrono::local-time-format-t<common_type_t<Duration, seconds>>, charT> { template<class FormatContext> typename FormatContext::iterator format(const chrono::zoned_time<Duration, TimeZonePtr>& tp, FormatContext& ctx) const; };
template<class FormatContext> typename FormatContext::iterator format(const chrono::zoned_time<Duration, TimeZonePtr>& tp, FormatContext& ctx) const;
Effects: Equivalent to: sys_info info = tp.get_info(); return formatter<chrono::local-time-format-t<common_type_t<Duration, seconds>>, charT>:: format({tp.get_local_time(), &info.abbrev, &info.offset}, ctx);

30.13 Parsing [time.parse]

Each parse overload specified in this subclause calls from_stream unqualified, so as to enable argument-dependent lookup ([basic.lookup.argdep]).
In the following paragraphs, let is denote an object of type basic_istream<charT, traits> and let I be basic_istream<charT, traits>&, where charT and traits are template parameters in that context.
Recommended practice: Implementations should make it difficult to accidentally store or use a manipulator that may contain a dangling reference to a format string, for example by making the manipulators produced by parse immovable and preventing stream extraction into an lvalue of such a manipulator type.
template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);
Let F be fmt for the first overload and fmt.c_str() for the second overload.
Let traits be char_traits<charT> for the first overload.
Constraints: The expression from_stream(declval<basic_istream<charT, traits>&>(), F, tp) is well-formed when treated as an unevaluated operand.
Returns: A manipulator such that the expression is >> parse(fmt, tp) has type I, has value is, and calls from_stream(is, F, tp).
template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev);
Let F be fmt for the first overload and fmt.c_str() for the second overload.
Constraints: The expression from_stream(declval<basic_istream<charT, traits>&>(), F, tp, addressof(abbrev)) is well-formed when treated as an unevaluated operand.
Returns: A manipulator such that the expression is >> parse(fmt, tp, abbrev) has type I, has value is, and calls from_stream(is, F, tp, addressof(abbrev)).
template<class charT, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, minutes& offset);
Let F be fmt for the first overload and fmt.c_str() for the second overload.
Let traits be char_traits<charT> and Alloc be allocator<charT> for the first overload.
Constraints: The expression from_stream(declval<basic_istream<charT, traits>&>(), F, tp, declval<basic_string<charT, traits, Alloc>*>(), &offset) is well-formed when treated as an unevaluated operand.
Returns: A manipulator such that the expression is >> parse(fmt, tp, offset) has type I, has value is, and calls: from_stream(is, F, tp, static_cast<basic_string<charT, traits, Alloc>*>(nullptr), &offset)
template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const charT* fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); template<class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset);
Let F be fmt for the first overload and fmt.c_str() for the second overload.
Constraints: The expression from_stream(declval<basic_istream<charT, traits>&>(), F, tp, addressof(abbrev), &offset) is well-formed when treated as an unevaluated operand.
Returns: A manipulator such that the expression is >> parse(fmt, tp, abbrev, offset) has type I, has value is, and calls from_stream(is, F, tp, addressof(abbrev), &offset).
All from_stream overloads behave as unformatted input functions, except that they have an unspecified effect on the value returned by subsequent calls to basic_istream<>​::​gcount().
Each overload takes a format string containing ordinary characters and flags which have special meaning.
Each flag begins with a %.
Some flags can be modified by E or O.
During parsing each flag interprets characters as parts of date and time types according to Table 129.
Some flags can be modified by a width parameter given as a positive decimal integer called out as N below which governs how many characters are parsed from the stream in interpreting the flag.
All characters in the format string that are not represented in Table 129, except for whitespace, are parsed unchanged from the stream.
A whitespace character matches zero or more whitespace characters in the input stream.
If the type being parsed cannot represent the information that the format flag refers to, is.setstate(ios_base​::​failbit) is called.
[Example 1: 
A duration cannot represent a weekday.
— end example]
However, if a flag refers to a “time of day” (e.g., %H, %I, %p, etc.)
, then a specialization of duration is parsed as the time of day elapsed since midnight.
If the from_stream overload fails to parse everything specified by the format string, or if insufficient information is parsed to specify a complete duration, time point, or calendrical data structure, setstate(ios_base​::​failbit) is called on the basic_istream.
Table 129 — Meaning of parse flags [tab:time.parse.spec]
Flag
Parsed value
%a
The locale's full or abbreviated case-insensitive weekday name.
%A
Equivalent to %a.
%b
The locale's full or abbreviated case-insensitive month name.
%B
Equivalent to %b.
%c
The locale's date and time representation.
The modified command %Ec interprets the locale's alternate date and time representation.
%C
The century as a decimal number.
The modified command %NC specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %EC interprets the locale's alternative representation of the century.
%d
The day of the month as a decimal number.
The modified command %Nd specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %Od interprets the locale's alternative representation of the day of the month.
%D
Equivalent to %m/%d/%y.
%e
Equivalent to %d and can be modified like %d.
%F
Equivalent to %Y-%m-%d.
If modified with a width N, the width is applied to only %Y.
%g
The last two decimal digits of the calendar year, as specified in ISO 8601-1:2019 for the week calendar.
The modified command %Ng specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
%G
The calendar year as a decimal number, as specified in ISO 8601-1:2019 for the week calendar.
The modified command %NG specifies the maximum number of characters to read.
If N is not specified, the default is 4.
Leading zeroes are permitted but not required.
%h
Equivalent to %b.
%H
The hour (24-hour clock) as a decimal number.
The modified command %NH specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %OH interprets the locale's alternative representation.
%I
The hour (12-hour clock) as a decimal number.
The modified command %NI specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %OI interprets the locale's alternative representation.
%j
If the type being parsed is a specialization of duration, a decimal number of days.
Otherwise, the day of the year as a decimal number.
January 1 is 1.
In either case, the modified command %Nj specifies the maximum number of characters to read.
If N is not specified, the default is 3.
Leading zeroes are permitted but not required.
%m
The month as a decimal number.
January is 1.
The modified command %Nm specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %Om interprets the locale's alternative representation.
%M
The minutes as a decimal number.
The modified command %NM specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %OM interprets the locale's alternative representation.
%n
Matches one whitespace character.
[Note 1: 
%n, %t, and a space can be combined to match a wide range of whitespace patterns.
For example, "%n " matches one or more whitespace characters, and "%n%t%t" matches one to three whitespace characters.
— end note]
%p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock.
%r
The locale's 12-hour clock time.
%R
Equivalent to %H:%M.
%S
The seconds as a decimal number.
The modified command %NS specifies the maximum number of characters to read.
If N is not specified, the default is 2 if the input time has a precision convertible to seconds.
Otherwise the default width is determined by the decimal precision of the input and the field is interpreted as a long double in a fixed format.
If encountered, the locale determines the decimal point character.
Leading zeroes are permitted but not required.
The modified command %OS interprets the locale's alternative representation.
%t
Matches zero or one whitespace characters.
%T
Equivalent to %H:%M:%S.
%u
The calendar day of week as a decimal number (1-7), as specified in ISO 8601-1:2019, where Monday is 1.
The modified command %Nu specifies the maximum number of characters to read.
If N is not specified, the default is 1.
Leading zeroes are permitted but not required.
%U
The week number of the year as a decimal number.
The first Sunday of the year is the first day of week 01.
Days of the same year prior to that are in week 00.
The modified command %NU specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %OU interprets the locale's alternative representation.
%V
The calendar week of year as a decimal number, as specified in ISO 8601-1:2019 for the week calendar.
The modified command %NV specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
%w
The weekday as a decimal number (0-6), where Sunday is 0.
The modified command %Nw specifies the maximum number of characters to read.
If N is not specified, the default is 1.
Leading zeroes are permitted but not required.
The modified command %Ow interprets the locale's alternative representation.
%W
The week number of the year as a decimal number.
The first Monday of the year is the first day of week 01.
Days of the same year prior to that are in week 00.
The modified command %NW specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified command %OW interprets the locale's alternative representation.
%x
The locale's date representation.
The modified command %Ex interprets the locale's alternate date representation.
%X
The locale's time representation.
The modified command %EX interprets the locale's alternate time representation.
%y
The last two decimal digits of the year.
If the century is not otherwise specified (e.g., with %C), values in the range [69, 99] are presumed to refer to the years 1969 to 1999, and values in the range [00, 68] are presumed to refer to the years 2000 to 2068.
The modified command %Ny specifies the maximum number of characters to read.
If N is not specified, the default is 2.
Leading zeroes are permitted but not required.
The modified commands %Ey and %Oy interpret the locale's alternative representation.
%Y
The year as a decimal number.
The modified command %NY specifies the maximum number of characters to read.
If N is not specified, the default is 4.
Leading zeroes are permitted but not required.
The modified command %EY interprets the locale's alternative representation.
%z
The offset from UTC in the format [+|-]hh[mm].
For example -0430 refers to 4 hours 30 minutes behind UTC, and 04 refers to 4 hours ahead of UTC.
The modified commands %Ez and %Oz parse a : between the hours and minutes and render leading zeroes on the hour field optional: [+|-]h[h][:mm].
For example -04:30 refers to 4 hours 30 minutes behind UTC, and 4 refers to 4 hours ahead of UTC.
%Z
The time zone abbreviation or name.
A single word is parsed.
This word can only contain characters from the basic character set ([lex.charset]) that are alphanumeric, or one of '_', '/', '-', or '+'.
%%
A % character is extracted.

30.14 Hash support [time.hash]

template<class Rep, class Period> struct hash<chrono::duration<Rep, Period>>;
The specialization hash<chrono​::​duration<Rep, Period>> is enabled ([unord.hash]) if and only if
hash<Rep> is enabled.
The member functions are not guaranteed to be noexcept.
template<class Clock, class Duration> struct hash<chrono::time_point<Clock, Duration>>;
The specialization hash<chrono​::​time_point<Clock, Duration>> is enabled ([unord.hash]) if and only if hash<Duration> is enabled.
The member functions are not guaranteed to be noexcept.
template<> struct hash<chrono::day>; template<> struct hash<chrono::month>; template<> struct hash<chrono::year>; template<> struct hash<chrono::weekday>; template<> struct hash<chrono::weekday_indexed>; template<> struct hash<chrono::weekday_last>; template<> struct hash<chrono::month_day>; template<> struct hash<chrono::month_day_last>; template<> struct hash<chrono::month_weekday>; template<> struct hash<chrono::month_weekday_last>; template<> struct hash<chrono::year_month>; template<> struct hash<chrono::year_month_day>; template<> struct hash<chrono::year_month_day_last>; template<> struct hash<chrono::year_month_weekday>; template<> struct hash<chrono::year_month_weekday_last>;
The specializations are enabled ([unord.hash]).
[Note 1: 
All the hash<Key> specializations listed above meet the Cpp17Hash requirements, even when called on objects k of type Key such that k.ok() is false.
— end note]
template<class Duration, class TimeZonePtr> struct hash<chrono::zoned_time<Duration, TimeZonePtr>>;
The specialization hash<chrono​::​zoned_time<Duration, TimeZonePtr>> is enabled ([unord.hash]) if and only if hash<Duration> is enabled and hash<TimeZonePtr> is enabled.
The member functions are not guaranteed to be noexcept.
template<> struct hash<chrono::leap_second>;
The specialization is enabled ([unord.hash]).

30.15 Header <ctime> synopsis [ctime.syn]

#define NULL see [support.types.nullptr] #define CLOCKS_PER_SEC see below #define TIME_UTC see below namespace std { using size_t = see [support.types.layout]; using clock_t = see below; using time_t = see below; struct timespec; struct tm; clock_t clock(); double difftime(time_t time1, time_t time0); time_t mktime(tm* timeptr); time_t time(time_t* timer); int timespec_get(timespec* ts, int base); char* asctime(const tm* timeptr); char* ctime(const time_t* timer); tm* gmtime(const time_t* timer); tm* localtime(const time_t* timer); size_t strftime(char* s, size_t maxsize, const char* format, const tm* timeptr); }
The contents of the header <ctime> are the same as the C standard library header <time.h>.258
The functions asctime, ctime, gmtime, and localtime are not required to avoid data races ([res.on.data.races]).
See also: ISO/IEC 9899:2018, 7.27
258)258)
strftime supports the C conversion specifiers C, D, e, F, g, G, h, r, R, t, T, u, V, and z, and the modifiers E and O.

31 Input/output library [input.output]

31.1 General [input.output.general]

This Clause describes components that C++ programs may use to perform input/output operations.
The following subclauses describe requirements for stream parameters, and components for forward declarations of iostreams, predefined iostreams objects, base iostreams classes, stream buffering, stream formatting and manipulators, string streams, and file streams, as summarized in Table 130.
Table 130 — Input/output library summary [tab:iostreams.summary]
Subclause
Header
Requirements
Forward declarations
<iosfwd>
Standard iostream objects
<iostream>
Iostreams base classes
<ios>
Stream buffers
<streambuf>
Formatting and manipulators
<istream>, <ostream>, <iomanip>, <print>
String streams
<sstream>
Span-based streams
<spanstream>
File streams
<fstream>
Synchronized output streams
<syncstream>
File systems
<filesystem>
C library files
<cstdio>, <cinttypes>

31.2 Iostreams requirements [iostreams.requirements]

31.2.1 Imbue limitations [iostream.limits.imbue]

No function described in [input.output] except for ios_base​::​imbue and basic_filebuf​::​pubimbue causes any instance of basic_ios​::​imbue or basic_streambuf​::​imbue to be called.
If any user function called from a function declared in [input.output] or as an overriding virtual function of any class declared in [input.output] calls imbue, the behavior is undefined.

31.2.2 Types [stream.types]

using streamoff = implementation-defined;
The type streamoff is a synonym for one of the signed basic integral types of sufficient size to represent the maximum possible file size for the operating system.259
using streamsize = implementation-defined;
The type streamsize is a synonym for one of the signed basic integral types.
It is used to represent the number of characters transferred in an I/O operation, or the size of I/O buffers.260
259)259)
Typically long long.
260)260)
Most places where streamsize is used would use size_t in C, or ssize_t in POSIX.

31.2.3 Positioning type limitations [iostreams.limits.pos]

The classes of [input.output] with template arguments charT and traits behave as described if traits​::​pos_type and traits​::​off_type are streampos and streamoff respectively.
Except as noted explicitly below, their behavior when traits​::​pos_type and traits​::​off_type are other types is implementation-defined.
[Note 1: 
For each of the specializations of char_traits defined in [char.traits.specializations], state_type denotes mbstate_t, pos_type denotes fpos<mbstate_t>, and off_type denotes streamoff.
— end note]
In the classes of [input.output], a template parameter with name charT represents a member of the set of types containing char, wchar_t, and any other implementation-defined character container types ([defns.character.container]) that meet the requirements for a character on which any of the iostream components can be instantiated.

31.2.4 Thread safety [iostreams.threadsafety]

Concurrent access to a stream object ([string.streams], [file.streams]), stream buffer object ([stream.buffers]), or C Library stream ([c.files]) by multiple threads may result in a data race ([intro.multithread]) unless otherwise specified ([iostream.objects]).
[Note 1: 
Data races result in undefined behavior ([intro.multithread]).
— end note]
If one thread makes a library call a that writes a value to a stream and, as a result, another thread reads this value from the stream through a library call b such that this does not result in a data race, then a's write synchronizes with b's read.

31.3 Forward declarations [iostream.forward]

31.3.1 Header <iosfwd> synopsis [iosfwd.syn]

namespace std { template<class charT> struct char_traits; template<> struct char_traits<char>; template<> struct char_traits<char8_t>; template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; template<> struct char_traits<wchar_t>; template<class T> class allocator; template<class charT, class traits = char_traits<charT>> class basic_ios; template<class charT, class traits = char_traits<charT>> class basic_streambuf; template<class charT, class traits = char_traits<charT>> class basic_istream; template<class charT, class traits = char_traits<charT>> class basic_ostream; template<class charT, class traits = char_traits<charT>> class basic_iostream; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringbuf; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_istringstream; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_ostringstream; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringstream; template<class charT, class traits = char_traits<charT>> class basic_spanbuf; template<class charT, class traits = char_traits<charT>> class basic_ispanstream; template<class charT, class traits = char_traits<charT>> class basic_ospanstream; template<class charT, class traits = char_traits<charT>> class basic_spanstream; template<class charT, class traits = char_traits<charT>> class basic_filebuf; template<class charT, class traits = char_traits<charT>> class basic_ifstream; template<class charT, class traits = char_traits<charT>> class basic_ofstream; template<class charT, class traits = char_traits<charT>> class basic_fstream; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_syncbuf; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_osyncstream; template<class charT, class traits = char_traits<charT>> class istreambuf_iterator; template<class charT, class traits = char_traits<charT>> class ostreambuf_iterator; using ios = basic_ios<char>; using wios = basic_ios<wchar_t>; using streambuf = basic_streambuf<char>; using istream = basic_istream<char>; using ostream = basic_ostream<char>; using iostream = basic_iostream<char>; using stringbuf = basic_stringbuf<char>; using istringstream = basic_istringstream<char>; using ostringstream = basic_ostringstream<char>; using stringstream = basic_stringstream<char>; using spanbuf = basic_spanbuf<char>; using ispanstream = basic_ispanstream<char>; using ospanstream = basic_ospanstream<char>; using spanstream = basic_spanstream<char>; using filebuf = basic_filebuf<char>; using ifstream = basic_ifstream<char>; using ofstream = basic_ofstream<char>; using fstream = basic_fstream<char>; using syncbuf = basic_syncbuf<char>; using osyncstream = basic_osyncstream<char>; using wstreambuf = basic_streambuf<wchar_t>; using wistream = basic_istream<wchar_t>; using wostream = basic_ostream<wchar_t>; using wiostream = basic_iostream<wchar_t>; using wstringbuf = basic_stringbuf<wchar_t>; using wistringstream = basic_istringstream<wchar_t>; using wostringstream = basic_ostringstream<wchar_t>; using wstringstream = basic_stringstream<wchar_t>; using wspanbuf = basic_spanbuf<wchar_t>; using wispanstream = basic_ispanstream<wchar_t>; using wospanstream = basic_ospanstream<wchar_t>; using wspanstream = basic_spanstream<wchar_t>; using wfilebuf = basic_filebuf<wchar_t>; using wifstream = basic_ifstream<wchar_t>; using wofstream = basic_ofstream<wchar_t>; using wfstream = basic_fstream<wchar_t>; using wsyncbuf = basic_syncbuf<wchar_t>; using wosyncstream = basic_osyncstream<wchar_t>; template<class state> class fpos; using streampos = fpos<char_traits<char>::state_type>; using wstreampos = fpos<char_traits<wchar_t>::state_type>; using u8streampos = fpos<char_traits<char8_t>::state_type>; using u16streampos = fpos<char_traits<char16_t>::state_type>; using u32streampos = fpos<char_traits<char32_t>::state_type>; }
Default template arguments are described as appearing both in <iosfwd> and in the synopsis of other headers but it is well-formed to include both <iosfwd> and one or more of the other headers.261
261)261)
It is the implementation's responsibility to implement headers so that including <iosfwd> and other headers does not violate the rules about multiple occurrences of default arguments.

31.3.2 Overview [iostream.forward.overview]

The class template specialization basic_ios<charT, traits> serves as a virtual base class for the class templates basic_istream, basic_ostream, and class templates derived from them.
basic_iostream is a class template derived from both basic_istream<charT, traits> and basic_ostream<charT, traits>.
The class template specialization basic_streambuf<charT, traits> serves as a base class for class templates basic_stringbuf, basic_filebuf, and basic_syncbuf.
The class template specialization basic_istream<charT, traits> serves as a base class for class templates basic_istringstream and basic_ifstream.
The class template specialization basic_ostream<charT, traits> serves as a base class for class templates basic_ostringstream, basic_ofstream, and basic_osyncstream.
The class template specialization basic_iostream<charT, traits> serves as a base class for class templates basic_stringstream and basic_fstream.
[Note 1: 
For each of the class templates above, the program is ill-formed if traits​::​char_type is not the same type as charT ([char.traits]).
— end note]
Other typedef-names define instances of class templates specialized for char or wchar_t types.
Specializations of the class template fpos are used for specifying file position information.
[Example 1: 
The types streampos and wstreampos are used for positioning streams specialized on char and wchar_t respectively.
— end example]
[Note 2: 
This synopsis suggests a circularity between streampos and char_traits<char>.
An implementation can avoid this circularity by substituting equivalent types.
— end note]

31.4 Standard iostream objects [iostream.objects]

31.4.1 Header <iostream> synopsis [iostream.syn]

#include <ios> // see [ios.syn] #include <streambuf> // see [streambuf.syn] #include <istream> // see [istream.syn] #include <ostream> // see [ostream.syn] namespace std { extern istream cin; extern ostream cout; extern ostream cerr; extern ostream clog; extern wistream wcin; extern wostream wcout; extern wostream wcerr; extern wostream wclog; }

31.4.2 Overview [iostream.objects.overview]

In this Clause, the type name FILE refers to the type FILE declared in <cstdio>.
The header <iostream> declares objects that associate objects with the standard C streams provided for by the functions declared in <cstdio>, and includes all the headers necessary to use these objects.
The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_base​::​Init is constructed, and in any case before the body of main ([basic.start.main]) begins execution.
The objects are not destroyed during program execution.262
Recommended practice: If it is possible for them to do so, implementations should initialize the objects earlier than required.
The results of including <iostream> in a translation unit shall be as if <iostream> defined an instance of ios_base​::​Init with static storage duration.
Each C++ library module ([std.modules]) in a hosted implementation shall behave as if it contains an interface unit that defines an unexported ios_base​::​Init variable with ordered initialization ([basic.start.dynamic]).
[Note 1: 
As a result, the definition of that variable is appearance-ordered before any declaration following the point of importation of a C++ library module.
Whether such a definition exists is unobservable by a program that does not reference any of the standard iostream objects.
— end note]
Mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on FILEs, as specified in the C standard library.
Concurrent access to a synchronized ([ios.members.static]) standard iostream object's formatted and unformatted input ([istream]) and output ([ostream]) functions or a standard C stream by multiple threads does not result in a data race ([intro.multithread]).
[Note 2: 
Unsynchronized concurrent use of these objects and streams by multiple threads can result in interleaved characters.
— end note]
See also: ISO/IEC 9899:2018, 7.21.2
262)262)
Constructors and destructors for objects with static storage duration can access these objects to read input from stdin or write output to stdout or stderr.

31.4.3 Narrow stream objects [narrow.stream.objects]

istream cin;
The object cin controls input from a stream buffer associated with the object stdin, declared in <cstdio>.
After the object cin is initialized, cin.tie() returns &cout.
Its state is otherwise the same as required for basic_ios<char>​::​init.
ostream cout;
The object cout controls output to a stream buffer associated with the object stdout, declared in <cstdio>.
ostream cerr;
The object cerr controls output to a stream buffer associated with the object stderr, declared in <cstdio>.
After the object cerr is initialized, cerr.flags() & unitbuf is nonzero and cerr.tie() returns &cout.
Its state is otherwise the same as required for basic_ios<char>​::​init.
ostream clog;
The object clog controls output to a stream buffer associated with the object stderr, declared in <cstdio>.

31.4.4 Wide stream objects [wide.stream.objects]

wistream wcin;
The object wcin controls input from a stream buffer associated with the object stdin, declared in <cstdio>.
After the object wcin is initialized, wcin.tie() returns &wcout.
Its state is otherwise the same as required for basic_ios<wchar_t>​::​init.
wostream wcout;
The object wcout controls output to a stream buffer associated with the object stdout, declared in <cstdio>.
wostream wcerr;
The object wcerr controls output to a stream buffer associated with the object stderr, declared in <cstdio>.
After the object wcerr is initialized, wcerr.flags() & unitbuf is nonzero and wcerr.tie() returns &wcout.
Its state is otherwise the same as required for basic_ios<wchar_t>​::​init.
wostream wclog;
The object wclog controls output to a stream buffer associated with the object stderr, declared in <cstdio>.

31.5 Iostreams base classes [iostreams.base]

31.5.1 Header <ios> synopsis [ios.syn]

#include <iosfwd> // see [iosfwd.syn] namespace std { // [stream.types], types using streamoff = implementation-defined; using streamsize = implementation-defined; // [fpos], class template fpos template<class stateT> class fpos; // [ios.base], class ios_base class ios_base; // [ios], class template basic_ios template<class charT, class traits = char_traits<charT>> class basic_ios; // [std.ios.manip], manipulators ios_base& boolalpha (ios_base& str); ios_base& noboolalpha(ios_base& str); ios_base& showbase (ios_base& str); ios_base& noshowbase (ios_base& str); ios_base& showpoint (ios_base& str); ios_base& noshowpoint(ios_base& str); ios_base& showpos (ios_base& str); ios_base& noshowpos (ios_base& str); ios_base& skipws (ios_base& str); ios_base& noskipws (ios_base& str); ios_base& uppercase (ios_base& str); ios_base& nouppercase(ios_base& str); ios_base& unitbuf (ios_base& str); ios_base& nounitbuf (ios_base& str); // [adjustfield.manip], adjustfield ios_base& internal (ios_base& str); ios_base& left (ios_base& str); ios_base& right (ios_base& str); // [basefield.manip], basefield ios_base& dec (ios_base& str); ios_base& hex (ios_base& str); ios_base& oct (ios_base& str); // [floatfield.manip], floatfield ios_base& fixed (ios_base& str); ios_base& scientific (ios_base& str); ios_base& hexfloat (ios_base& str); ios_base& defaultfloat(ios_base& str); // [error.reporting], error reporting enum class io_errc { stream = 1 }; template<> struct is_error_code_enum<io_errc> : public true_type { }; error_code make_error_code(io_errc e) noexcept; error_condition make_error_condition(io_errc e) noexcept; const error_category& iostream_category() noexcept; }

31.5.2 Class ios_base [ios.base]

31.5.2.1 General [ios.base.general]

namespace std { class ios_base { public: class failure; // see below // [ios.fmtflags], fmtflags using fmtflags = T1; static constexpr fmtflags boolalpha = unspecified; static constexpr fmtflags dec = unspecified; static constexpr fmtflags fixed = unspecified; static constexpr fmtflags hex = unspecified; static constexpr fmtflags internal = unspecified; static constexpr fmtflags left = unspecified; static constexpr fmtflags oct = unspecified; static constexpr fmtflags right = unspecified; static constexpr fmtflags scientific = unspecified; static constexpr fmtflags showbase = unspecified; static constexpr fmtflags showpoint = unspecified; static constexpr fmtflags showpos = unspecified; static constexpr fmtflags skipws = unspecified; static constexpr fmtflags unitbuf = unspecified; static constexpr fmtflags uppercase = unspecified; static constexpr fmtflags adjustfield = see below; static constexpr fmtflags basefield = see below; static constexpr fmtflags floatfield = see below; // [ios.iostate], iostate using iostate = T2; static constexpr iostate badbit = unspecified; static constexpr iostate eofbit = unspecified; static constexpr iostate failbit = unspecified; static constexpr iostate goodbit = see below; // [ios.openmode], openmode using openmode = T3; static constexpr openmode app = unspecified; static constexpr openmode ate = unspecified; static constexpr openmode binary = unspecified; static constexpr openmode in = unspecified; static constexpr openmode noreplace = unspecified; static constexpr openmode out = unspecified; static constexpr openmode trunc = unspecified; // [ios.seekdir], seekdir using seekdir = T4; static constexpr seekdir beg = unspecified; static constexpr seekdir cur = unspecified; static constexpr seekdir end = unspecified; class Init; // [fmtflags.state], fmtflags state fmtflags flags() const; fmtflags flags(fmtflags fmtfl); fmtflags setf(fmtflags fmtfl); fmtflags setf(fmtflags fmtfl, fmtflags mask); void unsetf(fmtflags mask); streamsize precision() const; streamsize precision(streamsize prec); streamsize width() const; streamsize width(streamsize wide); // [ios.base.locales], locales locale imbue(const locale& loc); locale getloc() const; // [ios.base.storage], storage static int xalloc(); long& iword(int idx); void*& pword(int idx); // destructor virtual ~ios_base(); // [ios.base.callback], callbacks enum event { erase_event, imbue_event, copyfmt_event }; using event_callback = void (*)(event, ios_base&, int idx); void register_callback(event_callback fn, int idx); ios_base(const ios_base&) = delete; ios_base& operator=(const ios_base&) = delete; static bool sync_with_stdio(bool sync = true); protected: ios_base(); private: static int index; // exposition only long* iarray; // exposition only void** parray; // exposition only }; }
ios_base defines several member types:
  • a type failure, defined as either a class derived from system_error or a synonym for a class derived from system_error;
  • a class Init;
  • three bitmask types, fmtflags, iostate, and openmode;
  • an enumerated type, seekdir.
It maintains several kinds of data:
  • state information that reflects the integrity of the stream buffer;
  • control information that influences how to interpret (format) input sequences and how to generate (format) output sequences;
  • additional information that is stored by the program for its private use.
[Note 1: 
For the sake of exposition, the maintained data is presented here as:
  • static int index, specifies the next available unique index for the integer or pointer arrays maintained for the private use of the program, initialized to an unspecified value;
  • long* iarray, points to the first element of an arbitrary-length long array maintained for the private use of the program;
  • void** parray, points to the first element of an arbitrary-length pointer array maintained for the private use of the program.
— end note]

31.5.2.2 Types [ios.types]

31.5.2.2.1 Class ios_base​::​failure [ios.failure]

namespace std { class ios_base::failure : public system_error { public: explicit failure(const string& msg, const error_code& ec = io_errc::stream); explicit failure(const char* msg, const error_code& ec = io_errc::stream); }; }
An implementation is permitted to define ios_base​::​failure as a synonym for a class with equivalent functionality to class ios_base​::​failure shown in this subclause.
[Note 1: 
When ios_base​::​failure is a synonym for another type, that type needs to provide a nested type failure to emulate the injected-class-name.
— end note]
The class failure defines the base class for the types of all objects thrown as exceptions, by functions in the iostreams library, to report errors detected during stream buffer operations.
When throwing ios_base​::​failure exceptions, implementations should provide values of ec that identify the specific reason for the failure.
[Note 2: 
Errors arising from the operating system would typically be reported as system_category() errors with an error value of the error number reported by the operating system.
Errors arising from within the stream library would typically be reported as error_code(io_errc​::​stream, iostream_category()).
— end note]
explicit failure(const string& msg, const error_code& ec = io_errc::stream);
Effects: Constructs the base class with msg and ec.
explicit failure(const char* msg, const error_code& ec = io_errc::stream);
Effects: Constructs the base class with msg and ec.

31.5.2.2.2 Type ios_base​::​fmtflags [ios.fmtflags]

using fmtflags = T1;
The type fmtflags is a bitmask type ([bitmask.types]).
Setting its elements has the effects indicated in Table 131.
Table 131fmtflags effects [tab:ios.fmtflags]
Element
Effect(s) if set
boolalpha
insert and extract bool type in alphabetic format
dec
converts integer input or generates integer output in decimal base
fixed
generate floating-point output in fixed-point notation
hex
converts integer input or generates integer output in hexadecimal base
internal
adds fill characters at a designated internal point in certain generated output, or identical to right if no such point is designated
left
adds fill characters on the right (final positions) of certain generated output
oct
converts integer input or generates integer output in octal base
right
adds fill characters on the left (initial positions) of certain generated output
scientific
generates floating-point output in scientific notation
showbase
generates a prefix indicating the numeric base of generated integer output
showpoint
generates a decimal-point character unconditionally in generated floating-point output
showpos
generates a + sign in non-negative generated numeric output
skipws
skips leading whitespace before certain input operations
unitbuf
flushes output after each output operation
uppercase
replaces certain lowercase letters with their uppercase equivalents in generated output
Type fmtflags also defines the constants indicated in Table 132.
Table 132fmtflags constants [tab:ios.fmtflags.const]
Constant
Allowable values
adjustfield
left | right | internal
basefield
dec | oct | hex
floatfield
scientific | fixed

31.5.2.2.3 Type ios_base​::​iostate [ios.iostate]

using iostate = T2;
The type iostate is a bitmask type ([bitmask.types]) that contains the elements indicated in Table 133.
Table 133iostate effects [tab:ios.iostate]
Element
Effect(s) if set
badbit
indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error from a file);
eofbit
indicates that an input operation reached the end of an input sequence;
failbit
indicates that an input operation failed to read the expected characters, or that an output operation failed to generate the desired characters.
Type iostate also defines the constant:

31.5.2.2.4 Type ios_base​::​openmode [ios.openmode]

using openmode = T3;
The type openmode is a bitmask type ([bitmask.types]).
It contains the elements indicated in Table 134.
Table 134openmode effects [tab:ios.openmode]
Element
Effect(s) if set
app
seek to end before each write
ate
open and seek to end immediately after opening
binary
perform input and output in binary mode (as opposed to text mode)
in
open for input
noreplace
open in exclusive mode
out
open for output
trunc
truncate an existing stream when opening

31.5.2.2.5 Type ios_base​::​seekdir [ios.seekdir]

using seekdir = T4;
The type seekdir is an enumerated type ([enumerated.types]) that contains the elements indicated in Table 135.
Table 135seekdir effects [tab:ios.seekdir]
Element
Meaning
beg
request a seek (for subsequent input or output) relative to the beginning of the stream
cur
request a seek relative to the current position within the sequence
end
request a seek relative to the current end of the sequence

31.5.2.2.6 Class ios_base​::​Init [ios.init]

namespace std { class ios_base::Init { public: Init(); Init(const Init&) = default; ~Init(); Init& operator=(const Init&) = default; }; }
The class Init describes an object whose construction ensures the construction of the eight objects declared in <iostream> ([iostream.objects]) that associate file stream buffers with the standard C streams provided for by the functions declared in <cstdio>.
Init();
Effects: Constructs and initializes the objects cin, cout, cerr, clog, wcin, wcout, wcerr, and wclog if they have not already been constructed and initialized.
~Init();
Effects: If there are no other instances of the class still in existence, calls cout.flush(), cerr.flush(), clog.flush(), wcout.flush(), wcerr.flush(), wclog.flush().

31.5.2.3 State functions [fmtflags.state]

fmtflags flags() const;
Returns: The format control information for both input and output.
fmtflags flags(fmtflags fmtfl);
Postconditions: fmtfl == flags().
Returns: The previous value of flags().
fmtflags setf(fmtflags fmtfl);
Effects: Sets fmtfl in flags().
Returns: The previous value of flags().
fmtflags setf(fmtflags fmtfl, fmtflags mask);
Effects: Clears mask in flags(), sets fmtfl & mask in flags().
Returns: The previous value of flags().
void unsetf(fmtflags mask);
Effects: Clears mask in flags().
streamsize precision() const;
Returns: The precision to generate on certain output conversions.
streamsize precision(streamsize prec);
Postconditions: prec == precision().
Returns: The previous value of precision().
streamsize width() const;
Returns: The minimum field width (number of characters) to generate on certain output conversions.
streamsize width(streamsize wide);
Postconditions: wide == width().
Returns: The previous value of width().

31.5.2.4 Functions [ios.base.locales]

locale imbue(const locale& loc);
Effects: Calls each registered callback pair (fn, idx) ([ios.base.callback]) as (*fn)(imbue_event, *this, idx) at such a time that a call to ios_base​::​getloc() from within fn returns the new locale value loc.
Postconditions: loc == getloc().
Returns: The previous value of getloc().
locale getloc() const;
Returns: If no locale has been imbued, a copy of the global C++ locale, locale(), in effect at the time of construction.
Otherwise, returns the imbued locale, to be used to perform locale-dependent input and output operations.

31.5.2.5 Static members [ios.members.static]

static bool sync_with_stdio(bool sync = true);
Effects: If any input or output operation has occurred using the standard streams prior to the call, the effect is implementation-defined.
Otherwise, called with a false argument, it allows the standard streams to operate independently of the standard C streams.
Returns: true if the previous state of the standard iostream objects was synchronized and otherwise returns false.
The first time it is called, the function returns true.
Remarks: When a standard iostream object str is synchronized with a standard stdio stream f, the effect of inserting a character c by fputc(f, c); is the same as the effect of str.rdbuf()->sputc(c); for any sequences of characters; the effect of extracting a character c by c = fgetc(f); is the same as the effect of c = str.rdbuf()->sbumpc(); for any sequences of characters; and the effect of pushing back a character c by ungetc(c, f); is the same as the effect of str.rdbuf()->sputbackc(c); for any sequence of characters.263
263)263)
This implies that operations on a standard iostream object can be mixed arbitrarily with operations on the corresponding stdio stream.
In practical terms, synchronization usually means that a standard iostream object and a standard stdio object share a buffer.

31.5.2.6 Storage functions [ios.base.storage]

static int xalloc();
Returns: index ++.
Remarks: Concurrent access to this function by multiple threads does not result in a data race.
long& iword(int idx);
Preconditions: idx is a value obtained by a call to xalloc.
Effects: If iarray is a null pointer, allocates an array of long of unspecified size and stores a pointer to its first element in iarray.
The function then extends the array pointed at by iarray as necessary to include the element iarray[idx].
Each newly allocated element of the array is initialized to zero.
The reference returned is invalid after any other operation on the object.264
However, the value of the storage referred to is retained, so that until the next call to copyfmt, calling iword with the same index yields another reference to the same value.
If the function fails265 and *this is a base class subobject of a basic_ios<> object or subobject, the effect is equivalent to calling basic_ios<>​::​setstate(badbit) on the derived object (which may throw failure).
Returns: On success iarray[idx].
On failure, a valid long& initialized to 0.
void*& pword(int idx);
Preconditions: idx is a value obtained by a call to xalloc.
Effects: If parray is a null pointer, allocates an array of pointers to void of unspecified size and stores a pointer to its first element in parray.
The function then extends the array pointed at by parray as necessary to include the element parray[idx].
Each newly allocated element of the array is initialized to a null pointer.
The reference returned is invalid after any other operation on the object.
However, the value of the storage referred to is retained, so that until the next call to copyfmt, calling pword with the same index yields another reference to the same value.
If the function fails266 and *this is a base class subobject of a basic_ios<> object or subobject, the effect is equivalent to calling basic_ios<>​::​setstate(badbit) on the derived object (which may throw failure).
Returns: On success parray[idx].
On failure a valid void*& initialized to 0.
Remarks: After a subsequent call to pword(int) for the same object, the earlier return value may no longer be valid.
264)264)
An implementation is free to implement both the integer array pointed at by iarray and the pointer array pointed at by parray as sparse data structures, possibly with a one-element cache for each.
265)265)
For example, because it cannot allocate space.
266)266)
For example, because it cannot allocate space.

31.5.2.7 Callbacks [ios.base.callback]

void register_callback(event_callback fn, int idx);
Preconditions: The function fn does not throw exceptions.
Effects: Registers the pair (fn, idx) such that during calls to imbue() ([ios.base.locales]), copyfmt(), or ~ios_base() ([ios.base.cons]), the function fn is called with argument idx.
Functions registered are called when an event occurs, in opposite order of registration.
Functions registered while a callback function is active are not called until the next event.
Remarks: Identical pairs are not merged.
A function registered twice will be called twice.

31.5.2.8 Constructors and destructor [ios.base.cons]

ios_base();
Effects: Each ios_base member has an indeterminate value after construction.
The object's members shall be initialized by calling basic_ios​::​init before the object's first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined.
~ios_base();
Effects: Calls each registered callback pair (fn, idx) ([ios.base.callback]) as (*fn)(​erase_event, *this, idx) at such time that any ios_base member function called from within fn has well-defined results.
Then, any memory obtained is deallocated.

31.5.3 Class template fpos [fpos]

31.5.3.1 General [fpos.general]

namespace std { template<class stateT> class fpos { public: // [fpos.members], members stateT state() const; void state(stateT); private: stateT st; // exposition only }; }

31.5.3.2 Members [fpos.members]

void state(stateT s);
Effects: Assigns s to st.
stateT state() const;
Returns: Current value of st.

31.5.3.3 Requirements [fpos.operations]

An fpos type specifies file position information.
It holds a state object whose type is equal to the template parameter stateT.
Type stateT shall meet the Cpp17DefaultConstructible (Table 30), Cpp17CopyConstructible (Table 32), Cpp17CopyAssignable (Table 34), and Cpp17Destructible (Table 35) requirements.
If is_trivially_copy_constructible_v<stateT> is true, then fpos<stateT> has a trivial copy constructor.
If is_trivially_copy_assignable_v<stateT> is true, then fpos<stateT> has a trivial copy assignment operator.
If is_trivially_destructible_v<stateT> is true, then fpos<stateT> has a trivial destructor.
In addition, the expressions shown in Table 136 are valid and have the indicated semantics.
In that table,
  • P refers to a specialization of fpos,
  • p and q refer to values of type P or const P,
  • pl and ql refer to modifiable lvalues of type P,
  • O refers to type streamoff, and
  • o and o2 refer to values of type streamoff or const streamoff.
Table 136 — Position type requirements [tab:fpos.operations]
Expression
Return type
Operational
Assertion/note
semantics
pre-/post-condition
P(o)
P
converts from offset
Effects: Value-initializes the state object.
P p(o);
P p = o;
Effects: Value-initializes the state object.

Postconditions: p == P(o) is true.
P()
P
P(0)
P p;
P p(0);
O(p)
streamoff
converts to offset
P(O(p)) == p
p == q
bool
Remarks: For any two values o and o2, if p is obtained from o converted to P or from a copy of such P value and if q is obtained from o2 converted to P or from a copy of such P value, then p == q is true only if o == o2 is true.
p != q
bool
!(p == q)
p + o
P
+ offset
Remarks: With ql = p + o;, then: ql - o == p
pl += o
P&
+= offset
Remarks: With ql = pl; before the +=, then: pl - o == ql
p - o
P
- offset
Remarks: With ql = p - o;, then: ql + o == p
pl -= o
P&
-= offset
Remarks: With ql = pl; before the -=, then: pl + o == ql
o + p
convertible to P
p + o
P(o + p) == p + o
p - q
streamoff
distance
p == q + (p - q)
Stream operations that return a value of type traits​::​pos_type return P(O(-1)) as an invalid value to signal an error.
If this value is used as an argument to any istream, ostream, or streambuf member that accepts a value of type traits​::​pos_type then the behavior of that function is undefined.

31.5.4 Class template basic_ios [ios]

31.5.4.1 Overview [ios.overview]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_ios : public ios_base { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [iostate.flags], flags functions explicit operator bool() const; bool operator!() const; iostate rdstate() const; void clear(iostate state = goodbit); void setstate(iostate state); bool good() const; bool eof() const; bool fail() const; bool bad() const; iostate exceptions() const; void exceptions(iostate except); // [basic.ios.cons], constructor/destructor explicit basic_ios(basic_streambuf<charT, traits>* sb); virtual ~basic_ios(); // [basic.ios.members], members basic_ostream<charT, traits>* tie() const; basic_ostream<charT, traits>* tie(basic_ostream<charT, traits>* tiestr); basic_streambuf<charT, traits>* rdbuf() const; basic_streambuf<charT, traits>* rdbuf(basic_streambuf<charT, traits>* sb); basic_ios& copyfmt(const basic_ios& rhs); char_type fill() const; char_type fill(char_type ch); locale imbue(const locale& loc); char narrow(char_type c, char dfault) const; char_type widen(char c) const; basic_ios(const basic_ios&) = delete; basic_ios& operator=(const basic_ios&) = delete; protected: basic_ios(); void init(basic_streambuf<charT, traits>* sb); void move(basic_ios& rhs); void move(basic_ios&& rhs); void swap(basic_ios& rhs) noexcept; void set_rdbuf(basic_streambuf<charT, traits>* sb); }; }

31.5.4.2 Constructors [basic.ios.cons]

explicit basic_ios(basic_streambuf<charT, traits>* sb);
Effects: Assigns initial values to its member objects by calling init(sb).
basic_ios();
Effects: Leaves its member objects uninitialized.
The object shall be initialized by calling basic_ios​::​init before its first use or before it is destroyed, whichever comes first; otherwise the behavior is undefined.
~basic_ios();
Remarks: The destructor does not destroy rdbuf().
void init(basic_streambuf<charT, traits>* sb);
Postconditions: The postconditions of this function are indicated in Table 137.
Table 137basic_ios​::​init() effects [tab:basic.ios.cons]
Element
Value
rdbuf()
sb
tie()
0
rdstate()
goodbit if sb is not a null pointer, otherwise badbit.
exceptions()
goodbit
flags()
skipws | dec
width()
0
precision()
6
fill()
widen(' ')
getloc()
a copy of the value returned by locale()
iarray
a null pointer
parray
a null pointer

31.5.4.3 Member functions [basic.ios.members]

basic_ostream<charT, traits>* tie() const;
Returns: An output sequence that is tied to (synchronized with) the sequence controlled by the stream buffer.
basic_ostream<charT, traits>* tie(basic_ostream<charT, traits>* tiestr);
Preconditions: If tiestr is not null, tiestr is not reachable by traversing the linked list of tied stream objects starting from tiestr->tie().
Postconditions: tiestr == tie().
Returns: The previous value of tie().
basic_streambuf<charT, traits>* rdbuf() const;
Returns: A pointer to the streambuf associated with the stream.
basic_streambuf<charT, traits>* rdbuf(basic_streambuf<charT, traits>* sb);
Effects: Calls clear().
Postconditions: sb == rdbuf().
Returns: The previous value of rdbuf().
locale imbue(const locale& loc);
Effects: Calls ios_base​::​imbue(loc) and if rdbuf() != 0 then rdbuf()->pubimbue(loc).
Returns: The prior value of ios_base​::​imbue().
char narrow(char_type c, char dfault) const;
Returns: use_facet<ctype<char_type>>(getloc()).narrow(c, dfault)
char_type widen(char c) const;
Returns: use_facet<ctype<char_type>>(getloc()).widen(c)
char_type fill() const;
Returns: The character used to pad (fill) an output conversion to the specified field width.
char_type fill(char_type fillch);
Postconditions: traits​::​eq(fillch, fill()).
Returns: The previous value of fill().
basic_ios& copyfmt(const basic_ios& rhs);
Effects: If (this == addressof(rhs)) is true does nothing.
Otherwise assigns to the member objects of *this the corresponding member objects of rhs as follows:
  • calls each registered callback pair (fn, idx) as (*fn)(erase_event, *this, idx);
  • then, assigns to the member objects of *this the corresponding member objects of rhs, except that
    • rdstate(), rdbuf(), and exceptions() are left unchanged;
    • the contents of arrays pointed at by pword and iword are copied, not the pointers themselves;267 and
    • if any newly stored pointer values in *this point at objects stored outside the object rhs and those objects are destroyed when rhs is destroyed, the newly stored pointer values are altered to point at newly constructed copies of the objects;
  • then, calls each callback pair that was copied from rhs as (*fn)(copyfmt_event, *this, idx);
  • then, calls exceptions(rhs.exceptions()).
[Note 1: 
The second pass through the callback pairs permits a copied pword value to be zeroed, or to have its referent deep copied or reference counted, or to have other special action taken.
— end note]
Postconditions: The postconditions of this function are indicated in Table 138.
Table 138basic_ios​::​copyfmt() effects [tab:basic.ios.copyfmt]
Element
Value
rdbuf()
unchanged
tie()
rhs.tie()
rdstate()
unchanged
exceptions()
rhs.exceptions()
flags()
rhs.flags()
width()
rhs.width()
precision()
rhs.precision()
fill()
rhs.fill()
getloc()
rhs.getloc()
Returns: *this.
void move(basic_ios& rhs); void move(basic_ios&& rhs);
Postconditions: *this has the state that rhs had before the function call, except that rdbuf() returns nullptr.
rhs is in a valid but unspecified state, except that rhs.rdbuf() returns the same value as it returned before the function call, and rhs.tie() returns nullptr.
void swap(basic_ios& rhs) noexcept;
Effects: The states of *this and rhs are exchanged, except that rdbuf() returns the same value as it returned before the function call, and rhs.rdbuf() returns the same value as it returned before the function call.
void set_rdbuf(basic_streambuf<charT, traits>* sb);
Preconditions: sb != nullptr is true.
Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear().
Postconditions: rdbuf() == sb is true.
Throws: Nothing.
267)267)
This suggests an infinite amount of copying, but the implementation can keep track of the maximum element of the arrays that is nonzero.

31.5.4.4 Flags functions [iostate.flags]

explicit operator bool() const;
Returns: !fail().
bool operator!() const;
Returns: fail().
iostate rdstate() const;
Returns: The error state of the stream buffer.
void clear(iostate state = goodbit);
Effects: If ((state | (rdbuf() ? goodbit : badbit)) & exceptions()) == 0, returns.
Otherwise, the function throws an object of class ios_base​::​failure ([ios.failure]), constructed with implementation-defined argument values.
Postconditions: If rdbuf() != 0 then state == rdstate(); otherwise rdstate() == (state | ios_base​::​badbit).
void setstate(iostate state);
Effects: Calls clear(rdstate() | state) (which may throw ios_base​::​failure ([ios.failure])).
bool good() const;
Returns: rdstate() == 0
bool eof() const;
Returns: true if eofbit is set in rdstate().
bool fail() const;
Returns: true if failbit or badbit is set in rdstate().268
bool bad() const;
Returns: true if badbit is set in rdstate().
iostate exceptions() const;
Returns: A mask that determines what elements set in rdstate() cause exceptions to be thrown.
void exceptions(iostate except);
Effects: Calls clear(rdstate()).
Postconditions: except == exceptions().
268)268)
Checking badbit also for fail() is historical practice.

31.5.5 ios_base manipulators [std.ios.manip]

31.5.5.1 fmtflags manipulators [fmtflags.manip]

Each function specified in this subclause is a designated addressable function ([namespace.std]).
ios_base& boolalpha(ios_base& str);
Effects: Calls str.setf(ios_base​::​boolalpha).
Returns: str.
ios_base& noboolalpha(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​boolalpha).
Returns: str.
ios_base& showbase(ios_base& str);
Effects: Calls str.setf(ios_base​::​showbase).
Returns: str.
ios_base& noshowbase(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​showbase).
Returns: str.
ios_base& showpoint(ios_base& str);
Effects: Calls str.setf(ios_base​::​showpoint).
Returns: str.
ios_base& noshowpoint(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​showpoint).
Returns: str.
ios_base& showpos(ios_base& str);
Effects: Calls str.setf(ios_base​::​showpos).
Returns: str.
ios_base& noshowpos(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​showpos).
Returns: str.
ios_base& skipws(ios_base& str);
Effects: Calls str.setf(ios_base​::​skipws).
Returns: str.
ios_base& noskipws(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​skipws).
Returns: str.
ios_base& uppercase(ios_base& str);
Effects: Calls str.setf(ios_base​::​uppercase).
Returns: str.
ios_base& nouppercase(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​uppercase).
Returns: str.
ios_base& unitbuf(ios_base& str);
Effects: Calls str.setf(ios_base​::​unitbuf).
Returns: str.
ios_base& nounitbuf(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​unitbuf).
Returns: str.

31.5.5.2 adjustfield manipulators [adjustfield.manip]

Each function specified in this subclause is a designated addressable function ([namespace.std]).
ios_base& internal(ios_base& str);
Effects: Calls str.setf(ios_base​::​internal, ios_base​::​adjustfield).
Returns: str.
ios_base& left(ios_base& str);
Effects: Calls str.setf(ios_base​::​left, ios_base​::​adjustfield).
Returns: str.
ios_base& right(ios_base& str);
Effects: Calls str.setf(ios_base​::​right, ios_base​::​adjustfield).
Returns: str.

31.5.5.3 basefield manipulators [basefield.manip]

Each function specified in this subclause is a designated addressable function ([namespace.std]).
ios_base& dec(ios_base& str);
Effects: Calls str.setf(ios_base​::​dec, ios_base​::​basefield).
Returns: str.269
ios_base& hex(ios_base& str);
Effects: Calls str.setf(ios_base​::​hex, ios_base​::​basefield).
Returns: str.
ios_base& oct(ios_base& str);
Effects: Calls str.setf(ios_base​::​oct, ios_base​::​basefield).
Returns: str.
269)269)
The function signature dec(ios_base&) can be called by the function signature basic_ostream& stream​::​operator<<(ios_base& (*)(ios_base&)) to permit expressions of the form cout << dec to change the format flags stored in cout.

31.5.5.4 floatfield manipulators [floatfield.manip]

Each function specified in this subclause is a designated addressable function ([namespace.std]).
ios_base& fixed(ios_base& str);
Effects: Calls str.setf(ios_base​::​fixed, ios_base​::​floatfield).
Returns: str.
ios_base& scientific(ios_base& str);
Effects: Calls str.setf(ios_base​::​scientific, ios_base​::​floatfield).
Returns: str.
ios_base& hexfloat(ios_base& str);
Effects: Calls str.setf(ios_base​::​fixed | ios_base​::​scientific, ios_base​::​floatfield).
Returns: str.
[Note 1: 
ios_base​::​hex cannot be used to specify a hexadecimal floating-point format, because it is not part of ios_base​::​floatfield (Table 132).
— end note]
ios_base& defaultfloat(ios_base& str);
Effects: Calls str.unsetf(ios_base​::​floatfield).
Returns: str.

31.5.6 Error reporting [error.reporting]

error_code make_error_code(io_errc e) noexcept;
Returns: error_code(static_cast<int>(e), iostream_category()).
error_condition make_error_condition(io_errc e) noexcept;
Returns: error_condition(static_cast<int>(e), iostream_category()).
const error_category& iostream_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
The object's default_error_condition and equivalent virtual functions shall behave as specified for the class error_category.
The object's name virtual function shall return a pointer to the string "iostream".

31.6 Stream buffers [stream.buffers]

31.6.1 Header <streambuf> synopsis [streambuf.syn]

namespace std { // [streambuf], class template basic_streambuf template<class charT, class traits = char_traits<charT>> class basic_streambuf; using streambuf = basic_streambuf<char>; using wstreambuf = basic_streambuf<wchar_t>; }
The header <streambuf> defines types that control input from and output to character sequences.

31.6.2 Stream buffer requirements [streambuf.reqts]

Stream buffers can impose various constraints on the sequences they control.
Some constraints are:
  • The controlled input sequence can be not readable.
  • The controlled output sequence can be not writable.
  • The controlled sequences can be associated with the contents of other representations for character sequences, such as external files.
  • The controlled sequences can support operations directly to or from associated sequences.
  • The controlled sequences can impose limitations on how the program can read characters from a sequence, write characters to a sequence, put characters back into an input sequence, or alter the stream position.
Each sequence is characterized by three pointers which, if non-null, all point into the same charT array object.
The array object represents, at any moment, a (sub)sequence of characters from the sequence.
Operations performed on a sequence alter the values stored in these pointers, perform reads and writes directly to or from associated sequences, and alter “the stream position” and conversion state as needed to maintain this subsequence relationship.
The three pointers are:
  • the beginning pointer, or lowest element address in the array (called xbeg here);
  • the next pointer, or next element address that is a current candidate for reading or writing (called xnext here);
  • the end pointer, or first element address beyond the end of the array (called xend here).
The following semantic constraints shall always apply for any set of three pointers for a sequence, using the pointer names given immediately above:
  • If xnext is not a null pointer, then xbeg and xend shall also be non-null pointers into the same charT array, as described above; otherwise, xbeg and xend shall also be null.
  • If xnext is not a null pointer and xnext < xend for an output sequence, then a write position is available.
    In this case, *xnext shall be assignable as the next element to write (to put, or to store a character value, into the sequence).
  • If xnext is not a null pointer and xbeg < xnext for an input sequence, then a putback position is available.
    In this case, xnext[-1] shall have a defined value and is the next (preceding) element to store a character that is put back into the input sequence.
  • If xnext is not a null pointer and xnext < xend for an input sequence, then a read position is available.
    In this case, *xnext shall have a defined value and is the next element to read (to get, or to obtain a character value, from the sequence).

31.6.3 Class template basic_streambuf [streambuf]

31.6.3.1 General [streambuf.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_streambuf { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; virtual ~basic_streambuf(); // [streambuf.locales], locales locale pubimbue(const locale& loc); locale getloc() const; // [streambuf.buffer], buffer and positioning basic_streambuf* pubsetbuf(char_type* s, streamsize n); pos_type pubseekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out); pos_type pubseekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out); int pubsync(); // get and put areas // [streambuf.pub.get], get area streamsize in_avail(); int_type snextc(); int_type sbumpc(); int_type sgetc(); streamsize sgetn(char_type* s, streamsize n); // [streambuf.pub.pback], putback int_type sputbackc(char_type c); int_type sungetc(); // [streambuf.pub.put], put area int_type sputc(char_type c); streamsize sputn(const char_type* s, streamsize n); protected: basic_streambuf(); basic_streambuf(const basic_streambuf& rhs); basic_streambuf& operator=(const basic_streambuf& rhs); void swap(basic_streambuf& rhs); // [streambuf.get.area], get area access char_type* eback() const; char_type* gptr() const; char_type* egptr() const; void gbump(int n); void setg(char_type* gbeg, char_type* gnext, char_type* gend); // [streambuf.put.area], put area access char_type* pbase() const; char_type* pptr() const; char_type* epptr() const; void pbump(int n); void setp(char_type* pbeg, char_type* pend); // [streambuf.virtuals], virtual functions // [streambuf.virt.locales], locales virtual void imbue(const locale& loc); // [streambuf.virt.buffer], buffer management and positioning virtual basic_streambuf* setbuf(char_type* s, streamsize n); virtual pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out); virtual pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out); virtual int sync(); // [streambuf.virt.get], get area virtual streamsize showmanyc(); virtual streamsize xsgetn(char_type* s, streamsize n); virtual int_type underflow(); virtual int_type uflow(); // [streambuf.virt.pback], putback virtual int_type pbackfail(int_type c = traits::eof()); // [streambuf.virt.put], put area virtual streamsize xsputn(const char_type* s, streamsize n); virtual int_type overflow(int_type c = traits::eof()); }; }
The class template basic_streambuf serves as a base class for deriving various stream buffers whose objects each control two character sequences:

31.6.3.2 Constructors [streambuf.cons]

basic_streambuf();
Effects: Initializes:270
  • all pointer member objects to null pointers,
  • the getloc() member to a copy of the global locale, locale(), at the time of construction.
Remarks: Once the getloc() member is initialized, results of calling locale member functions, and of members of facets so obtained, can safely be cached until the next time the member imbue is called.
basic_streambuf(const basic_streambuf& rhs);
Postconditions:
  • eback() == rhs.eback()
  • gptr() == rhs.gptr()
  • egptr() == rhs.egptr()
  • pbase() == rhs.pbase()
  • pptr() == rhs.pptr()
  • epptr() == rhs.epptr()
  • getloc() == rhs.getloc()
~basic_streambuf();
Effects: None.
270)270)
The default constructor is protected for class basic_streambuf to assure that only objects for classes derived from this class can be constructed.

31.6.3.3 Public member functions [streambuf.members]

31.6.3.3.1 Locales [streambuf.locales]

locale pubimbue(const locale& loc);
Effects: Calls imbue(loc).
Postconditions: loc == getloc().
Returns: Previous value of getloc().
locale getloc() const;
Returns: If pubimbue() has ever been called, then the last value of loc supplied, otherwise the current global locale, locale(), in effect at the time of construction.
If called after pubimbue() has been called but before pubimbue has returned (i.e., from within the call of imbue()) then it returns the previous value.

31.6.3.3.2 Buffer management and positioning [streambuf.buffer]

basic_streambuf* pubsetbuf(char_type* s, streamsize n);
Returns: setbuf(s, n).
pos_type pubseekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out);
Returns: seekoff(off, way, which).
pos_type pubseekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out);
Returns: seekpos(sp, which).
int pubsync();
Returns: sync().

31.6.3.3.3 Get area [streambuf.pub.get]

streamsize in_avail();
Returns: If a read position is available, returns egptr() - gptr().
Otherwise returns showmanyc().
int_type snextc();
Effects: Calls sbumpc().
Returns: If that function returns traits​::​eof(), returns traits​::​eof().
Otherwise, returns sgetc().
int_type sbumpc();
Effects: If the input sequence read position is not available, returns uflow().
Otherwise, returns traits​::​to_int_type(*gptr()) and increments the next pointer for the input sequence.
int_type sgetc();
Returns: If the input sequence read position is not available, returns underflow().
Otherwise, returns traits​::​to_int_type(*gptr()).
streamsize sgetn(char_type* s, streamsize n);
Returns: xsgetn(s, n).

31.6.3.3.4 Putback [streambuf.pub.pback]

int_type sputbackc(char_type c);
Effects: If the input sequence putback position is not available, or if traits​::​eq(c, gptr()[-1]) is false, returns pbackfail(traits​::​to_int_type(c)).
Otherwise, decrements the next pointer for the input sequence and returns traits​::​to_int_type(*gptr()).
int_type sungetc();
Effects: If the input sequence putback position is not available, returns pbackfail().
Otherwise, decrements the next pointer for the input sequence and returns traits​::​to_int_type(*gptr()).

31.6.3.3.5 Put area [streambuf.pub.put]

int_type sputc(char_type c);
Effects: If the output sequence write position is not available, returns overflow(traits​::​to_int_type(c)).
Otherwise, stores c at the next pointer for the output sequence, increments the pointer, and returns traits​::​to_int_type(c).
streamsize sputn(const char_type* s, streamsize n);
Returns: xsputn(s, n).

31.6.3.4 Protected member functions [streambuf.protected]

31.6.3.4.1 Assignment [streambuf.assign]

basic_streambuf& operator=(const basic_streambuf& rhs);
Postconditions:
  • eback() == rhs.eback()
  • gptr() == rhs.gptr()
  • egptr() == rhs.egptr()
  • pbase() == rhs.pbase()
  • pptr() == rhs.pptr()
  • epptr() == rhs.epptr()
  • getloc() == rhs.getloc()
Returns: *this.
void swap(basic_streambuf& rhs);
Effects: Swaps the data members of rhs and *this.

31.6.3.4.2 Get area access [streambuf.get.area]

char_type* eback() const;
Returns: The beginning pointer for the input sequence.
char_type* gptr() const;
Returns: The next pointer for the input sequence.
char_type* egptr() const;
Returns: The end pointer for the input sequence.
void gbump(int n);
Effects: Adds n to the next pointer for the input sequence.
void setg(char_type* gbeg, char_type* gnext, char_type* gend);
Preconditions: [gbeg, gnext), [gbeg, gend), and [gnext, gend) are all valid ranges.
Postconditions: gbeg == eback(), gnext == gptr(), and gend == egptr() are all true.

31.6.3.4.3 Put area access [streambuf.put.area]

char_type* pbase() const;
Returns: The beginning pointer for the output sequence.
char_type* pptr() const;
Returns: The next pointer for the output sequence.
char_type* epptr() const;
Returns: The end pointer for the output sequence.
void pbump(int n);
Effects: Adds n to the next pointer for the output sequence.
void setp(char_type* pbeg, char_type* pend);
Preconditions: [pbeg, pend) is a valid range.
Postconditions: pbeg == pbase(), pbeg == pptr(), and pend == epptr() are all true.

31.6.3.5 Virtual functions [streambuf.virtuals]

31.6.3.5.1 Locales [streambuf.virt.locales]

void imbue(const locale&);
Effects: Change any translations based on locale.
Remarks: Allows the derived class to be informed of changes in locale at the time they occur.
Between invocations of this function a class derived from streambuf can safely cache results of calls to locale functions and to members of facets so obtained.
Default behavior: Does nothing.

31.6.3.5.2 Buffer management and positioning [streambuf.virt.buffer]

basic_streambuf* setbuf(char_type* s, streamsize n);
Effects: Influences stream buffering in a way that is defined separately for each class derived from basic_streambuf in this Clause ([stringbuf.virtuals], [filebuf.virtuals]).
Default behavior: Does nothing.
Returns this.
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Alters the stream positions within one or more of the controlled sequences in a way that is defined separately for each class derived from basic_streambuf in this Clause ([stringbuf.virtuals], [filebuf.virtuals]).
Default behavior: Returns pos_type(off_type(-1)).
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Alters the stream positions within one or more of the controlled sequences in a way that is defined separately for each class derived from basic_streambuf in this Clause ([stringbuf], [filebuf]).
Default behavior: Returns pos_type(off_type(-1)).
int sync();
Effects: Synchronizes the controlled sequences with the arrays.
That is, if pbase() is non-null the characters between pbase() and pptr() are written to the controlled sequence.
The pointers may then be reset as appropriate.
Returns: -1 on failure.
What constitutes failure is determined by each derived class ([filebuf.virtuals]).
Default behavior: Returns zero.

31.6.3.5.3 Get area [streambuf.virt.get]

streamsize showmanyc();271
Returns: An estimate of the number of characters available in the sequence, or .
If it returns a positive value, then successive calls to underflow() will not return traits​::​eof() until at least that number of characters have been extracted from the stream.
If showmanyc() returns , then calls to underflow() or uflow() will fail.272
Default behavior: Returns zero.
Remarks: Uses traits​::​eof().
streamsize xsgetn(char_type* s, streamsize n);
Effects: Assigns up to n characters to successive elements of the array whose first element is designated by s.
The characters assigned are read from the input sequence as if by repeated calls to sbumpc().
Assigning stops when either n characters have been assigned or a call to sbumpc() would return traits​::​eof().
Returns: The number of characters assigned.273
Remarks: Uses traits​::​eof().
int_type underflow();
The pending sequence of characters is defined as the concatenation of
  • the empty sequence if gptr() is null, otherwise the characters in [gptr(), egptr()), followed by
  • some (possibly empty) sequence of characters read from the input sequence.
The result character is the first character of the pending sequence if it is non-empty, otherwise the next character that would be read from the input sequence.
The backup sequence is the empty sequence if eback() is null, otherwise the characters in [eback(), gptr()).
Effects: The function sets up the gptr() and egptr() such that if the pending sequence is non-empty, then egptr() is non-null and the characters in [gptr(), egptr()) are the characters in the pending sequence, otherwise either gptr() is null or gptr() == egptr().
If eback() and gptr() are non-null then the function is not constrained as to their contents, but the “usual backup condition” is that either
  • the backup sequence contains at least gptr() - eback() characters, in which case the characters in [eback(), gptr()) agree with the last gptr() - eback() characters of the backup sequence, or
  • the characters in [gptr() - n, gptr()) agree with the backup sequence (where n is the length of the backup sequence).
Returns: traits​::​to_int_type(c), where c is the first character of the pending sequence, without moving the input sequence position past it.
If the pending sequence is null then the function returns traits​::​eof() to indicate failure.
Default behavior: Returns traits​::​eof().
Remarks: The public members of basic_streambuf call this virtual function only if gptr() is null or gptr() >= egptr().
int_type uflow();
Preconditions: The constraints are the same as for underflow(), except that the result character is transferred from the pending sequence to the backup sequence, and the pending sequence is not empty before the transfer.
Default behavior: Calls underflow().
If underflow() returns traits​::​eof(), returns traits​::​eof().
Otherwise, returns the value of traits​::​to_int_type(*gptr()) and increments the value of the next pointer for the input sequence.
Returns: traits​::​eof() to indicate failure.
271)271)
The morphemes of showmanyc are “es-how-many-see”, not “show-manic”.
272)272)
underflow or uflow can fail by throwing an exception prematurely.
The intention is not only that the calls will not return eof() but that they will return “immediately”.
273)273)
Classes derived from basic_streambuf can provide more efficient ways to implement xsgetn() and xsputn() by overriding these definitions from the base class.

31.6.3.5.4 Putback [streambuf.virt.pback]

int_type pbackfail(int_type c = traits::eof());
The pending sequence is defined as for underflow(), with the modifications that
  • If traits​::​eq_int_type(c, traits​::​eof()) returns true, then the input sequence is backed up one character before the pending sequence is determined.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false, then c is prepended.
    Whether the input sequence is backed up or modified in any other way is unspecified.
Postconditions: On return, the constraints of gptr(), eback(), and pptr() are the same as for underflow().
Returns: traits​::​eof() to indicate failure.
Failure may occur because the input sequence could not be backed up, or if for some other reason the pointers cannot be set consistent with the constraints.
pbackfail() is called only when put back has really failed.
Returns some value other than traits​::​eof() to indicate success.
Default behavior: Returns traits​::​eof().
Remarks: The public functions of basic_streambuf call this virtual function only when gptr() is null, gptr() == eback(), or traits​::​eq(traits​::​to_char_type(c), gptr()[-1]) returns false.
Other calls shall also satisfy that constraint.

31.6.3.5.5 Put area [streambuf.virt.put]

streamsize xsputn(const char_type* s, streamsize n);
Effects: Writes up to n characters to the output sequence as if by repeated calls to sputc(c).
The characters written are obtained from successive elements of the array whose first element is designated by s.
Writing stops when either n characters have been written or a call to sputc(c) would return traits​::​eof().
It is unspecified whether the function calls overflow() when pptr() == epptr() becomes true or whether it achieves the same effects by other means.
Returns: The number of characters written.
int_type overflow(int_type c = traits::eof());
Effects: Consumes some initial subsequence of the characters of the pending sequence.
The pending sequence is defined as the concatenation of
  • the empty sequence if pbase() is null, otherwise the pptr() - pbase() characters beginning at pbase(), followed by
  • the empty sequence if traits​::​eq_int_type(c, traits​::​eof()) returns true, otherwise the sequence consisting of c.
Preconditions: Every overriding definition of this virtual function obeys the following constraints:
  • The effect of consuming a character on the associated output sequence is specified.274
  • Let r be the number of characters in the pending sequence not consumed.
    If r is nonzero then pbase() and pptr() are set so that: pptr() - pbase() == r and the r characters starting at pbase() are the associated output stream.
    In case r is zero (all characters of the pending sequence have been consumed) then either pbase() is set to nullptr, or pbase() and pptr() are both set to the same non-null value.
  • The function may fail if either appending some character to the associated output stream fails or if it is unable to establish pbase() and pptr() according to the above rules.
Returns: traits​::​eof() or throws an exception if the function fails.
Otherwise, returns some value other than traits​::​eof() to indicate success.275
Default behavior: Returns traits​::​eof().
Remarks: The member functions sputc() and sputn() call this function in case that no room can be found in the put buffer enough to accommodate the argument character sequence.
274)274)
That is, for each class derived from a specialization of basic_streambuf in this Clause ([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.
275)275)
Typically, overflow returns c to indicate success, except when traits​::​eq_int_type(c, traits​::​eof()) returns true, in which case it returns traits​::​not_eof(c).

31.7 Formatting and manipulators [iostream.format]

31.7.1 Header <istream> synopsis [istream.syn]

namespace std { // [istream], class template basic_istream template<class charT, class traits = char_traits<charT>> class basic_istream; using istream = basic_istream<char>; using wistream = basic_istream<wchar_t>; // [iostreamclass], class template basic_iostream template<class charT, class traits = char_traits<charT>> class basic_iostream; using iostream = basic_iostream<char>; using wiostream = basic_iostream<wchar_t>; // [istream.manip], standard basic_istream manipulators template<class charT, class traits> basic_istream<charT, traits>& ws(basic_istream<charT, traits>& is); // [istream.rvalue], rvalue stream extraction template<class Istream, class T> Istream&& operator>>(Istream&& is, T&& x); }

31.7.2 Header <ostream> synopsis [ostream.syn]

namespace std { // [ostream], class template basic_ostream template<class charT, class traits = char_traits<charT>> class basic_ostream; using ostream = basic_ostream<char>; using wostream = basic_ostream<wchar_t>; // [ostream.manip], standard basic_ostream manipulators template<class charT, class traits> basic_ostream<charT, traits>& endl(basic_ostream<charT, traits>& os); template<class charT, class traits> basic_ostream<charT, traits>& ends(basic_ostream<charT, traits>& os); template<class charT, class traits> basic_ostream<charT, traits>& flush(basic_ostream<charT, traits>& os); template<class charT, class traits> basic_ostream<charT, traits>& emit_on_flush(basic_ostream<charT, traits>& os); template<class charT, class traits> basic_ostream<charT, traits>& noemit_on_flush(basic_ostream<charT, traits>& os); template<class charT, class traits> basic_ostream<charT, traits>& flush_emit(basic_ostream<charT, traits>& os); // [ostream.rvalue], rvalue stream insertion template<class Ostream, class T> Ostream&& operator<<(Ostream&& os, const T& x); // [ostream.formatted.print], print functions template<class... Args> void print(ostream& os, format_string<Args...> fmt, Args&&... args); template<class... Args> void println(ostream& os, format_string<Args...> fmt, Args&&... args); void println(ostream& os); void vprint_unicode(ostream& os, string_view fmt, format_args args); void vprint_nonunicode(ostream& os, string_view fmt, format_args args); }

31.7.3 Header <iomanip> synopsis [iomanip.syn]

namespace std { // [std.manip], standard manipulators unspecified resetiosflags(ios_base::fmtflags mask); unspecified setiosflags (ios_base::fmtflags mask); unspecified setbase(int base); template<class charT> unspecified setfill(charT c); unspecified setprecision(int n); unspecified setw(int n); // [ext.manip], extended manipulators template<class moneyT> unspecified get_money(moneyT& mon, bool intl = false); template<class moneyT> unspecified put_money(const moneyT& mon, bool intl = false); template<class charT> unspecified get_time(tm* tmb, const charT* fmt); template<class charT> unspecified put_time(const tm* tmb, const charT* fmt); // [quoted.manip], quoted manipulators template<class charT> unspecified quoted(const charT* s, charT delim = charT('"'), charT escape = charT('\\')); template<class charT, class traits, class Allocator> unspecified quoted(const basic_string<charT, traits, Allocator>& s, charT delim = charT('"'), charT escape = charT('\\')); template<class charT, class traits, class Allocator> unspecified quoted(basic_string<charT, traits, Allocator>& s, charT delim = charT('"'), charT escape = charT('\\')); template<class charT, class traits> unspecified quoted(basic_string_view<charT, traits> s, charT delim = charT('"'), charT escape = charT('\\')); }

31.7.4 Header <print> synopsis [print.syn]

namespace std { // [print.fun], print functions template<class... Args> void print(format_string<Args...> fmt, Args&&... args); template<class... Args> void print(FILE* stream, format_string<Args...> fmt, Args&&... args); template<class... Args> void println(format_string<Args...> fmt, Args&&... args); void println(); template<class... Args> void println(FILE* stream, format_string<Args...> fmt, Args&&... args); void println(FILE* stream); void vprint_unicode(string_view fmt, format_args args); void vprint_unicode(FILE* stream, string_view fmt, format_args args); void vprint_unicode_buffered(FILE* stream, string_view fmt, format_args args); void vprint_nonunicode(string_view fmt, format_args args); void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); void vprint_nonunicode_buffered(FILE* stream, string_view fmt, format_args args); }

31.7.5 Input streams [input.streams]

31.7.5.1 General [input.streams.general]

The header <istream> defines two class templates and a function template that control input from a stream buffer, along with a function template that extracts from stream rvalues.

31.7.5.2 Class template basic_istream [istream]

31.7.5.2.1 General [istream.general]

When a function is specified with a type placeholder of extended-floating-point-type, the implementation provides overloads for all cv-unqualified extended floating-point types ([basic.fundamental]) in lieu of extended-floating-​point-type.
namespace std { template<class charT, class traits = char_traits<charT>> class basic_istream : virtual public basic_ios<charT, traits> { public: // types (inherited from basic_ios) using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [istream.cons], constructor/destructor explicit basic_istream(basic_streambuf<charT, traits>* sb); virtual ~basic_istream(); // [istream.sentry], prefix/suffix class sentry; // [istream.formatted], formatted input basic_istream& operator>>(basic_istream& (*pf)(basic_istream&)); basic_istream& operator>>(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&)); basic_istream& operator>>(ios_base& (*pf)(ios_base&)); basic_istream& operator>>(bool& n); basic_istream& operator>>(short& n); basic_istream& operator>>(unsigned short& n); basic_istream& operator>>(int& n); basic_istream& operator>>(unsigned int& n); basic_istream& operator>>(long& n); basic_istream& operator>>(unsigned long& n); basic_istream& operator>>(long long& n); basic_istream& operator>>(unsigned long long& n); basic_istream& operator>>(float& f); basic_istream& operator>>(double& f); basic_istream& operator>>(long double& f); basic_istream& operator>>(extended-floating-point-type& f); basic_istream& operator>>(void*& p); basic_istream& operator>>(basic_streambuf<char_type, traits>* sb); // [istream.unformatted], unformatted input streamsize gcount() const; int_type get(); basic_istream& get(char_type& c); basic_istream& get(char_type* s, streamsize n); basic_istream& get(char_type* s, streamsize n, char_type delim); basic_istream& get(basic_streambuf<char_type, traits>& sb); basic_istream& get(basic_streambuf<char_type, traits>& sb, char_type delim); basic_istream& getline(char_type* s, streamsize n); basic_istream& getline(char_type* s, streamsize n, char_type delim); basic_istream& ignore(streamsize n = 1, int_type delim = traits::eof()); int_type peek(); basic_istream& read (char_type* s, streamsize n); streamsize readsome(char_type* s, streamsize n); basic_istream& putback(char_type c); basic_istream& unget(); int sync(); pos_type tellg(); basic_istream& seekg(pos_type); basic_istream& seekg(off_type, ios_base::seekdir); protected: // [istream.cons], copy/move constructor basic_istream(const basic_istream&) = delete; basic_istream(basic_istream&& rhs); // [istream.assign], assignment and swap basic_istream& operator=(const basic_istream&) = delete; basic_istream& operator=(basic_istream&& rhs); void swap(basic_istream& rhs); }; // [istream.extractors], character extraction templates template<class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, charT&); template<class traits> basic_istream<char, traits>& operator>>(basic_istream<char, traits>&, unsigned char&); template<class traits> basic_istream<char, traits>& operator>>(basic_istream<char, traits>&, signed char&); template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, charT(&)[N]); template<class traits, size_t N> basic_istream<char, traits>& operator>>(basic_istream<char, traits>&, unsigned char(&)[N]); template<class traits, size_t N> basic_istream<char, traits>& operator>>(basic_istream<char, traits>&, signed char(&)[N]); }
The class template basic_istream defines a number of member function signatures that assist in reading and interpreting input from sequences controlled by a stream buffer.
Two groups of member function signatures share common properties: the formatted input functions (or extractors) and the unformatted input functions. Both groups of input functions are described as if they obtain (or extract) input characters by calling rdbuf()->sbumpc() or rdbuf()->sgetc().
They may use other public members of istream.

31.7.5.2.2 Constructors [istream.cons]

explicit basic_istream(basic_streambuf<charT, traits>* sb);
Effects: Initializes the base class subobject with basic_ios​::​init(sb) ([basic.ios.cons]).
Postconditions: gcount() == 0.
basic_istream(basic_istream&& rhs);
Effects: Default constructs the base class, copies the gcount() from rhs, calls basic_ios<charT, traits>​::​move(rhs) to initialize the base class, and sets the gcount() for rhs to 0.
virtual ~basic_istream();
Remarks: Does not perform any operations of rdbuf().

31.7.5.2.3 Assignment and swap [istream.assign]

basic_istream& operator=(basic_istream&& rhs);
Effects: Equivalent to swap(rhs).
Returns: *this.
void swap(basic_istream& rhs);
Effects: Calls basic_ios<charT, traits>​::​swap(rhs).
Exchanges the values returned by gcount() and rhs.gcount().

31.7.5.2.4 Class basic_istream​::​sentry [istream.sentry]

namespace std { template<class charT, class traits> class basic_istream<charT, traits>::sentry { bool ok_; // exposition only public: explicit sentry(basic_istream& is, bool noskipws = false); ~sentry(); explicit operator bool() const { return ok_; } sentry(const sentry&) = delete; sentry& operator=(const sentry&) = delete; }; }
The class sentry defines a class that is responsible for doing exception safe prefix and suffix operations.
explicit sentry(basic_istream& is, bool noskipws = false);
Effects: If is.good() is false, calls is.setstate(failbit).
Otherwise, prepares for formatted or unformatted input.
First, if is.tie() is not a null pointer, the function calls is.tie()->flush() to synchronize the output sequence with any associated external C stream.
Except that this call can be suppressed if the put area of is.tie() is empty.
Further an implementation is allowed to defer the call to flush until a call of is.rdbuf()->underflow() occurs.
If no such call occurs before the sentry object is destroyed, the call to flush may be eliminated entirely.276
If noskipws is zero and is.flags() & ios_base​::​skipws is nonzero, the function extracts and discards each character as long as the next available input character c is a whitespace character.
If is.rdbuf()->sbumpc() or is.rdbuf()->sgetc() returns traits​::​eof(), the function calls setstate(failbit | eofbit) (which may throw ios_base​::​failure).
Remarks: The constructor explicit sentry(basic_istream& is, bool noskipws = false) uses the currently imbued locale in is, to determine whether the next input character is whitespace or not.
To decide if the character c is a whitespace character, the constructor performs as if it executes the following code fragment: const ctype<charT>& ctype = use_facet<ctype<charT>>(is.getloc()); if (ctype.is(ctype.space, c) != 0) // c is a whitespace character.
If, after any preparation is completed, is.good() is true, ok_ != false otherwise, ok_ == false.
During preparation, the constructor may call setstate(failbit) (which may throw ios_base​::​​failure ([iostate.flags])).277
~sentry();
Effects: None.
explicit operator bool() const;
Returns: ok_.
276)276)
This will be possible only in functions that are part of the library.
The semantics of the constructor used in user code is as specified.
277)277)
The sentry constructor and destructor can also perform additional implementation-dependent operations.

31.7.5.3 Formatted input functions [istream.formatted]

31.7.5.3.1 Common requirements [istream.formatted.reqmts]

Each formatted input function begins execution by constructing an object of type ios_base​::​iostate, termed the local error state, and initializing it to ios_base​::​goodbit.
It then creates an object of class sentry with the noskipws (second) argument false.
If the sentry object returns true, when converted to a value of type bool, the function endeavors to obtain the requested input.
Otherwise, if the sentry constructor exits by throwing an exception or if the sentry object produces false when converted to a value of type bool, the function returns without attempting to obtain any input.
If rdbuf()->sbumpc() or rdbuf()->sgetc() returns traits​::​eof(), then ios_base​::​eofbit is set in the local error state and the input function stops trying to obtain the requested input.
If an exception is thrown during input then ios_base​::​badbit is set in the local error state, *this's error state is set to the local error state, and the exception is rethrown if (exceptions() & badbit) != 0.
After extraction is done, the input function calls setstate, which sets *this's error state to the local error state, and may throw an exception.
In any case, the formatted input function destroys the sentry object.
If no exception has been thrown, it returns *this.

31.7.5.3.2 Arithmetic extractors [istream.formatted.arithmetic]

basic_istream& operator>>(unsigned short& val); basic_istream& operator>>(unsigned int& val); basic_istream& operator>>(long& val); basic_istream& operator>>(unsigned long& val); basic_istream& operator>>(long long& val); basic_istream& operator>>(unsigned long long& val); basic_istream& operator>>(float& val); basic_istream& operator>>(double& val); basic_istream& operator>>(long double& val); basic_istream& operator>>(bool& val); basic_istream& operator>>(void*& val);
As in the case of the inserters, these extractors depend on the locale's num_get<> object to perform parsing the input stream data.
These extractors behave as formatted input functions (as described in [istream.formatted.reqmts]).
After a sentry object is constructed, the conversion occurs as if performed by the following code fragment, where state represents the input function's local error state: using numget = num_get<charT, istreambuf_iterator<charT, traits>>; use_facet<numget>(loc).get(*this, 0, *this, state, val);
In the above fragment, loc stands for the private member of the basic_ios class.
[Note 1: 
The first argument provides an object of the istreambuf_iterator class which is an iterator pointed to an input stream.
It bypasses istreams and uses streambufs directly.
— end note]
Class locale relies on this type as its interface to istream, so that it does not need to depend directly on istream.
basic_istream& operator>>(short& val);
The conversion occurs as if performed by the following code fragment (using the same notation as for the preceding code fragment): using numget = num_get<charT, istreambuf_iterator<charT, traits>>; long lval; use_facet<numget>(loc).get(*this, 0, *this, state, lval); if (lval < numeric_limits<short>::min()) { state |= ios_base::failbit; val = numeric_limits<short>::min(); } else if (numeric_limits<short>::max() < lval) { state |= ios_base::failbit; val = numeric_limits<short>::max(); } else val = static_cast<short>(lval);
basic_istream& operator>>(int& val);
The conversion occurs as if performed by the following code fragment (using the same notation as for the preceding code fragment): using numget = num_get<charT, istreambuf_iterator<charT, traits>>; long lval; use_facet<numget>(loc).get(*this, 0, *this, state, lval); if (lval < numeric_limits<int>::min()) { state |= ios_base::failbit; val = numeric_limits<int>::min(); } else if (numeric_limits<int>::max() < lval) { state |= ios_base::failbit; val = numeric_limits<int>::max(); } else val = static_cast<int>(lval);
basic_istream& operator>>(extended-floating-point-type& val);
If the floating-point conversion rank of extended-floating-point-type is not less than or equal to that of long double, then an invocation of the operator function is conditionally supported with implementation-defined semantics.
Otherwise, let FP be a standard floating-point type:
  • if the floating-point conversion rank of extended-floating-point-type is less than or equal to that of float, then FP is float,
  • otherwise, if the floating-point conversion rank of extended-floating-point-type is less than or equal to that of double, then FP is double,
  • otherwise, FP is long double.
The conversion occurs as if performed by the following code fragment (using the same notation as for the preceding code fragment): using numget = num_get<charT, istreambuf_iterator<charT, traits>>; FP fval; use_facet<numget>(loc).get(*this, 0, *this, state, fval); if (fval < -numeric_limits<extended-floating-point-type>::max()) { state |= ios_base::failbit; val = -numeric_limits<extended-floating-point-type>::max(); } else if (numeric_limits<extended-floating-point-type>::max() < fval) { state |= ios_base::failbit; val = numeric_limits<extended-floating-point-type>::max(); } else { val = static_cast<extended-floating-point-type>(fval); }
[Note 2: 
When the extended floating-point type has a floating-point conversion rank that is not equal to the rank of any standard floating-point type, then double rounding during the conversion can result in inaccurate results.
from_chars can be used in situations where maximum accuracy is important.
— end note]

31.7.5.3.3 basic_istream​::​operator>> [istream.extractors]

basic_istream& operator>>(basic_istream& (*pf)(basic_istream&));
Effects: None.
This extractor does not behave as a formatted input function (as described in [istream.formatted.reqmts]).
Returns: pf(*this).
278
basic_istream& operator>>(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&));
Effects: Calls pf(*this).
This extractor does not behave as a formatted input function (as described in [istream.formatted.reqmts]).
Returns: *this.
basic_istream& operator>>(ios_base& (*pf)(ios_base&));
Effects: Calls pf(*this).279
This extractor does not behave as a formatted input function (as described in [istream.formatted.reqmts]).
Returns: *this.
template<class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& in, charT (&s)[N]); template<class traits, size_t N> basic_istream<char, traits>& operator>>(basic_istream<char, traits>& in, unsigned char (&s)[N]); template<class traits, size_t N> basic_istream<char, traits>& operator>>(basic_istream<char, traits>& in, signed char (&s)[N]);
Effects: Behaves like a formatted input member (as described in [istream.formatted.reqmts]) of in.
After a sentry object is constructed, operator>> extracts characters and stores them into s.
If width() is greater than zero, n is min(size_t(width()), N).
Otherwise n is N.
n is the maximum number of characters stored.
Characters are extracted and stored until any of the following occurs:
  • n-1 characters are stored;
  • end of file occurs on the input sequence;
  • letting ct be use_facet<ctype<charT>>(in.getloc()), ct.is(ct.space, c) is true.
operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted.
operator>> then calls width(0).
If the function extracted no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: in.
template<class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& in, charT& c); template<class traits> basic_istream<char, traits>& operator>>(basic_istream<char, traits>& in, unsigned char& c); template<class traits> basic_istream<char, traits>& operator>>(basic_istream<char, traits>& in, signed char& c);
Effects: Behaves like a formatted input member (as described in [istream.formatted.reqmts]) of in.
A character is extracted from in, if one is available, and stored in c.
Otherwise, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: in.
basic_istream& operator>>(basic_streambuf<charT, traits>* sb);
Effects: Behaves as an unformatted input function.
If sb is null, calls setstate(failbit), which may throw ios_base​::​failure ([iostate.flags]).
After a sentry object is constructed, extracts characters from *this and inserts them in the output sequence controlled by sb.
Characters are extracted and inserted until any of the following occurs:
  • end-of-file occurs on the input sequence;
  • inserting in the output sequence fails (in which case the character to be inserted is not extracted);
  • an exception occurs (in which case the exception is caught).
If the function inserts no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: *this.
278)278)
See, for example, the function signature ws(basic_istream&) ([istream.manip]).
279)279)
See, for example, the function signature dec(ios_base&) ([basefield.manip]).

31.7.5.4 Unformatted input functions [istream.unformatted]

Each unformatted input function begins execution by constructing an object of type ios_base​::​iostate, termed the local error state, and initializing it to ios_base​::​goodbit.
It then creates an object of class sentry with the default argument noskipws (second) argument true.
If the sentry object returns true, when converted to a value of type bool, the function endeavors to obtain the requested input.
Otherwise, if the sentry constructor exits by throwing an exception or if the sentry object produces false, when converted to a value of type bool, the function returns without attempting to obtain any input.
In either case the number of extracted characters is set to 0; unformatted input functions taking a character array of nonzero size as an argument shall also store a null character (using charT()) in the first location of the array.
If rdbuf()->sbumpc() or rdbuf()->sgetc() returns traits​::​eof(), then ios_base​::​eofbit is set in the local error state and the input function stops trying to obtain the requested input.
If an exception is thrown during input then ios_base​::​badbit is set in the local error state, *this's error state is set to the local error state, and the exception is rethrown if (exceptions() & badbit) != 0.
If no exception has been thrown it stores the number of characters extracted in a member object.
After extraction is done, the input function calls setstate, which sets *this's error state to the local error state, and may throw an exception.
In any event the sentry object is destroyed before leaving the unformatted input function.
streamsize gcount() const;
Effects: None.
This member function does not behave as an unformatted input function (as described above).
Returns: The number of characters extracted by the last unformatted input member function called for the object.
If the number cannot be represented, returns numeric_limits<streamsize>​::​max().
int_type get();
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts a character c, if one is available.
Otherwise, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: c if available, otherwise traits​::​eof().
basic_istream& get(char_type& c);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts a character, if one is available, and assigns it to c.280
Otherwise, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: *this.
basic_istream& get(char_type* s, streamsize n, char_type delim);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts characters and stores them into successive locations of an array whose first element is designated by s.281
Characters are extracted and stored until any of the following occurs:
  • n is less than one or n - 1 characters are stored;
  • end-of-file occurs on the input sequence;
  • traits​::​eq(c, delim) for the next available input character c (in which case c is not extracted).
If the function stores no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
In any case, if n is greater than zero it then stores a null character into the next successive location of the array.
Returns: *this.
basic_istream& get(char_type* s, streamsize n);
Effects: Calls get(s, n, widen('\n')).
Returns: Value returned by the call.
basic_istream& get(basic_streambuf<char_type, traits>& sb, char_type delim);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts characters and inserts them in the output sequence controlled by sb.
Characters are extracted and inserted until any of the following occurs:
  • end-of-file occurs on the input sequence;
  • inserting in the output sequence fails (in which case the character to be inserted is not extracted);
  • traits​::​eq(c, delim) for the next available input character c (in which case c is not extracted);
  • an exception occurs (in which case, the exception is caught but not rethrown).
If the function inserts no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.
Returns: *this.
basic_istream& get(basic_streambuf<char_type, traits>& sb);
Effects: Calls get(sb, widen('\n')).
Returns: Value returned by the call.
basic_istream& getline(char_type* s, streamsize n, char_type delim);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts characters and stores them into successive locations of an array whose first element is designated by s.282
Characters are extracted and stored until one of the following occurs:
1.end-of-file occurs on the input sequence;
2.traits​::​eq(c, delim) for the next available input character c (in which case the input character is extracted but not stored);283
3.n is less than one or n - 1 characters are stored (in which case the function calls setstate(​failbit)).
These conditions are tested in the order shown.284
If the function extracts no characters, ios_base​::​failbit is set in the input function's local error state before setstate is called.285
In any case, if n is greater than zero, it then stores a null character (using charT()) into the next successive location of the array.
Returns: *this.
[Example 1: #include <iostream> int main() { using namespace std; const int line_buffer_size = 100; char buffer[line_buffer_size]; int line_number = 0; while (cin.getline(buffer, line_buffer_size, '\n') || cin.gcount()) { int count = cin.gcount(); if (cin.eof()) cout << "Partial final line"; // cin.fail() is false else if (cin.fail()) { cout << "Partial long line"; cin.clear(cin.rdstate() & ~ios_base::failbit); } else { count--; // Don't include newline in count cout << "Line " << ++line_number; } cout << " (" << count << " chars): " << buffer << endl; } } — end example]
basic_istream& getline(char_type* s, streamsize n);
Returns: getline(s, n, widen('\n'))
basic_istream& ignore(streamsize n = 1, int_type delim = traits::eof());
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, extracts characters and discards them.
Characters are extracted until any of the following occurs:
  • n != numeric_limits<streamsize>​::​max()numeric.limits and n characters have been extracted so far;
  • end-of-file occurs on the input sequence (in which case the function calls setstate(eofbit), which may throw ios_base​::​failure ([iostate.flags]));
  • traits​::​eq_int_type(traits​::​to_int_type(c), delim) for the next available input character c (in which case c is extracted).
[Note 1: 
The last condition will never occur if traits​::​eq_int_type(delim, traits​::​eof()).
— end note]
Returns: *this.
int_type peek();
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, reads but does not extract the current input character.
Returns: traits​::​eof() if good() is false.
Otherwise, returns rdbuf()->sgetc().
basic_istream& read(char_type* s, streamsize n);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, if !good() calls setstate(failbit) which may throw an exception, and return.
Otherwise extracts characters and stores them into successive locations of an array whose first element is designated by s.286
Characters are extracted and stored until either of the following occurs:
  • n characters are stored;
  • end-of-file occurs on the input sequence (in which case the function calls setstate(failbit | eofbit), which may throw ios_base​::​failure ([iostate.flags])).
Returns: *this.
streamsize readsome(char_type* s, streamsize n);
Effects: Behaves as an unformatted input function (as described above).
After constructing a sentry object, if !good() calls setstate(failbit) which may throw an exception, and return.
Otherwise extracts characters and stores them into successive locations of an array whose first element is designated by s.
If rdbuf()->in_avail() == -1, calls setstate(eofbit) (which may throw ios_base​::​failure ([iostate.flags])), and extracts no characters;
  • If rdbuf()->in_avail() == 0, extracts no characters
  • If rdbuf()->in_avail() > 0, extracts min(rdbuf()->in_avail(), n)).
Returns: The number of characters extracted.
basic_istream& putback(char_type c);
Effects: Behaves as an unformatted input function (as described above), except that the function first clears eofbit.
After constructing a sentry object, if !good() calls setstate(failbit) which may throw an exception, and return.
If rdbuf() is not null, calls rdbuf()->sputbackc(c).
If rdbuf() is null, or if sputbackc returns traits​::​eof(), calls setstate(badbit) (which may throw ios_base​::​failure ([iostate.flags])).
[Note 2: 
This function extracts no characters, so the value returned by the next call to gcount() is 0.
— end note]
Returns: *this.
basic_istream& unget();
Effects: Behaves as an unformatted input function (as described above), except that the function first clears eofbit.
After constructing a sentry object, if !good() calls setstate(failbit) which may throw an exception, and return.
If rdbuf() is not null, calls rdbuf()->sungetc().
If rdbuf() is null, or if sungetc returns traits​::​eof(), calls setstate(badbit) (which may throw ios_base​::​failure ([iostate.flags])).
[Note 3: 
This function extracts no characters, so the value returned by the next call to gcount() is 0.
— end note]
Returns: *this.
int sync();
Effects: Behaves as an unformatted input function (as described above), except that it does not count the number of characters extracted and does not affect the value returned by subsequent calls to gcount().
After constructing a sentry object, if rdbuf() is a null pointer, returns -1.
Otherwise, calls rdbuf()->pubsync() and, if that function returns -1 calls setstate(badbit) (which may throw ios_base​::​failure ([iostate.flags]), and returns -1.
Otherwise, returns zero.
pos_type tellg();
Effects: Behaves as an unformatted input function (as described above), except that it does not count the number of characters extracted and does not affect the value returned by subsequent calls to gcount().
Returns: After constructing a sentry object, if fail() != false, returns pos_type(-1) to indicate failure.
Otherwise, returns rdbuf()->pubseekoff(0, cur, in).
basic_istream& seekg(pos_type pos);
Effects: Behaves as an unformatted input function (as described above), except that the function first clears eofbit, it does not count the number of characters extracted, and it does not affect the value returned by subsequent calls to gcount().
After constructing a sentry object, if fail() != true, executes rdbuf()->pubseekpos(pos, ios_base​::​in).
In case of failure, the function calls setstate(failbit) (which may throw ios_base​::​failure).
Returns: *this.
basic_istream& seekg(off_type off, ios_base::seekdir dir);
Effects: Behaves as an unformatted input function (as described above), except that the function first clears eofbit, does not count the number of characters extracted, and does not affect the value returned by subsequent calls to gcount().
After constructing a sentry object, if fail() != true, executes rdbuf()->pubseekoff(off, dir, ios_base​::​in).
In case of failure, the function calls setstate(​failbit) (which may throw ios_base​::​failure).
Returns: *this.
280)280)
Note that this function is not overloaded on types signed char and unsigned char.
281)281)
Note that this function is not overloaded on types signed char and unsigned char.
282)282)
Note that this function is not overloaded on types signed char and unsigned char.
283)283)
Since the final input character is “extracted”, it is counted in the gcount(), even though it is not stored.
284)284)
This allows an input line which exactly fills the buffer, without setting failbit.
This is different behavior than the historical AT&T implementation.
285)285)
This implies an empty input line will not cause failbit to be set.
286)286)
Note that this function is not overloaded on types signed char and unsigned char.

31.7.5.5 Standard basic_istream manipulators [istream.manip]

Each instantiation of the function template specified in this subclause is a designated addressable function ([namespace.std]).
template<class charT, class traits> basic_istream<charT, traits>& ws(basic_istream<charT, traits>& is);
Effects: Behaves as an unformatted input function, except that it does not count the number of characters extracted and does not affect the value returned by subsequent calls to is.gcount().
After constructing a sentry object extracts characters as long as the next available character c is whitespace or until there are no more characters in the sequence.
Whitespace characters are distinguished with the same criterion as used by sentry​::​sentry.
If ws stops extracting characters because there are no more available it sets eofbit, but not failbit.
Returns: is.

31.7.5.6 Rvalue stream extraction [istream.rvalue]

template<class Istream, class T> Istream&& operator>>(Istream&& is, T&& x);
Constraints: The expression is >> std​::​forward<T>(x) is well-formed when treated as an unevaluated operand and Istream is publicly and unambiguously derived from ios_base.
Effects: Equivalent to: is >> std::forward<T>(x); return std::move(is);

31.7.5.7 Class template basic_iostream [iostreamclass]

31.7.5.7.1 General [iostreamclass.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [iostream.cons], constructor explicit basic_iostream(basic_streambuf<charT, traits>* sb); // [iostream.dest], destructor virtual ~basic_iostream(); protected: // [iostream.cons], constructor basic_iostream(const basic_iostream&) = delete; basic_iostream(basic_iostream&& rhs); // [iostream.assign], assignment and swap basic_iostream& operator=(const basic_iostream&) = delete; basic_iostream& operator=(basic_iostream&& rhs); void swap(basic_iostream& rhs); }; }
The class template basic_iostream inherits a number of functions that allow reading input and writing output to sequences controlled by a stream buffer.

31.7.5.7.2 Constructors [iostream.cons]

explicit basic_iostream(basic_streambuf<charT, traits>* sb);
Effects: Initializes the base class subobjects with basic_istream<charT, traits>(sb) ([istream]) and basic_ostream<charT, traits>(sb).
Postconditions: rdbuf() == sb and gcount() == 0.
basic_iostream(basic_iostream&& rhs);
Effects: Move constructs from the rvalue rhs by constructing the basic_istream base class with std​::​move(rhs).

31.7.5.7.3 Destructor [iostream.dest]

virtual ~basic_iostream();
Remarks: Does not perform any operations on rdbuf().

31.7.5.7.4 Assignment and swap [iostream.assign]

basic_iostream& operator=(basic_iostream&& rhs);
Effects: Equivalent to swap(rhs).
void swap(basic_iostream& rhs);
Effects: Calls basic_istream<charT, traits>​::​swap(rhs).

31.7.6 Output streams [output.streams]

31.7.6.1 General [output.streams.general]

The header <ostream> defines a class template and several function templates that control output to a stream buffer, along with a function template that inserts into stream rvalues.

31.7.6.2 Class template basic_ostream [ostream]

31.7.6.2.1 General [ostream.general]

When a function has a parameter type extended-floating-point-type, the implementation provides overloads for all cv-unqualified extended floating-point types ([basic.fundamental]).
namespace std { template<class charT, class traits = char_traits<charT>> class basic_ostream : virtual public basic_ios<charT, traits> { public: // types (inherited from basic_ios) using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [ostream.cons], constructor/destructor explicit basic_ostream(basic_streambuf<char_type, traits>* sb); virtual ~basic_ostream(); // [ostream.sentry], prefix/suffix class sentry; // [ostream.formatted], formatted output basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&)); basic_ostream& operator<<(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&)); basic_ostream& operator<<(ios_base& (*pf)(ios_base&)); basic_ostream& operator<<(bool n); basic_ostream& operator<<(short n); basic_ostream& operator<<(unsigned short n); basic_ostream& operator<<(int n); basic_ostream& operator<<(unsigned int n); basic_ostream& operator<<(long n); basic_ostream& operator<<(unsigned long n); basic_ostream& operator<<(long long n); basic_ostream& operator<<(unsigned long long n); basic_ostream& operator<<(float f); basic_ostream& operator<<(double f); basic_ostream& operator<<(long double f); basic_ostream& operator<<(extended-floating-point-type f); basic_ostream& operator<<(const void* p); basic_ostream& operator<<(const volatile void* p); basic_ostream& operator<<(nullptr_t); basic_ostream& operator<<(basic_streambuf<char_type, traits>* sb); // [ostream.unformatted], unformatted output basic_ostream& put(char_type c); basic_ostream& write(const char_type* s, streamsize n); basic_ostream& flush(); // [ostream.seeks], seeks pos_type tellp(); basic_ostream& seekp(pos_type); basic_ostream& seekp(off_type, ios_base::seekdir); protected: // [ostream.cons], copy/move constructor basic_ostream(const basic_ostream&) = delete; basic_ostream(basic_ostream&& rhs); // [ostream.assign], assignment and swap basic_ostream& operator=(const basic_ostream&) = delete; basic_ostream& operator=(basic_ostream&& rhs); void swap(basic_ostream& rhs); }; // [ostream.inserters.character], character inserters template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, charT); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, char); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, signed char); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, unsigned char); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, wchar_t) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char8_t) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char16_t) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, char32_t) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char8_t) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char16_t) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, char32_t) = delete; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const charT*); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const signed char*); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const unsigned char*); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const wchar_t*) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char8_t*) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char16_t*) = delete; template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char32_t*) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char8_t*) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char16_t*) = delete; template<class traits> basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, const char32_t*) = delete; }
The class template basic_ostream defines a number of member function signatures that assist in formatting and writing output to output sequences controlled by a stream buffer.
Two groups of member function signatures share common properties: the formatted output functions (or inserters) and the unformatted output functions. Both groups of output functions generate (or insert) output characters by actions equivalent to calling rdbuf()->sputc(int_type).
They may use other public members of basic_ostream except that they shall not invoke any virtual members of rdbuf() except overflow(), xsputn(), and sync().
If one of these called functions throws an exception, then unless explicitly noted otherwise the output function sets badbit in the error state.
If badbit is set in exceptions(), the output function rethrows the exception without completing its actions, otherwise it does not throw anything and proceeds as if the called function had returned a failure indication.
[Note 1: 
The deleted overloads of operator<< prevent formatting characters as integers and strings as pointers.
— end note]

31.7.6.2.2 Constructors [ostream.cons]

explicit basic_ostream(basic_streambuf<charT, traits>* sb);
Effects: Initializes the base class subobject with basic_ios<charT, traits>​::​init(sb) ([basic.ios.cons]).
Postconditions: rdbuf() == sb.
basic_ostream(basic_ostream&& rhs);
Effects: Move constructs from the rvalue rhs.
This is accomplished by default constructing the base class and calling basic_ios<charT, traits>​::​move(rhs) to initialize the base class.
virtual ~basic_ostream();
Remarks: Does not perform any operations on rdbuf().

31.7.6.2.3 Assignment and swap [ostream.assign]

basic_ostream& operator=(basic_ostream&& rhs);
Effects: Equivalent to swap(rhs).
Returns: *this.
void swap(basic_ostream& rhs);
Effects: Calls basic_ios<charT, traits>​::​swap(rhs).

31.7.6.2.4 Class basic_ostream​::​sentry [ostream.sentry]

namespace std { template<class charT, class traits> class basic_ostream<charT, traits>::sentry { bool ok_; // exposition only public: explicit sentry(basic_ostream& os); ~sentry(); explicit operator bool() const { return ok_; } sentry(const sentry&) = delete; sentry& operator=(const sentry&) = delete; }; }
The class sentry defines a class that is responsible for doing exception safe prefix and suffix operations.
explicit sentry(basic_ostream& os);
If os.good() is nonzero, prepares for formatted or unformatted output.
If os.tie() is not a null pointer, calls os.tie()->flush().287
If, after any preparation is completed, os.good() is true, ok_ == true otherwise, ok_ == false.
During preparation, the constructor may call setstate(failbit) (which may throw ios_base​::​​failure ([iostate.flags])).288
~sentry();
If (os.flags() & ios_base​::​unitbuf) && !uncaught_exceptions() && os.good() is true, calls os.rdbuf()->pubsync().
If that function returns , sets badbit in os.rdstate() without propagating an exception.
explicit operator bool() const;
Effects: Returns ok_.
287)287)
The call os.tie()->flush() does not necessarily occur if the function can determine that no synchronization is necessary.
288)288)
The sentry constructor and destructor can also perform additional implementation-dependent operations.

31.7.6.2.5 Seek members [ostream.seeks]

Each seek member function begins execution by constructing an object of class sentry.
It returns by destroying the sentry object.
pos_type tellp();
Returns: If fail() != false, returns pos_type(-1) to indicate failure.
Otherwise, returns rdbuf()->​pubseekoff(0, cur, out).
basic_ostream& seekp(pos_type pos);
Effects: If fail() != true, executes rdbuf()->pubseekpos(pos, ios_base​::​out).
In case of failure, the function calls setstate(failbit) (which may throw ios_base​::​failure).
Returns: *this.
basic_ostream& seekp(off_type off, ios_base::seekdir dir);
Effects: If fail() != true, executes rdbuf()->pubseekoff(off, dir, ios_base​::​out).
In case of failure, the function calls setstate(failbit) (which may throw ios_base​::​failure).
Returns: *this.

31.7.6.3 Formatted output functions [ostream.formatted]

31.7.6.3.1 Common requirements [ostream.formatted.reqmts]

Each formatted output function begins execution by constructing an object of class sentry.
If that object returns true when converted to a value of type bool, the function endeavors to generate the requested output.
If the generation fails, then the formatted output function does setstate(ios_base​::​failbit), which can throw an exception.
If an exception is thrown during output, then ios_base​::​badbit is set289 in *this's error state.
If (exceptions()&badbit) != 0 then the exception is rethrown.
Whether or not an exception is thrown, the sentry object is destroyed before leaving the formatted output function.
If no exception is thrown, the result of the formatted output function is *this.
The descriptions of the individual formatted output functions describe how they perform output and do not mention the sentry object.
If a formatted output function of a stream os determines padding, it does so as follows.
Given a charT character sequence seq where charT is the character container type of the stream, if the length of seq is less than os.width(), then enough copies of os.fill() are added to this sequence as necessary to pad to a width of os.width() characters.
If (os.flags() & ios_base​::​adjustfield) == ios_base​::​left is true, the fill characters are placed after the character sequence; otherwise, they are placed before the character sequence.
289)289)
This is done without causing an ios_base​::​failure to be thrown.

31.7.6.3.2 Arithmetic inserters [ostream.inserters.arithmetic]

basic_ostream& operator<<(bool val); basic_ostream& operator<<(short val); basic_ostream& operator<<(unsigned short val); basic_ostream& operator<<(int val); basic_ostream& operator<<(unsigned int val); basic_ostream& operator<<(long val); basic_ostream& operator<<(unsigned long val); basic_ostream& operator<<(long long val); basic_ostream& operator<<(unsigned long long val); basic_ostream& operator<<(float val); basic_ostream& operator<<(double val); basic_ostream& operator<<(long double val); basic_ostream& operator<<(const void* val);
Effects: The classes num_get<> and num_put<> handle locale-dependent numeric formatting and parsing.
These inserter functions use the imbued locale value to perform numeric formatting.
When val is of type bool, long, unsigned long, long long, unsigned long long, double, long double, or const void*, the formatting conversion occurs as if it performed the following code fragment: bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), val).failed();
When val is of type short the formatting conversion occurs as if it performed the following code fragment: ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), baseflags == ios_base::oct || baseflags == ios_base::hex ? static_cast<long>(static_cast<unsigned short>(val)) : static_cast<long>(val)).failed();
When val is of type int the formatting conversion occurs as if it performed the following code fragment: ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), baseflags == ios_base::oct || baseflags == ios_base::hex ? static_cast<long>(static_cast<unsigned int>(val)) : static_cast<long>(val)).failed();
When val is of type unsigned short or unsigned int the formatting conversion occurs as if it performed the following code fragment: bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), static_cast<unsigned long>(val)).failed();
When val is of type float the formatting conversion occurs as if it performed the following code fragment: bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), static_cast<double>(val)).failed();
The first argument provides an object of the ostreambuf_iterator<> class which is an iterator for class basic_ostream<>.
It bypasses ostreams and uses streambufs directly.
Class locale relies on these types as its interface to iostreams, since for flexibility it has been abstracted away from direct dependence on ostream.
The second parameter is a reference to the base class subobject of type ios_base.
It provides formatting specifications such as field width, and a locale from which to obtain other facets.
If failed is true then does setstate(badbit), which may throw an exception, and returns.
Returns: *this.
basic_ostream& operator<<(const volatile void* p);
Effects: Equivalent to: return operator<<(const_cast<const void*>(p));
basic_ostream& operator<<(extended-floating-point-type val);
Effects: If the floating-point conversion rank of extended-floating-point-type is less than or equal to that of double, the formatting conversion occurs as if it performed the following code fragment: bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), static_cast<double>(val)).failed();
Otherwise, if the floating-point conversion rank of extended-floating-point-type is less than or equal to that of long double, the formatting conversion occurs as if it performed the following code fragment: bool failed = use_facet<num_put<charT, ostreambuf_iterator<charT, traits>>>( getloc()).put(*this, *this, fill(), static_cast<long double>(val)).failed();
Otherwise, an invocation of the operator function is conditionally supported with implementation-defined semantics.
If failed is true then does setstate(badbit), which may throw an exception, and returns.
Returns: *this.

31.7.6.3.3 basic_ostream​::​operator<< [ostream.inserters]

basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&));
Effects: None.
Does not behave as a formatted output function (as described in [ostream.formatted.reqmts]).
Returns: pf(*this).290
basic_ostream& operator<<(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&));
Effects: Calls pf(*this).
This inserter does not behave as a formatted output function (as described in [ostream.formatted.reqmts]).
Returns: *this.291
basic_ostream& operator<<(ios_base& (*pf)(ios_base&));
Effects: Calls pf(*this).
This inserter does not behave as a formatted output function (as described in [ostream.formatted.reqmts]).
Returns: *this.
basic_ostream& operator<<(basic_streambuf<charT, traits>* sb);
Effects: Behaves as an unformatted output function ([ostream.unformatted]).
After the sentry object is constructed, if sb is null calls setstate(badbit) (which may throw ios_base​::​failure).
Gets characters from sb and inserts them in *this.
Characters are read from sb and inserted until any of the following occurs:
  • end-of-file occurs on the input sequence;
  • inserting in the output sequence fails (in which case the character to be inserted is not extracted);
  • an exception occurs while getting a character from sb.
If the function inserts no characters, it calls setstate(failbit) (which may throw ios_base​::​​failure ([iostate.flags])).
If an exception was thrown while extracting a character, the function sets failbit in the error state, and if failbit is set in exceptions() the caught exception is rethrown.
Returns: *this.
basic_ostream& operator<<(nullptr_t);
Effects: Equivalent to: return *this << s; where s is an implementation-defined NTCTS.
290)290)
See, for example, the function signature endl(basic_ostream&) ([ostream.manip]).
291)291)
See, for example, the function signature dec(ios_base&) ([basefield.manip]).

31.7.6.3.4 Character inserter function templates [ostream.inserters.character]

template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, charT c); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, char c); // specialization template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, char c); // signed and unsigned template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, signed char c); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, unsigned char c);
Effects: Behaves as a formatted output function of out.
Constructs a character sequence seq.
If c has type char and the character container type of the stream is not char, then seq consists of out.widen(c); otherwise seq consists of c.
Determines padding for seq as described in [ostream.formatted.reqmts].
Inserts seq into out.
Calls os.width(0).
Returns: out.
template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, const charT* s); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, const char* s); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, const char* s); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, const signed char* s); template<class traits> basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>& out, const unsigned char* s);
Preconditions: s is not a null pointer.
Effects: Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of out.
Creates a character sequence seq of n characters starting at s, each widened using out.widen() ([basic.ios.members]), where n is the number that would be computed as if by:
  • traits​::​length(s) for the overload where the first argument is of type basic_ostream<charT, traits>& and the second is of type const charT*, and also for the overload where the first argument is of type basic_ostream<char, traits>& and the second is of type const char*,
  • char_traits<char>​::​length(s) for the overload where the first argument is of type basic_ostream<charT, traits>& and the second is of type const char*,
  • traits​::​length(reinterpret_cast<const char*>(s)) for the other two overloads.
Determines padding for seq as described in [ostream.formatted.reqmts].
Inserts seq into out.
Calls width(0).
Returns: out.

31.7.6.3.5 Print [ostream.formatted.print]

template<class... Args> void print(ostream& os, format_string<Args...> fmt, Args&&... args);
Effects: If the ordinary literal encoding ([lex.charset]) is UTF-8, equivalent to: vprint_unicode(os, fmt.str, make_format_args(args...));
Otherwise, equivalent to: vprint_nonunicode(os, fmt.str, make_format_args(args...));
template<class... Args> void println(ostream& os, format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: print(os, "{}\n", format(os.getloc(), fmt, std::forward<Args>(args)...));
void println(ostream& os);
Effects: Equivalent to: print(os, "\n");
void vprint_unicode(ostream& os, string_view fmt, format_args args); void vprint_nonunicode(ostream& os, string_view fmt, format_args args);
Effects: Behaves as a formatted output function ([ostream.formatted.reqmts]) of os, except that:
  • failure to generate output is reported as specified below, and
  • any exception thrown by the call to vformat is propagated without regard to the value of os.exceptions() and without turning on ios_base​::​badbit in the error state of os.
After constructing a sentry object, the function initializes a variable with automatic storage duration via string out = vformat(os.getloc(), fmt, args);
  • If the function is vprint_unicode and os is a stream that refers to a terminal that is capable of displaying Unicode only via a native Unicode API, which is determined in an implementation-defined manner, flushes os and then writes out to the terminal using the native Unicode API; if out contains invalid code units, the behavior is undefined.
  • Otherwise inserts the character sequence [out.begin(), out.end()) into os.
If writing to the terminal or inserting into os fails, calls os.setstate(ios_base​::​badbit) (which may throw ios_base​::​failure).
Recommended practice: For vprint_unicode, if invoking the native Unicode API requires transcoding, implementations should substitute invalid code units with U+fffd replacement character per the Unicode Standard, Chapter 3.9 U+fffd Substitution in Conversion.

31.7.6.4 Unformatted output functions [ostream.unformatted]

Each unformatted output function begins execution by constructing an object of class sentry.
If that object returns true, while converting to a value of type bool, the function endeavors to generate the requested output.
If an exception is thrown during output, then ios_base​::​badbit is set292 in *this's error state.
If (exceptions() & badbit) != 0 then the exception is rethrown.
In any case, the unformatted output function ends by destroying the sentry object, then, if no exception was thrown, returning the value specified for the unformatted output function.
basic_ostream& put(char_type c);
Effects: Behaves as an unformatted output function (as described above).
After constructing a sentry object, inserts the character c, if possible.293
Otherwise, calls setstate(badbit) (which may throw ios_base​::​failure ([iostate.flags])).
Returns: *this.
basic_ostream& write(const char_type* s, streamsize n);
Effects: Behaves as an unformatted output function (as described above).
After constructing a sentry object, obtains characters to insert from successive locations of an array whose first element is designated by s.294
Characters are inserted until either of the following occurs:
  • n characters are inserted;
  • inserting in the output sequence fails (in which case the function calls setstate(badbit), which may throw ios_base​::​failure ([iostate.flags])).
Returns: *this.
basic_ostream& flush();
Effects: Behaves as an unformatted output function (as described above).
If rdbuf() is not a null pointer, constructs a sentry object.
If that object returns true when converted to a value of type bool the function calls rdbuf()->pubsync().
If that function returns calls setstate(badbit) (which may throw ios_base​::​failure ([iostate.flags])).
Otherwise, if the sentry object returns false, does nothing.
Returns: *this.
292)292)
This is done without causing an ios_base​::​failure to be thrown.
293)293)
Note that this function is not overloaded on types signed char and unsigned char.
294)294)
Note that this function is not overloaded on types signed char and unsigned char.

31.7.6.5 Standard basic_ostream manipulators [ostream.manip]

Each instantiation of any of the function templates specified in this subclause is a designated addressable function ([namespace.std]).
template<class charT, class traits> basic_ostream<charT, traits>& endl(basic_ostream<charT, traits>& os);
Effects: Calls os.put(os.widen('\n')), then os.flush().
Returns: os.
template<class charT, class traits> basic_ostream<charT, traits>& ends(basic_ostream<charT, traits>& os);
Effects: Inserts a null character into the output sequence: calls os.put(charT()).
Returns: os.
template<class charT, class traits> basic_ostream<charT, traits>& flush(basic_ostream<charT, traits>& os);
Effects: Calls os.flush().
Returns: os.
template<class charT, class traits> basic_ostream<charT, traits>& emit_on_flush(basic_ostream<charT, traits>& os);
Effects: If os.rdbuf() is a basic_syncbuf<charT, traits, Allocator>*, called buf for the purpose of exposition, calls buf->set_emit_on_sync(true).
Otherwise this manipulator has no effect.
[Note 1: 
To work around the issue that the Allocator template argument cannot be deduced, implementations can introduce an intermediate base class to basic_syncbuf that manages its emit-on-sync flag.
— end note]
Returns: os.
template<class charT, class traits> basic_ostream<charT, traits>& noemit_on_flush(basic_ostream<charT, traits>& os);
Effects: If os.rdbuf() is a basic_syncbuf<charT, traits, Allocator>*, called buf for the purpose of exposition, calls buf->set_emit_on_sync(false).
Otherwise this manipulator has no effect.
Returns: os.
template<class charT, class traits> basic_ostream<charT, traits>& flush_emit(basic_ostream<charT, traits>& os);
Effects: Calls os.flush().
Then, if os.rdbuf() is a basic_syncbuf<charT, traits, Allocator>*, called buf for the purpose of exposition, behaves as an unformatted output function ([ostream.unformatted]) of os.
After constructing a sentry object, calls buf->emit().
If that call returns false, calls os.setstate(ios_base​::​badbit).
Returns: os.

31.7.6.6 Rvalue stream insertion [ostream.rvalue]

template<class Ostream, class T> Ostream&& operator<<(Ostream&& os, const T& x);
Constraints: The expression os << x is well-formed when treated as an unevaluated operand and Ostream is publicly and unambiguously derived from ios_base.
Effects: As if by: os << x;
Returns: std​::​move(os).

31.7.7 Standard manipulators [std.manip]

The header <iomanip> defines several functions that support extractors and inserters that alter information maintained by class ios_base and its derived classes.
unspecified resetiosflags(ios_base::fmtflags mask);
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << resetiosflags(mask) behaves as if it called f(out, mask), or if in is an object of type basic_istream<charT, traits> then the expression in >> resetiosflags(​mask) behaves as if it called f(in, mask), where the function f is defined as:295 void f(ios_base& str, ios_base::fmtflags mask) { // reset specified flags str.setf(ios_base::fmtflags(0), mask); }
The expression out << resetiosflags(mask) has type basic_ostream<charT, traits>& and value out.
The expression in >> resetiosflags(mask) has type basic_istream<charT, traits>& and value in.
unspecified setiosflags(ios_base::fmtflags mask);
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << setiosflags(mask) behaves as if it called f(out, mask), or if in is an object of type basic_istream<charT, traits> then the expression in >> setiosflags(mask) behaves as if it called f(in, mask), where the function f is defined as: void f(ios_base& str, ios_base::fmtflags mask) { // set specified flags str.setf(mask); }
The expression out << setiosflags(mask) has type basic_ostream<charT, traits>& and value out.
The expression in >> setiosflags(mask) has type basic_istream<charT, traits>& and value in.
unspecified setbase(int base);
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << setbase(base) behaves as if it called f(out, base), or if in is an object of type basic_istream<charT, traits> then the expression in >> setbase(base) behaves as if it called f(in, base), where the function f is defined as: void f(ios_base& str, int base) { // set basefield str.setf(base == 8 ? ios_base::oct : base == 10 ? ios_base::dec : base == 16 ? ios_base::hex : ios_base::fmtflags(0), ios_base::basefield); }
The expression out << setbase(base) has type basic_ostream<charT, traits>& and value out.
The expression in >> setbase(base) has type basic_istream<charT, traits>& and value in.
unspecified setfill(char_type c);
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> and c has type charT then the expression out << setfill(c) behaves as if it called f(out, c), where the function f is defined as: template<class charT, class traits> void f(basic_ios<charT, traits>& str, charT c) { // set fill character str.fill(c); }
The expression out << setfill(c) has type basic_ostream<charT, traits>& and value out.
unspecified setprecision(int n);
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << setprecision(n) behaves as if it called f(out, n), or if in is an object of type basic_istream<charT, traits> then the expression in >> setprecision(n) behaves as if it called f(in, n), where the function f is defined as: void f(ios_base& str, int n) { // set precision str.precision(n); }
The expression out << setprecision(n) has type basic_ostream<charT, traits>& and value out.
The expression in >> setprecision(n) has type basic_istream<charT, traits>& and value in.
unspecified setw(int n);
Returns: An object of unspecified type such that if out is an instance of basic_ostream<charT, traits> then the expression out << setw(n) behaves as if it called f(out, n), or if in is an object of type basic_istream<charT, traits> then the expression in >> setw(n) behaves as if it called f(in, n), where the function f is defined as: void f(ios_base& str, int n) { // set width str.width(n); }
The expression out << setw(n) has type basic_ostream<charT, traits>& and value out.
The expression in >> setw(n) has type basic_istream<charT, traits>& and value in.
295)295)
The expression cin >> resetiosflags(ios_base​::​skipws) clears ios_base​::​skipws in the format flags stored in the basic_istream<charT, traits> object cin (the same as cin >> noskipws), and the expression cout << resetiosflags(ios_base​::​showbase) clears ios_base​::​showbase in the format flags stored in the basic_ostream<charT, traits> object cout (the same as cout << noshowbase).

31.7.8 Extended manipulators [ext.manip]

The header <iomanip> defines several functions that support extractors and inserters that allow for the parsing and formatting of sequences and values for money and time.
template<class moneyT> unspecified get_money(moneyT& mon, bool intl = false);
Mandates: The type moneyT is either long double or a specialization of the basic_string template ([strings]).
Effects: The expression in >> get_money(mon, intl) described below behaves as a formatted input function.
Returns: An object of unspecified type such that if in is an object of type basic_istream<charT, traits> then the expression in >> get_money(mon, intl) behaves as if it called f(in, mon, intl), where the function f is defined as: template<class charT, class traits, class moneyT> void f(basic_ios<charT, traits>& str, moneyT& mon, bool intl) { using Iter = istreambuf_iterator<charT, traits>; using MoneyGet = money_get<charT, Iter>; ios_base::iostate err = ios_base::goodbit; const MoneyGet& mg = use_facet<MoneyGet>(str.getloc()); mg.get(Iter(str.rdbuf()), Iter(), intl, str, err, mon); if (ios_base::goodbit != err) str.setstate(err); }
The expression in >> get_money(mon, intl) has type basic_istream<charT, traits>& and value in.
template<class moneyT> unspecified put_money(const moneyT& mon, bool intl = false);
Mandates: The type moneyT is either long double or a specialization of the basic_string template ([strings]).
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << put_money(mon, intl) behaves as a formatted output function that calls f(out, mon, intl), where the function f is defined as: template<class charT, class traits, class moneyT> void f(basic_ios<charT, traits>& str, const moneyT& mon, bool intl) { using Iter = ostreambuf_iterator<charT, traits>; using MoneyPut = money_put<charT, Iter>; const MoneyPut& mp = use_facet<MoneyPut>(str.getloc()); const Iter end = mp.put(Iter(str.rdbuf()), intl, str, str.fill(), mon); if (end.failed()) str.setstate(ios_base::badbit); }
The expression out << put_money(mon, intl) has type basic_ostream<charT, traits>& and value out.
template<class charT> unspecified get_time(tm* tmb, const charT* fmt);
Preconditions: The argument tmb is a valid pointer to an object of type tm, and [fmt, fmt + char_traits<charT>​::​length(fmt)) is a valid range.
Returns: An object of unspecified type such that if in is an object of type basic_istream<charT, traits> then the expression in >> get_time(tmb, fmt) behaves as if it called f(in, tmb, fmt), where the function f is defined as: template<class charT, class traits> void f(basic_ios<charT, traits>& str, tm* tmb, const charT* fmt) { using Iter = istreambuf_iterator<charT, traits>; using TimeGet = time_get<charT, Iter>; ios_base::iostate err = ios_base::goodbit; const TimeGet& tg = use_facet<TimeGet>(str.getloc()); tg.get(Iter(str.rdbuf()), Iter(), str, err, tmb, fmt, fmt + traits::length(fmt)); if (err != ios_base::goodbit) str.setstate(err); }
The expression in >> get_time(tmb, fmt) has type basic_istream<charT, traits>& and value in.
template<class charT> unspecified put_time(const tm* tmb, const charT* fmt);
Preconditions: The argument tmb is a valid pointer to an object of type tm, and [fmt, fmt + char_traits<charT>​::​length(fmt)) is a valid range.
Returns: An object of unspecified type such that if out is an object of type basic_ostream<charT, traits> then the expression out << put_time(tmb, fmt) behaves as if it called f(out, tmb, fmt), where the function f is defined as: template<class charT, class traits> void f(basic_ios<charT, traits>& str, const tm* tmb, const charT* fmt) { using Iter = ostreambuf_iterator<charT, traits>; using TimePut = time_put<charT, Iter>; const TimePut& tp = use_facet<TimePut>(str.getloc()); const Iter end = tp.put(Iter(str.rdbuf()), str, str.fill(), tmb, fmt, fmt + traits::length(fmt)); if (end.failed()) str.setstate(ios_base::badbit); }
The expression out << put_time(tmb, fmt) has type basic_ostream<charT, traits>& and value out.

31.7.9 Quoted manipulators [quoted.manip]

[Note 1: 
Quoted manipulators provide string insertion and extraction of quoted strings (for example, XML and CSV formats).
Quoted manipulators are useful in ensuring that the content of a string with embedded spaces remains unchanged if inserted and then extracted via stream I/O.
— end note]
template<class charT> unspecified quoted(const charT* s, charT delim = charT('"'), charT escape = charT('\\')); template<class charT, class traits, class Allocator> unspecified quoted(const basic_string<charT, traits, Allocator>& s, charT delim = charT('"'), charT escape = charT('\\')); template<class charT, class traits> unspecified quoted(basic_string_view<charT, traits> s, charT delim = charT('"'), charT escape = charT('\\'));
Returns: An object of unspecified type such that if out is an instance of basic_ostream with member type char_type the same as charT and with member type traits_type, which in the second and third forms is the same as traits, then the expression out << quoted(s, delim, escape) behaves as a formatted output function of out.
This forms a character sequence seq, initially consisting of the following elements:
  • delim.
  • Each character in s.
    If the character to be output is equal to escape or delim, as determined by traits_type​::​eq, first output escape.
  • delim.
Let x be the number of elements initially in seq.
Then padding is determined for seq as described in [ostream.formatted.reqmts], seq is inserted as if by calling out.rdbuf()->sputn(seq, n), where n is the larger of out.width() and x, and out.width(0) is called.
The expression out << quoted(s, delim, escape) has type basic_ostream<charT, traits>& and value out.
template<class charT, class traits, class Allocator> unspecified quoted(basic_string<charT, traits, Allocator>& s, charT delim = charT('"'), charT escape = charT('\\'));
Returns: An object of unspecified type such that:
  • If in is an instance of basic_istream with member types char_type and traits_type the same as charT and traits, respectively, then the expression in >> quoted(s, delim, escape) behaves as if it extracts the following characters from in using operator>>(basic_istream<charT, traits>&, charT&) ([istream.extractors]) which may throw ios_base​::​failure ([ios.failure]):
    • If the first character extracted is equal to delim, as determined by traits_type​::​eq, then:
      • Turn off the skipws flag.
      • s.clear()
      • Until an unescaped delim character is reached or !in, extract characters from in and append them to s, except that if an escape is reached, ignore it and append the next character to s.
      • Discard the final delim character.
      • Restore the skipws flag to its original value.
    • Otherwise, in >> s.
  • If out is an instance of basic_ostream with member types char_type and traits_type the same as charT and traits, respectively, then the expression out << quoted(s, delim, escape) behaves as specified for the const basic_string<charT, traits, Allocator>& overload of the quoted function.
  • The expression in >> quoted(s, delim, escape) has type basic_istream<charT, traits>& and value in.
  • The expression out << quoted(s, delim, escape) has type basic_ostream​<charT, traits>& and value out.

31.7.10 Print functions [print.fun]

template<class... Args> void print(format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: print(stdout, fmt, std::forward<Args>(args)...);
template<class... Args> void print(FILE* stream, format_string<Args...> fmt, Args&&... args);
Effects: Let locksafe be (enable_nonlocking_formatter_optimization<remove_cvref_t<Args>> && ...).
If the ordinary literal encoding ([lex.charset]) is UTF-8, equivalent to: locksafe ? vprint_unicode(stream, fmt.str, make_format_args(args...)) : vprint_unicode_buffered(stream, fmt.str, make_format_args(args...));
Otherwise, equivalent to: locksafe ? vprint_nonunicode(stream, fmt.str, make_format_args(args...)) : vprint_nonunicode_buffered(stream, fmt.str, make_format_args(args...));
template<class... Args> void println(format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: println(stdout, fmt, std::forward<Args>(args)...);
void println();
Effects: Equivalent to: println(stdout);
template<class... Args> void println(FILE* stream, format_string<Args...> fmt, Args&&... args);
Effects: Equivalent to: print(stream, runtime_format(string(fmt.get()) + '\n'), std::forward<Args>(args)...);
void println(FILE* stream);
Effects: Equivalent to: print(stream, "\n");
void vprint_unicode(string_view fmt, format_args args);
Effects: Equivalent to: vprint_unicode(stdout, fmt, args);
void vprint_unicode_buffered(FILE* stream, string_view fmt, format_args args);
Effects: Equivalent to: string out = vformat(fmt, args); vprint_unicode(stream, "{}", make_format_args(out));
void vprint_unicode(FILE* stream, string_view fmt, format_args args);
Preconditions: stream is a valid pointer to an output C stream.
Effects: Locks stream.
Let out denote the character representation of formatting arguments provided by args formatted according to specifications given in fmt.
  • If stream refers to a terminal that is capable of displaying Unicode only via a native Unicode API, flushes stream and then writes out to the terminal using the native Unicode API; if out contains invalid code units, the behavior is undefined.
  • Otherwise writes out to stream unchanged.
Unconditionally unlocks stream on function exit.
See also: ISO/IEC 9899:2018, 7.21.2.
[Note 1: 
On Windows the native Unicode API is WriteConsoleW and stream referring to a terminal means that GetConsoleMode(_get_osfhandle(_fileno(stream)), ...) returns nonzero.
— end note]
Throws: Any exception thrown by the call to vformat ([format.err.report]).
system_error if writing to the terminal or stream fails.
May throw bad_alloc.
Recommended practice: If invoking the native Unicode API requires transcoding, implementations should substitute invalid code units with U+fffd replacement character per the Unicode Standard, Chapter 3.9 U+fffd Substitution in Conversion.
void vprint_nonunicode(string_view fmt, format_args args);
Effects: Equivalent to: vprint_nonunicode(stdout, fmt, args);
void vprint_nonunicode_buffered(FILE* stream, string_view fmt, format_args args);
Effects: Equivalent to: string out = vformat(fmt, args); vprint_nonunicode("{}", make_format_args(out));
void vprint_nonunicode(FILE* stream, string_view fmt, format_args args);
Preconditions: stream is a valid pointer to an output C stream.
Effects: While holding the lock on stream, writes the character representation of formatting arguments provided by args formatted according to specifications given in fmt to stream.
Throws: Any exception thrown by the call to vformat ([format.err.report]).
system_error if writing to stream fails.
May throw bad_alloc.

31.8 String-based streams [string.streams]

31.8.1 Header <sstream> synopsis [sstream.syn]

namespace std { // [stringbuf], class template basic_stringbuf template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringbuf; template<class charT, class traits, class Allocator> void swap(basic_stringbuf<charT, traits, Allocator>& x, basic_stringbuf<charT, traits, Allocator>& y) noexcept(noexcept(x.swap(y))); using stringbuf = basic_stringbuf<char>; using wstringbuf = basic_stringbuf<wchar_t>; // [istringstream], class template basic_istringstream template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_istringstream; template<class charT, class traits, class Allocator> void swap(basic_istringstream<charT, traits, Allocator>& x, basic_istringstream<charT, traits, Allocator>& y); using istringstream = basic_istringstream<char>; using wistringstream = basic_istringstream<wchar_t>; // [ostringstream], class template basic_ostringstream template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_ostringstream; template<class charT, class traits, class Allocator> void swap(basic_ostringstream<charT, traits, Allocator>& x, basic_ostringstream<charT, traits, Allocator>& y); using ostringstream = basic_ostringstream<char>; using wostringstream = basic_ostringstream<wchar_t>; // [stringstream], class template basic_stringstream template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringstream; template<class charT, class traits, class Allocator> void swap(basic_stringstream<charT, traits, Allocator>& x, basic_stringstream<charT, traits, Allocator>& y); using stringstream = basic_stringstream<char>; using wstringstream = basic_stringstream<wchar_t>; }
The header <sstream> defines four class templates and eight types that associate stream buffers with objects of class basic_string, as described in [string.classes].

31.8.2 Class template basic_stringbuf [stringbuf]

31.8.2.1 General [stringbuf.general]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringbuf : public basic_streambuf<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; // [stringbuf.cons], constructors basic_stringbuf() : basic_stringbuf(ios_base::in | ios_base::out) {} explicit basic_stringbuf(ios_base::openmode which); explicit basic_stringbuf( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::in | ios_base::out); explicit basic_stringbuf(const Allocator& a) : basic_stringbuf(ios_base::in | ios_base::out, a) {} basic_stringbuf(ios_base::openmode which, const Allocator& a); explicit basic_stringbuf( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::in | ios_base::out); template<class SAlloc> basic_stringbuf( const basic_string<charT, traits, SAlloc>& s, const Allocator& a) : basic_stringbuf(s, ios_base::in | ios_base::out, a) {} template<class SAlloc> basic_stringbuf( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a); template<class SAlloc> explicit basic_stringbuf( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::in | ios_base::out); template<class T> explicit basic_stringbuf(const T& t, ios_base::openmode which = ios_base::in | ios_base::out); template<class T> basic_stringbuf(const T& t, const Allocator& a); template<class T> basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a); basic_stringbuf(const basic_stringbuf&) = delete; basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a); // [stringbuf.assign], assignment and swap basic_stringbuf& operator=(const basic_stringbuf&) = delete; basic_stringbuf& operator=(basic_stringbuf&& rhs); void swap(basic_stringbuf& rhs) noexcept(see below); // [stringbuf.members], getters and setters allocator_type get_allocator() const noexcept; basic_string<charT, traits, Allocator> str() const &; template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const; basic_string<charT, traits, Allocator> str() &&; basic_string_view<charT, traits> view() const noexcept; void str(const basic_string<charT, traits, Allocator>& s); template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s); void str(basic_string<charT, traits, Allocator>&& s); template<class T> void str(const T& t); protected: // [stringbuf.virtuals], overridden virtual functions int_type underflow() override; int_type pbackfail(int_type c = traits::eof()) override; int_type overflow (int_type c = traits::eof()) override; basic_streambuf<charT, traits>* setbuf(charT*, streamsize) override; pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override; pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override; private: ios_base::openmode mode; // exposition only basic_string<charT, traits, Allocator> buf; // exposition only void init-buf-ptrs(); // exposition only }; }
The class basic_stringbuf is derived from basic_streambuf to associate possibly the input sequence and possibly the output sequence with a sequence of arbitrary characters.
The sequence can be initialized from, or made available as, an object of class basic_string.
For the sake of exposition, the maintained data and internal pointer initialization is presented here as:
  • ios_base​::​openmode mode, has in set if the input sequence can be read, and out set if the output sequence can be written.
  • basic_string<charT, traits, Allocator> buf contains the underlying character sequence.
  • init-buf-ptrs() sets the base class' get area ([streambuf.get.area]) and put area ([streambuf.put.area]) pointers after initializing, moving from, or assigning to buf accordingly.

31.8.2.2 Constructors [stringbuf.cons]

explicit basic_stringbuf(ios_base::openmode which);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), and mode with which.
It is implementation-defined whether the sequence pointers (eback(), gptr(), egptr(), pbase(), pptr(), epptr()) are initialized to null pointers.
Postconditions: str().empty() is true.
explicit basic_stringbuf( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), mode with which, and buf with s, then calls init-buf-ptrs().
basic_stringbuf(ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), mode with which, and buf with a, then calls init-buf-ptrs().
Postconditions: str().empty() is true.
explicit basic_stringbuf( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), mode with which, and buf with std​::​move(s), then calls init-buf-ptrs().
template<class SAlloc> basic_stringbuf( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), mode with which, and buf with {s,a}, then calls init-buf-ptrs().
template<class SAlloc> explicit basic_stringbuf( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::in | ios_base::out);
Constraints: is_same_v<SAlloc, Allocator> is false.
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), mode with which, and buf with s, then calls init-buf-ptrs().
template<class T> explicit basic_stringbuf(const T& t, ios_base::openmode which = ios_base::in | ios_base::out); template<class T> basic_stringbuf(const T& t, const Allocator& a); template<class T> basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a);
Let which be ios_base​::​in | ios_base​::​out for the overload with no parameter which, and a be Allocator() for the overload with no parameter a.
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Creates a variable sv as if by basic_string_view<charT, traits> sv = t, then value-initializes the base class, initializes mode with which, and direct-non-list-initializes buf with sv, a, then calls init-buf-ptrs().
basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a);
Effects: Copy constructs the base class from rhs and initializes mode with rhs.mode.
In the first form buf is initialized from std​::​move(rhs).str().
In the second form buf is initialized from {std​::​move(rhs).str(), a}.
It is implementation-defined whether the sequence pointers in *this (eback(), gptr(), egptr(), pbase(), pptr(), epptr()) obtain the values which rhs had.
Postconditions: Let rhs_p refer to the state of rhs just prior to this construction and let rhs_a refer to the state of rhs just after this construction.
  • str() == rhs_p.str()
  • gptr() - eback() == rhs_p.gptr() - rhs_p.eback()
  • egptr() - eback() == rhs_p.egptr() - rhs_p.eback()
  • pptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()
  • epptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()
  • if (eback()) eback() != rhs_a.eback()
  • if (gptr()) gptr() != rhs_a.gptr()
  • if (egptr()) egptr() != rhs_a.egptr()
  • if (pbase()) pbase() != rhs_a.pbase()
  • if (pptr()) pptr() != rhs_a.pptr()
  • if (epptr()) epptr() != rhs_a.epptr()
  • getloc() == rhs_p.getloc()
  • rhs is empty but usable, as if std​::​move(rhs).str() was called.

31.8.2.3 Assignment and swap [stringbuf.assign]

basic_stringbuf& operator=(basic_stringbuf&& rhs);
Effects: After the move assignment *this has the observable state it would have had if it had been move constructed from rhs (see [stringbuf.cons]).
Returns: *this.
void swap(basic_stringbuf& rhs) noexcept(see below);
Preconditions: allocator_traits<Allocator>​::​propagate_on_container_swap​::​value is true or get_allocator() == rhs.get_allocator() is true.
Effects: Exchanges the state of *this and rhs.
Remarks: The exception specification is equivalent to:
allocator_traits<Allocator>​::​propagate_on_container_swap​::​value ||
allocator_traits<Allocator>​::​is_always_equal​::​value
template<class charT, class traits, class Allocator> void swap(basic_stringbuf<charT, traits, Allocator>& x, basic_stringbuf<charT, traits, Allocator>& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to x.swap(y).

31.8.2.4 Member functions [stringbuf.members]

The member functions getting the underlying character sequence all refer to a high_mark value, where high_mark represents the position one past the highest initialized character in the buffer.
Characters can be initialized by writing to the stream, by constructing the basic_stringbuf passing a basic_string argument, or by calling one of the str member functions passing a basic_string as an argument.
In the latter case, all characters initialized prior to the call are now considered uninitialized (except for those characters re-initialized by the new basic_string).
void init-buf-ptrs(); // exposition only
Effects: Initializes the input and output sequences from buf according to mode.
Postconditions:
  • If ios_base​::​out is set in mode, pbase() points to buf.front() and epptr() >= pbase() + buf.size() is true;
    • in addition, if ios_base​::​ate is set in mode, pptr() == pbase() + buf.size() is true,
    • otherwise pptr() == pbase() is true.
  • If ios_base​::​in is set in mode, eback() points to buf.front(), and (gptr() == eback() && egptr() == eback() + buf.size()) is true.
[Note 1: 
For efficiency reasons, stream buffer operations can violate invariants of buf while it is held encapsulated in the basic_stringbuf, e.g., by writing to characters in the range [buf.data() + buf.size(), buf.data() + buf.capacity()).
All operations retrieving a basic_string from buf ensure that the basic_string invariants hold on the returned value.
— end note]
allocator_type get_allocator() const noexcept;
Returns: buf.get_allocator().
basic_string<charT, traits, Allocator> str() const &;
Effects: Equivalent to: return basic_string<charT, traits, Allocator>(view(), get_allocator());
template<class SAlloc> basic_string<charT, traits, SAlloc> str(const SAlloc& sa) const;
Constraints: SAlloc is a type that qualifies as an allocator ([container.reqmts]).
Effects: Equivalent to: return basic_string<charT, traits, SAlloc>(view(), sa);
basic_string<charT, traits, Allocator> str() &&;
Postconditions: The underlying character sequence buf is empty and pbase(), pptr(), epptr(), eback(), gptr(), and egptr() are initialized as if by calling init-buf-ptrs() with an empty buf.
Returns: A basic_string<charT, traits, Allocator> object move constructed from the basic_stringbuf's underlying character sequence in buf.
This can be achieved by first adjusting buf to have the same content as view().
basic_string_view<charT, traits> view() const noexcept;
Let sv be basic_string_view<charT, traits>.
Returns: A sv object referring to the basic_stringbuf's underlying character sequence in buf:
  • If ios_base​::​out is set in mode, then sv(pbase(), high_mark-pbase()) is returned.
  • Otherwise, if ios_base​::​in is set in mode, then sv(eback(), egptr()-eback()) is returned.
  • Otherwise, sv() is returned.
[Note 2: 
Using the returned sv object after destruction or invalidation of the character sequence underlying *this is undefined behavior, unless sv.empty() is true.
— end note]
void str(const basic_string<charT, traits, Allocator>& s);
Effects: Equivalent to: buf = s; init-buf-ptrs();
template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s);
Constraints: is_same_v<SAlloc,Allocator> is false.
Effects: Equivalent to: buf = s; init-buf-ptrs();
void str(basic_string<charT, traits, Allocator>&& s);
Effects: Equivalent to: buf = std::move(s); init-buf-ptrs();
template<class T> void str(const T& t);
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Equivalent to: basic_string_view<charT, traits> sv = t; buf = sv; init-buf-ptrs();

31.8.2.5 Overridden virtual functions [stringbuf.virtuals]

int_type underflow() override;
Returns: If the input sequence has a read position available, returns traits​::​to_int_type(*gptr()).
Otherwise, returns traits​::​eof().
Any character in the underlying buffer which has been initialized is considered to be part of the input sequence.
int_type pbackfail(int_type c = traits::eof()) override;
Effects: Puts back the character designated by c to the input sequence, if possible, in one of three ways:
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false and if the input sequence has a putback position available, and if traits​::​eq(to_char_type(c), gptr()[-1]) returns true, assigns gptr() - 1 to gptr().
    Returns: c.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false and if the input sequence has a putback position available, and if mode & ios_base​::​out is nonzero, assigns c to *--gptr().
    Returns: c.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns true and if the input sequence has a putback position available, assigns gptr() - 1 to gptr().
    Returns: traits​::​not_eof(c).
Returns: As specified above, or traits​::​eof() to indicate failure.
Remarks: If the function can succeed in more than one of these ways, it is unspecified which way is chosen.
int_type overflow(int_type c = traits::eof()) override;
Effects: Appends the character designated by c to the output sequence, if possible, in one of two ways:
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false and if either the output sequence has a write position available or the function makes a write position available (as described below), the function calls sputc(c).
    Signals success by returning c.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns true, there is no character to append.
    Signals success by returning a value other than traits​::​eof().
Returns: As specified above, or traits​::​eof() to indicate failure.
Remarks: The function can alter the number of write positions available as a result of any call.
The function can make a write position available only if ios_base​::​out is set in mode.
To make a write position available, the function reallocates (or initially allocates) an array object with a sufficient number of elements to hold the current array object (if any), plus at least one additional write position.
If ios_base​::​in is set in mode, the function alters the read end pointer egptr() to point just past the new write position.
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Alters the stream position within one of the controlled sequences, if possible, as indicated in Table 139.
Table 139seekoff positioning [tab:stringbuf.seekoff.pos]
Conditions
Result
ios_base​::​in is set in which
positions the input sequence
ios_base​::​out is set in which
positions the output sequence
both ios_base​::​in and ios_base​::​out are set in which and either
way == ios_base​::​beg or
way == ios_base​::​end
positions both the input and the output sequences
Otherwise
the positioning operation fails.
For a sequence to be positioned, the function determines newoff as indicated in Table 140.
If the sequence's next pointer (either gptr() or pptr()) is a null pointer and newoff is nonzero, the positioning operation fails.
Table 140newoff values [tab:stringbuf.seekoff.newoff]
Condition
newoff Value
way == ios_base​::​beg
0
way == ios_base​::​cur
the next pointer minus the beginning pointer (xnext - xbeg).
way == ios_base​::​end
the high mark pointer minus the beginning pointer (high_mark - xbeg).
If (newoff + off) < 0, or if newoff + off refers to an uninitialized character ([stringbuf.members]), the positioning operation fails.
Otherwise, the function assigns xbeg + newoff + off to the next pointer xnext.
Returns: pos_type(newoff), constructed from the resultant offset newoff (of type off_type), that stores the resultant stream position, if possible.
If the positioning operation fails, or if the constructed object cannot represent the resultant stream position, the return value is pos_type(off_type(-1)).
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Equivalent to seekoff(off_type(sp), ios_base​::​beg, which).
Returns: sp to indicate success, or pos_type(off_type(-1)) to indicate failure.
basic_streambuf<charT, traits>* setbuf(charT* s, streamsize n) override;
Effects: implementation-defined, except that setbuf(0, 0) has no effect.
Returns: this.

31.8.3 Class template basic_istringstream [istringstream]

31.8.3.1 General [istringstream.general]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_istringstream : public basic_istream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; // [istringstream.cons], constructors basic_istringstream() : basic_istringstream(ios_base::in) {} explicit basic_istringstream(ios_base::openmode which); explicit basic_istringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::in); basic_istringstream(ios_base::openmode which, const Allocator& a); explicit basic_istringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::in); template<class SAlloc> basic_istringstream( const basic_string<charT, traits, SAlloc>& s, const Allocator& a) : basic_istringstream(s, ios_base::in, a) {} template<class SAlloc> basic_istringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a); template<class SAlloc> explicit basic_istringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::in); template<class T> explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); template<class T> basic_istringstream(const T& t, const Allocator& a); template<class T> basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_istringstream(const basic_istringstream&) = delete; basic_istringstream(basic_istringstream&& rhs); basic_istringstream& operator=(const basic_istringstream&) = delete; basic_istringstream& operator=(basic_istringstream&& rhs); // [istringstream.swap], swap void swap(basic_istringstream& rhs); // [istringstream.members], members basic_stringbuf<charT, traits, Allocator>* rdbuf() const; basic_string<charT, traits, Allocator> str() const &; template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const; basic_string<charT, traits, Allocator> str() &&; basic_string_view<charT, traits> view() const noexcept; void str(const basic_string<charT, traits, Allocator>& s); template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s); void str(basic_string<charT, traits, Allocator>&& s); template<class T> void str(const T& t); private: basic_stringbuf<charT, traits, Allocator> sb; // exposition only }; }
The class basic_istringstream<charT, traits, Allocator> supports reading objects of class basic_string<​charT, traits, Allocator>.
It uses a basic_stringbuf<charT, traits, Allocator> object to control the associated storage.
For the sake of exposition, the maintained data is presented here as:
  • sb, the stringbuf object.

31.8.3.2 Constructors [istringstream.cons]

explicit basic_istringstream(ios_base::openmode which);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(which | ios_base​::​in) ([stringbuf.cons]).
explicit basic_istringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::in);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​in)
([stringbuf.cons]).
basic_istringstream(ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(which | ios_base​::​in, a) ([stringbuf.cons]).
explicit basic_istringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::in);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(std​::​move(s), which | ios_base​::​​in) ([stringbuf.cons]).
template<class SAlloc> basic_istringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​in, a)
([stringbuf.cons]).
template<class SAlloc> explicit basic_istringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::in);
Constraints: is_same_v<SAlloc, Allocator> is false.
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​in) ([stringbuf.cons]).
template<class T> explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); template<class T> basic_istringstream(const T& t, const Allocator& a); template<class T> basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a);
Let which be ios_base​::​in for the overload with no parameter which, and a be Allocator() for the overload with no parameter a.
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Initializes the base class with addressof(sb), and direct-non-list-initializes sb with t, which | ios_base​::​in, a.
basic_istringstream(basic_istringstream&& rhs);
Effects: Move constructs from the rvalue rhs.
This is accomplished by move constructing the base class, and the contained basic_stringbuf.
Then calls basic_istream<charT, traits>​::​set_rdbuf(addressof(sb)) to install the contained basic_stringbuf.

31.8.3.3 Swap [istringstream.swap]

void swap(basic_istringstream& rhs);
Effects: Equivalent to: basic_istream<charT, traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits, class Allocator> void swap(basic_istringstream<charT, traits, Allocator>& x, basic_istringstream<charT, traits, Allocator>& y);
Effects: Equivalent to x.swap(y).

31.8.3.4 Member functions [istringstream.members]

basic_stringbuf<charT, traits, Allocator>* rdbuf() const;
Returns: const_cast<basic_stringbuf<charT, traits, Allocator>*>(addressof(sb)).
basic_string<charT, traits, Allocator> str() const &;
Effects: Equivalent to: return rdbuf()->str();
template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const;
Effects: Equivalent to: return rdbuf()->str(sa);
basic_string<charT,traits,Allocator> str() &&;
Effects: Equivalent to: return std​::​move(*rdbuf()).str();
basic_string_view<charT, traits> view() const noexcept;
Effects: Equivalent to: return rdbuf()->view();
void str(const basic_string<charT, traits, Allocator>& s);
Effects: Equivalent to: rdbuf()->str(s);
template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s);
Effects: Equivalent to: rdbuf()->str(s);
void str(basic_string<charT, traits, Allocator>&& s);
Effects: Equivalent to: rdbuf()->str(std​::​move(s));
template<class T> void str(const T& t);
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Equivalent to: rdbuf()->str(t);

31.8.4 Class template basic_ostringstream [ostringstream]

31.8.4.1 General [ostringstream.general]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_ostringstream : public basic_ostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; // [ostringstream.cons], constructors basic_ostringstream() : basic_ostringstream(ios_base::out) {} explicit basic_ostringstream(ios_base::openmode which); explicit basic_ostringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::out); basic_ostringstream(ios_base::openmode which, const Allocator& a); explicit basic_ostringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::out); template<class SAlloc> basic_ostringstream( const basic_string<charT, traits, SAlloc>& s, const Allocator& a) : basic_ostringstream(s, ios_base::out, a) {} template<class SAlloc> basic_ostringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a); template<class SAlloc> explicit basic_ostringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::out); template<class T> explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); template<class T> basic_ostringstream(const T& t, const Allocator& a); template<class T> basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_ostringstream(const basic_ostringstream&) = delete; basic_ostringstream(basic_ostringstream&& rhs); basic_ostringstream& operator=(const basic_ostringstream&) = delete; basic_ostringstream& operator=(basic_ostringstream&& rhs); // [ostringstream.swap], swap void swap(basic_ostringstream& rhs); // [ostringstream.members], members basic_stringbuf<charT, traits, Allocator>* rdbuf() const; basic_string<charT, traits, Allocator> str() const &; template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const; basic_string<charT, traits, Allocator> str() &&; basic_string_view<charT, traits> view() const noexcept; void str(const basic_string<charT, traits, Allocator>& s); template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s); void str(basic_string<charT, traits, Allocator>&& s); template<class T> void str(const T& t); private: basic_stringbuf<charT, traits, Allocator> sb; // exposition only }; }
The class basic_ostringstream<charT, traits, Allocator> supports writing objects of class basic_string<​charT, traits, Allocator>.
It uses a basic_stringbuf object to control the associated storage.
For the sake of exposition, the maintained data is presented here as:
  • sb, the stringbuf object.

31.8.4.2 Constructors [ostringstream.cons]

explicit basic_ostringstream(ios_base::openmode which);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(which | ios_base​::​out) ([stringbuf.cons]).
explicit basic_ostringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::out);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​out)
([stringbuf.cons]).
basic_ostringstream(ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(which | ios_base​::​out, a)
([stringbuf.cons]).
explicit basic_ostringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::out);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(std​::​move(s), which | ios_base​::​​out) ([stringbuf.cons]).
template<class SAlloc> basic_ostringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​out, a)
([stringbuf.cons]).
template<class SAlloc> explicit basic_ostringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::out);
Constraints: is_same_v<SAlloc,Allocator> is false.
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which | ios_base​::​out)
([stringbuf.cons]).
template<class T> explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); template<class T> basic_ostringstream(const T& t, const Allocator& a); template<class T> basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a);
Let which be ios_base​::​out for the overload with no parameter which, and a be Allocator() for the overload with no parameter a.
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Initializes the base class with addressof(sb), and direct-non-list-initializes sb with t, which | ios_base​::​out, a.
basic_ostringstream(basic_ostringstream&& rhs);
Effects: Move constructs from the rvalue rhs.
This is accomplished by move constructing the base class, and the contained basic_stringbuf.
Then calls basic_ostream<charT, traits>​::​set_rdbuf(addressof(sb)) to install the contained basic_stringbuf.

31.8.4.3 Swap [ostringstream.swap]

void swap(basic_ostringstream& rhs);
Effects: Equivalent to: basic_ostream<charT, traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits, class Allocator> void swap(basic_ostringstream<charT, traits, Allocator>& x, basic_ostringstream<charT, traits, Allocator>& y);
Effects: Equivalent to x.swap(y).

31.8.4.4 Member functions [ostringstream.members]

basic_stringbuf<charT, traits, Allocator>* rdbuf() const;
Returns: const_cast<basic_stringbuf<charT, traits, Allocator>*>(addressof(sb)).
basic_string<charT, traits, Allocator> str() const &;
Effects: Equivalent to: return rdbuf()->str();
template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const;
Effects: Equivalent to: return rdbuf()->str(sa);
basic_string<charT,traits,Allocator> str() &&;
Effects: Equivalent to: return std​::​move(*rdbuf()).str();
basic_string_view<charT, traits> view() const noexcept;
Effects: Equivalent to: return rdbuf()->view();
void str(const basic_string<charT, traits, Allocator>& s);
Effects: Equivalent to: rdbuf()->str(s);
template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s);
Effects: Equivalent to: rdbuf()->str(s);
void str(basic_string<charT, traits, Allocator>&& s);
Effects: Equivalent to: rdbuf()->str(std​::​move(s));
template<class T> void str(const T& t);
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Equivalent to: rdbuf()->str(t);

31.8.5 Class template basic_stringstream [stringstream]

31.8.5.1 General [stringstream.general]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_stringstream : public basic_iostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; // [stringstream.cons], constructors basic_stringstream() : basic_stringstream(ios_base::out | ios_base::in) {} explicit basic_stringstream(ios_base::openmode which); explicit basic_stringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::out | ios_base::in); basic_stringstream(ios_base::openmode which, const Allocator& a); explicit basic_stringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::out | ios_base::in); template<class SAlloc> basic_stringstream( const basic_string<charT, traits, SAlloc>& s, const Allocator& a) : basic_stringstream(s, ios_base::out | ios_base::in, a) {} template<class SAlloc> basic_stringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a); template<class SAlloc> explicit basic_stringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::out | ios_base::in); template<class T> explicit basic_stringstream(const T& t, ios_base::openmode which = ios_base::out | ios_base::in); template<class T> basic_stringstream(const T& t, const Allocator& a); template<class T> basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a); basic_stringstream(const basic_stringstream&) = delete; basic_stringstream(basic_stringstream&& rhs); basic_stringstream& operator=(const basic_stringstream&) = delete; basic_stringstream& operator=(basic_stringstream&& rhs); // [stringstream.swap], swap void swap(basic_stringstream& rhs); // [stringstream.members], members basic_stringbuf<charT, traits, Allocator>* rdbuf() const; basic_string<charT, traits, Allocator> str() const &; template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const; basic_string<charT, traits, Allocator> str() &&; basic_string_view<charT, traits> view() const noexcept; void str(const basic_string<charT, traits, Allocator>& s); template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s); void str(basic_string<charT, traits, Allocator>&& s); template<class T> void str(const T& t); private: basic_stringbuf<charT, traits, Allocator> sb; // exposition only }; }
The class template basic_stringstream<charT, traits> supports reading and writing from objects of class basic_string<charT, traits, Allocator>.
It uses a basic_stringbuf<charT, traits, Allocator> object to control the associated sequence.
For the sake of exposition, the maintained data is presented here as
  • sb, the stringbuf object.

31.8.5.2 Constructors [stringstream.cons]

explicit basic_stringstream(ios_base::openmode which);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(which).
explicit basic_stringstream( const basic_string<charT, traits, Allocator>& s, ios_base::openmode which = ios_base::out | ios_base::in);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which).
basic_stringstream(ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(which, a) ([stringbuf.cons]).
explicit basic_stringstream( basic_string<charT, traits, Allocator>&& s, ios_base::openmode which = ios_base::out | ios_base::in);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(std​::​move(s), which) ([stringbuf.cons]).
template<class SAlloc> basic_stringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which, const Allocator& a);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which, a) ([stringbuf.cons]).
template<class SAlloc> explicit basic_stringstream( const basic_string<charT, traits, SAlloc>& s, ios_base::openmode which = ios_base::out | ios_base::in);
Constraints: is_same_v<SAlloc,Allocator> is false.
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_stringbuf<charT, traits, Allocator>(s, which) ([stringbuf.cons]).
template<class T> explicit basic_stringstream(const T& t, ios_base::openmode which = ios_base::out | ios_base::in); template<class T> basic_stringstream(const T& t, const Allocator& a); template<class T> basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a);
Let which be ios_base​::​out | ios_base​::​in for the overload with no parameter which, and a be Allocator() for the overload with no parameter a.
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Initializes the base class with addressof(sb), and direct-non-list-initializes sb with t, which, a.
basic_stringstream(basic_stringstream&& rhs);
Effects: Move constructs from the rvalue rhs.
This is accomplished by move constructing the base class, and the contained basic_stringbuf.
Then calls basic_istream<charT, traits>​::​set_rdbuf(addressof(sb)) to install the contained basic_stringbuf.

31.8.5.3 Swap [stringstream.swap]

void swap(basic_stringstream& rhs);
Effects: Equivalent to: basic_iostream<charT,traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits, class Allocator> void swap(basic_stringstream<charT, traits, Allocator>& x, basic_stringstream<charT, traits, Allocator>& y);
Effects: Equivalent to x.swap(y).

31.8.5.4 Member functions [stringstream.members]

basic_stringbuf<charT, traits, Allocator>* rdbuf() const;
Returns: const_cast<basic_stringbuf<charT, traits, Allocator>*>(addressof(sb)).
basic_string<charT, traits, Allocator> str() const &;
Effects: Equivalent to: return rdbuf()->str();
template<class SAlloc> basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const;
Effects: Equivalent to: return rdbuf()->str(sa);
basic_string<charT,traits,Allocator> str() &&;
Effects: Equivalent to: return std​::​move(*rdbuf()).str();
basic_string_view<charT, traits> view() const noexcept;
Effects: Equivalent to: return rdbuf()->view();
void str(const basic_string<charT, traits, Allocator>& s);
Effects: Equivalent to: rdbuf()->str(s);
template<class SAlloc> void str(const basic_string<charT, traits, SAlloc>& s);
Effects: Equivalent to: rdbuf()->str(s);
void str(basic_string<charT, traits, Allocator>&& s);
Effects: Equivalent to: rdbuf()->str(std​::​move(s));
template<class T> void str(const T&);
Constraints: is_convertible_v<const T&, basic_string_view<charT, traits>> is true.
Effects: Equivalent to: rdbuf()->str(t);

31.9 Span-based streams [span.streams]

31.9.1 Overview [span.streams.overview]

The header <spanstream> defines class templates and types that associate stream buffers with objects whose types are specializations of span as described in [views.span].
[Note 1: 
A user of these classes is responsible for ensuring that the character sequence represented by the given span outlives the use of the sequence by objects of the classes in [span.streams].
Using multiple basic_spanbuf objects referring to overlapping underlying sequences from different threads, where at least one basic_spanbuf object is used for writing to the sequence, results in a data race.
— end note]

31.9.2 Header <spanstream> synopsis [spanstream.syn]

namespace std { // [spanbuf], class template basic_spanbuf template<class charT, class traits = char_traits<charT>> class basic_spanbuf; template<class charT, class traits> void swap(basic_spanbuf<charT, traits>& x, basic_spanbuf<charT, traits>& y); using spanbuf = basic_spanbuf<char>; using wspanbuf = basic_spanbuf<wchar_t>; // [ispanstream], class template basic_ispanstream template<class charT, class traits = char_traits<charT>> class basic_ispanstream; template<class charT, class traits> void swap(basic_ispanstream<charT, traits>& x, basic_ispanstream<charT, traits>& y); using ispanstream = basic_ispanstream<char>; using wispanstream = basic_ispanstream<wchar_t>; // [ospanstream], class template basic_ospanstream template<class charT, class traits = char_traits<charT>> class basic_ospanstream; template<class charT, class traits> void swap(basic_ospanstream<charT, traits>& x, basic_ospanstream<charT, traits>& y); using ospanstream = basic_ospanstream<char>; using wospanstream = basic_ospanstream<wchar_t>; // [spanstream], class template basic_spanstream template<class charT, class traits = char_traits<charT>> class basic_spanstream; template<class charT, class traits> void swap(basic_spanstream<charT, traits>& x, basic_spanstream<charT, traits>& y); using spanstream = basic_spanstream<char>; using wspanstream = basic_spanstream<wchar_t>; }

31.9.3 Class template basic_spanbuf [spanbuf]

31.9.3.1 General [spanbuf.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_spanbuf : public basic_streambuf<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [spanbuf.cons], constructors basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out) {} explicit basic_spanbuf(ios_base::openmode which) : basic_spanbuf(std::span<charT>(), which) {} explicit basic_spanbuf(std::span<charT> s, ios_base::openmode which = ios_base::in | ios_base::out); basic_spanbuf(const basic_spanbuf&) = delete; basic_spanbuf(basic_spanbuf&& rhs); // [spanbuf.assign], assignment and swap basic_spanbuf& operator=(const basic_spanbuf&) = delete; basic_spanbuf& operator=(basic_spanbuf&& rhs); void swap(basic_spanbuf& rhs); // [spanbuf.members], member functions std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; protected: // [spanbuf.virtuals], overridden virtual functions basic_streambuf<charT, traits>* setbuf(charT*, streamsize) override; pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override; pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override; private: ios_base::openmode mode; // exposition only std::span<charT> buf; // exposition only }; }
The class template basic_spanbuf is derived from basic_streambuf to associate possibly the input sequence and possibly the output sequence with a sequence of arbitrary characters.
The sequence is provided by an object of class span<charT>.
For the sake of exposition, the maintained data is presented here as:
  • ios_base​::​openmode mode, has in set if the input sequence can be read, and out set if the output sequence can be written.
  • std​::​span<charT> buf is the view to the underlying character sequence.

31.9.3.2 Constructors [spanbuf.cons]

explicit basic_spanbuf(std::span<charT> s, ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Initializes the base class with basic_streambuf() ([streambuf.cons]), and mode with which.
Initializes the internal pointers as if calling span(s).
basic_spanbuf(basic_spanbuf&& rhs);
Effects: Initializes the base class with std​::​move(rhs) and mode with std​::​move(rhs.mode) and buf with std​::​move(rhs.buf).
The sequence pointers in *this (eback(), gptr(), egptr(), pbase(), pptr(), epptr()) obtain the values which rhs had.
It is implementation-defined whether rhs.buf.​empty() returns true after the move.
Postconditions: Let rhs_p refer to the state of rhs just prior to this construction.
  • span().data() == rhs_p.span().data()
  • span().size() == rhs_p.span().size()
  • eback() == rhs_p.eback()
  • gptr() == rhs_p.gptr()
  • egptr() == rhs_p.egptr()
  • pbase() == rhs_p.pbase()
  • pptr() == rhs_p.pptr()
  • epptr() == rhs_p.epptr()
  • getloc() == rhs_p.getloc()

31.9.3.3 Assignment and swap [spanbuf.assign]

basic_spanbuf& operator=(basic_spanbuf&& rhs);
Effects: Equivalent to: basic_spanbuf tmp{std::move(rhs)}; this->swap(tmp); return *this;
void swap(basic_spanbuf& rhs);
Effects: Equivalent to: basic_streambuf<charT, traits>::swap(rhs); std::swap(mode, rhs.mode); std::swap(buf, rhs.buf);
template<class charT, class traits> void swap(basic_spanbuf<charT, traits>& x, basic_spanbuf<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.9.3.4 Member functions [spanbuf.members]

std::span<charT> span() const noexcept;
Returns: If ios_base​::​out is set in mode, returns std​::​span<charT>(pbase(), pptr()), otherwise returns buf.
[Note 1: 
In contrast to basic_stringbuf, the underlying sequence never grows and is not owned.
An owning copy can be obtained by converting the result to basic_string<charT>.
— end note]
void span(std::span<charT> s) noexcept;
Effects: buf = s.
Initializes the input and output sequences according to mode.
Postconditions:
  • If ios_base​::​out is set in mode, pbase() == s.data() && epptr() == pbase() + s.size() is true;
    • in addition, if ios_base​::​ate is set in mode, pptr() == pbase() + s.size() is true,
    • otherwise pptr() == pbase() is true.
  • If ios_base​::​in is set in mode, eback() == s.data() && gptr() == eback() && egptr() == eback() + s.size() is true.

31.9.3.5 Overridden virtual functions [spanbuf.virtuals]

[Note 1: 
Because the underlying buffer is of fixed size, neither overflow, underflow, nor pbackfail can provide useful behavior.
— end note]
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Alters the stream position within one or both of the controlled sequences, if possible, as follows:
  • If ios_base​::​in is set in which, positions the input sequence; xnext is gptr(), xbeg is eback().
  • If ios_base​::​out is set in which, positions the output sequence; xnext is pptr(), xbeg is pbase().
If both ios_base​::​in and ios_base​::​out are set in which and way is ios_base​::​cur, the positioning operation fails.
For a sequence to be positioned, if its next pointer xnext (either gptr() or pptr()) is a null pointer and the new offset newoff as computed below is nonzero, the positioning operation fails.
Otherwise, the function determines baseoff as a value of type off_type as follows:
  • 0 when way is ios_base​::​beg;
  • (pptr() - pbase()) for the output sequence, or (gptr() - eback()) for the input sequence when way is ios_base​::​cur;
  • when way is ios_base​::​end :
    • (pptr() - pbase()) if ios_base​::​out is set in mode and ios_base​::​in is not set in mode,
    • buf.size() otherwise.
If would overflow, or if is less than zero, or if is greater than buf.size(), the positioning operation fails.
Otherwise, the function computes off_type newoff = baseoff + off; and assigns xbeg + newoff to the next pointer xnext.
Returns: pos_type(off_type(-1)) if the positioning operation fails; pos_type(newoff) otherwise.
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Equivalent to: return seekoff(off_type(sp), ios_base::beg, which);
basic_streambuf<charT, traits>* setbuf(charT* s, streamsize n) override;
Effects: Equivalent to: this->span(std::span<charT>(s, n)); return this;

31.9.4 Class template basic_ispanstream [ispanstream]

31.9.4.1 General [ispanstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_ispanstream : public basic_istream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [ispanstream.cons], constructors explicit basic_ispanstream(std::span<charT> s, ios_base::openmode which = ios_base::in); basic_ispanstream(const basic_ispanstream&) = delete; basic_ispanstream(basic_ispanstream&& rhs); template<class ROS> explicit basic_ispanstream(ROS&& s); basic_ispanstream& operator=(const basic_ispanstream&) = delete; basic_ispanstream& operator=(basic_ispanstream&& rhs); // [ispanstream.swap], swap void swap(basic_ispanstream& rhs); // [ispanstream.members], member functions basic_spanbuf<charT, traits>* rdbuf() const noexcept; std::span<const charT> span() const noexcept; void span(std::span<charT> s) noexcept; template<class ROS> void span(ROS&& s) noexcept; private: basic_spanbuf<charT, traits> sb; // exposition only }; }
[Note 1: 
Constructing an ispanstream from a string-literal includes the termination character '\0' in the underlying spanbuf.
— end note]

31.9.4.2 Constructors [ispanstream.cons]

explicit basic_ispanstream(std::span<charT> s, ios_base::openmode which = ios_base::in);
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) and sb with basic_spanbuf<charT, traits>(s, which | ios_base​::​in) ([spanbuf.cons]).
basic_ispanstream(basic_ispanstream&& rhs);
Effects: Initializes the base class with std​::​move(rhs) and sb with std​::​move(rhs.sb).
Next, basic_istream<charT, traits>​::​set_rdbuf(addressof(sb)) is called to install the contained basic_spanbuf.
template<class ROS> explicit basic_ispanstream(ROS&& s)
Constraints: ROS models ranges​::​borrowed_range.
!convertible_to<ROS, std​::​span<charT>> && convertible_to<ROS, std​::​span<charT const>> is true.
Effects: Let sp be std​::​span<const charT>(std​::​forward<ROS>(s)).
Equivalent to: basic_ispanstream(std::span<charT>(const_cast<charT*>(sp.data()), sp.size()))

31.9.4.3 Swap [ispanstream.swap]

void swap(basic_ispanstream& rhs);
Effects: Equivalent to: basic_istream<charT, traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits> void swap(basic_ispanstream<charT, traits>& x, basic_ispanstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.9.4.4 Member functions [ispanstream.members]

basic_spanbuf<charT, traits>* rdbuf() const noexcept;
Effects: Equivalent to: return const_cast<basic_spanbuf<charT, traits>*>(addressof(sb));
std::span<const charT> span() const noexcept;
Effects: Equivalent to: return rdbuf()->span();
void span(std::span<charT> s) noexcept;
Effects: Equivalent to rdbuf()->span(s).
template<class ROS> void span(ROS&& s) noexcept;
Constraints: ROS models ranges​::​borrowed_range.
(!convertible_to<ROS, std​::​span<charT>>) && convertible_to<ROS, std​::​span<const charT>> is true.
Effects: Let sp be std​::​span<const charT>(std​::​forward<ROS>(s)).
Equivalent to: this->span(std::span<charT>(const_cast<charT*>(sp.data()), sp.size()));

31.9.5 Class template basic_ospanstream [ospanstream]

31.9.5.1 General [ospanstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_ospanstream : public basic_ostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [ospanstream.cons], constructors explicit basic_ospanstream(std::span<charT> s, ios_base::openmode which = ios_base::out); basic_ospanstream(const basic_ospanstream&) = delete; basic_ospanstream(basic_ospanstream&& rhs); basic_ospanstream& operator=(const basic_ospanstream&) = delete; basic_ospanstream& operator=(basic_ospanstream&& rhs); // [ospanstream.swap], swap void swap(basic_ospanstream& rhs); // [ospanstream.members], member functions basic_spanbuf<charT, traits>* rdbuf() const noexcept; std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; private: basic_spanbuf<charT, traits> sb; // exposition only }; }

31.9.5.2 Constructors [ospanstream.cons]

explicit basic_ospanstream(std::span<charT> s, ios_base::openmode which = ios_base::out);
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) and sb with basic_spanbuf<charT, traits>(s, which | ios_base​::​out) ([spanbuf.cons]).
basic_ospanstream(basic_ospanstream&& rhs) noexcept;
Effects: Initializes the base class with std​::​move(rhs) and sb with std​::​move(rhs.sb).
Next, basic_ostream<charT, traits>​::​set_rdbuf(addressof(sb)) is called to install the contained basic_spanbuf.

31.9.5.3 Swap [ospanstream.swap]

void swap(basic_ospanstream& rhs);
Effects: Equivalent to: basic_ostream<charT, traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits> void swap(basic_ospanstream<charT, traits>& x, basic_ospanstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.9.5.4 Member functions [ospanstream.members]

basic_spanbuf<charT, traits>* rdbuf() const noexcept;
Effects: Equivalent to: return const_cast<basic_spanbuf<charT, traits>*>(addressof(sb));
std::span<charT> span() const noexcept;
Effects: Equivalent to: return rdbuf()->span();
void span(std::span<charT> s) noexcept;
Effects: Equivalent to rdbuf()->span(s).

31.9.6 Class template basic_spanstream [spanstream]

31.9.6.1 General [spanstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_spanstream : public basic_iostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [spanstream.cons], constructors explicit basic_spanstream(std::span<charT> s, ios_base::openmode which = ios_base::out | ios_base::in); basic_spanstream(const basic_spanstream&) = delete; basic_spanstream(basic_spanstream&& rhs); basic_spanstream& operator=(const basic_spanstream&) = delete; basic_spanstream& operator=(basic_spanstream&& rhs); // [spanstream.swap], swap void swap(basic_spanstream& rhs); // [spanstream.members], members basic_spanbuf<charT, traits>* rdbuf() const noexcept; std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; private: basic_spanbuf<charT, traits> sb; // exposition only }; }

31.9.6.2 Constructors [spanstream.cons]

explicit basic_spanstream(std::span<charT> s, ios_base::openmode which = ios_base::out | ios_bas::in);
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) and sb with basic_spanbuf<charT, traits>(s, which) ([spanbuf.cons]).
basic_spanstream(basic_spanstream&& rhs);
Effects: Initializes the base class with std​::​move(rhs) and sb with std​::​move(rhs.sb).
Next, basic_iostream<charT, traits>​::​set_rdbuf(addressof(sb)) is called to install the contained basic_spanbuf.

31.9.6.3 Swap [spanstream.swap]

void swap(basic_spanstream& rhs);
Effects: Equivalent to: basic_iostream<charT, traits>::swap(rhs); sb.swap(rhs.sb);
template<class charT, class traits> void swap(basic_spanstream<charT, traits>& x, basic_spanstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.9.6.4 Member functions [spanstream.members]

basic_spanbuf<charT, traits>* rdbuf() const noexcept;
Effects: Equivalent to: return const_cast<basic_spanbuf<charT, traits>*>(addressof(sb));
std::span<charT> span() const noexcept;
Effects: Equivalent to: return rdbuf()->span();
void span(std::span<charT> s) noexcept;
Effects: Equivalent to rdbuf()->span(s).

31.10 File-based streams [file.streams]

31.10.1 Header <fstream> synopsis [fstream.syn]

namespace std { // [filebuf], class template basic_filebuf template<class charT, class traits = char_traits<charT>> class basic_filebuf; template<class charT, class traits> void swap(basic_filebuf<charT, traits>& x, basic_filebuf<charT, traits>& y); using filebuf = basic_filebuf<char>; using wfilebuf = basic_filebuf<wchar_t>; // [ifstream], class template basic_ifstream template<class charT, class traits = char_traits<charT>> class basic_ifstream; template<class charT, class traits> void swap(basic_ifstream<charT, traits>& x, basic_ifstream<charT, traits>& y); using ifstream = basic_ifstream<char>; using wifstream = basic_ifstream<wchar_t>; // [ofstream], class template basic_ofstream template<class charT, class traits = char_traits<charT>> class basic_ofstream; template<class charT, class traits> void swap(basic_ofstream<charT, traits>& x, basic_ofstream<charT, traits>& y); using ofstream = basic_ofstream<char>; using wofstream = basic_ofstream<wchar_t>; // [fstream], class template basic_fstream template<class charT, class traits = char_traits<charT>> class basic_fstream; template<class charT, class traits> void swap(basic_fstream<charT, traits>& x, basic_fstream<charT, traits>& y); using fstream = basic_fstream<char>; using wfstream = basic_fstream<wchar_t>; }
The header <fstream> defines four class templates and eight types that associate stream buffers with files and assist reading and writing files.
[Note 1: 
The class template basic_filebuf treats a file as a source or sink of bytes.
In an environment that uses a large character set, the file typically holds multibyte character sequences and the basic_filebuf object converts those multibyte sequences into wide character sequences.
— end note]
In subclause [file.streams], member functions taking arguments of const filesystem​::​path​::​value_type* are only provided on systems where filesystem​::​path​::​value_type ([fs.class.path]) is not char.
[Note 2: 
These functions enable class path support for systems with a wide native path character type, such as wchar_t.
— end note]

31.10.2 Native handles [file.native]

Several classes described in [file.streams] have a member native_handle_type.
The type native_handle_type represents a platform-specific native handle to a file.
It is trivially copyable and models semiregular.
[Note 1: 
For operating systems based on POSIX, native_handle_type is int.
For Windows-based operating systems, native_handle_type is HANDLE.
— end note]

31.10.3 Class template basic_filebuf [filebuf]

31.10.3.1 General [filebuf.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_filebuf : public basic_streambuf<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using native_handle_type = implementation-defined; // see [file.native] // [filebuf.cons], constructors/destructor basic_filebuf(); basic_filebuf(const basic_filebuf&) = delete; basic_filebuf(basic_filebuf&& rhs); virtual ~basic_filebuf(); // [filebuf.assign], assignment and swap basic_filebuf& operator=(const basic_filebuf&) = delete; basic_filebuf& operator=(basic_filebuf&& rhs); void swap(basic_filebuf& rhs); // [filebuf.members], members bool is_open() const; basic_filebuf* open(const char* s, ios_base::openmode mode); basic_filebuf* open(const filesystem::path::value_type* s, ios_base::openmode mode); // wide systems only; see [fstream.syn] basic_filebuf* open(const string& s, ios_base::openmode mode); basic_filebuf* open(const filesystem::path& s, ios_base::openmode mode); basic_filebuf* close(); native_handle_type native_handle() const noexcept; protected: // [filebuf.virtuals], overridden virtual functions streamsize showmanyc() override; int_type underflow() override; int_type uflow() override; int_type pbackfail(int_type c = traits::eof()) override; int_type overflow (int_type c = traits::eof()) override; basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) override; pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override; pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override; int sync() override; void imbue(const locale& loc) override; }; }
The class basic_filebuf<charT, traits> associates both the input sequence and the output sequence with a file.
The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf<charT, traits> are the same as for reading and writing with the C standard library FILEs.
In particular:
  • If the file is not open for reading the input sequence cannot be read.
  • If the file is not open for writing the output sequence cannot be written.
  • A joint file position is maintained for both the input sequence and the output sequence.
An instance of basic_filebuf behaves as described in [filebuf] provided traits​::​pos_type is fpos<traits​::​​state_type>.
Otherwise the behavior is undefined.
The file associated with a basic_filebuf has an associated value of type native_handle_type, called the native handle ([file.native]) of that file.
This native handle can be obtained by calling the member function native_handle.
For any opened basic_filebuf f, the native handle returned by f.native_handle() is invalidated when f.close() is called, or f is destroyed.
In order to support file I/O and multibyte/wide character conversion, conversions are performed using members of a facet, referred to as a_codecvt in following subclauses, obtained as if by const codecvt<charT, char, typename traits::state_type>& a_codecvt = use_facet<codecvt<charT, char, typename traits::state_type>>(getloc());

31.10.3.2 Constructors [filebuf.cons]

basic_filebuf();
Effects: Initializes the base class with basic_streambuf<charT, traits>() ([streambuf.cons]).
Postconditions: is_open() == false.
basic_filebuf(basic_filebuf&& rhs);
Effects: It is implementation-defined whether the sequence pointers in *this (eback(), gptr(), egptr(), pbase(), pptr(), epptr()) obtain the values which rhs had.
Whether they do or not, *this and rhs reference separate buffers (if any at all) after the construction.
Additionally *this references the file which rhs did before the construction, and rhs references no file after the construction.
The openmode, locale and any other state of rhs is also copied.
Postconditions: Let rhs_p refer to the state of rhs just prior to this construction and let rhs_a refer to the state of rhs just after this construction.
  • is_open() == rhs_p.is_open()
  • rhs_a.is_open() == false
  • gptr() - eback() == rhs_p.gptr() - rhs_p.eback()
  • egptr() - eback() == rhs_p.egptr() - rhs_p.eback()
  • pptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()
  • epptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()
  • if (eback()) eback() != rhs_a.eback()
  • if (gptr()) gptr() != rhs_a.gptr()
  • if (egptr()) egptr() != rhs_a.egptr()
  • if (pbase()) pbase() != rhs_a.pbase()
  • if (pptr()) pptr() != rhs_a.pptr()
  • if (epptr()) epptr() != rhs_a.epptr()
virtual ~basic_filebuf();
Effects: Calls close().
If an exception occurs during the destruction of the object, including the call to close(), the exception is caught but not rethrown (see [res.on.exception.handling]).

31.10.3.3 Assignment and swap [filebuf.assign]

basic_filebuf& operator=(basic_filebuf&& rhs);
Effects: Calls close() then move assigns from rhs.
After the move assignment *this has the observable state it would have had if it had been move constructed from rhs (see [filebuf.cons]).
Returns: *this.
void swap(basic_filebuf& rhs);
Effects: Exchanges the state of *this and rhs.
template<class charT, class traits> void swap(basic_filebuf<charT, traits>& x, basic_filebuf<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.10.3.4 Member functions [filebuf.members]

bool is_open() const;
Returns: true if a previous call to open succeeded (returned a non-null value) and there has been no intervening call to close.
basic_filebuf* open(const char* s, ios_base::openmode mode); basic_filebuf* open(const filesystem::path::value_type* s, ios_base::openmode mode); // wide systems only; see [fstream.syn]
Preconditions: s points to a NTCTS ([defns.ntcts]).
Effects: If is_open() != false, returns a null pointer.
Otherwise, initializes the filebuf as required.
It then opens the file to which s resolves, if possible, as if by a call to fopen with the second argument determined from mode & ~ios_base​::​ate as indicated in Table 141.
If mode is not some combination of flags shown in the table then the open fails.
Table 141 — File open modes [tab:filebuf.open.modes]
ios_base flag combination
stdio equivalent
binary
in
out
trunc
app
noreplace
+
"w"
+
+
"wx"
+
+
"w"
+
+
+
"wx"
+
+
"a"
+
"a"
+
"r"
+
+
"r+"
+
+
+
"w+"
+
+
+
+
"w+x"
+
+
+
"a+"
+
+
"a+"
+
+
"wb"
+
+
+
"wbx"
+
+
+
"wb"
+
+
+
+
"wbx"
+
+
+
"ab"
+
+
"ab"
+
+
"rb"
+
+
+
"r+b"
+
+
+
+
"w+b"
+
+
+
+
+
"w+bx"
+
+
+
+
"a+b"
+
+
+
"a+b"
If the open operation succeeds and ios_base​::​ate is set in mode, positions the file to the end (as if by calling fseek(file, 0, SEEK_END), where file is the pointer returned by calling fopen).296
If the repositioning operation fails, calls close() and returns a null pointer to indicate failure.
Returns: this if successful, a null pointer otherwise.
basic_filebuf* open(const string& s, ios_base::openmode mode); basic_filebuf* open(const filesystem::path& s, ios_base::openmode mode);
Returns: open(s.c_str(), mode);
basic_filebuf* close();
Effects: If is_open() == false, returns a null pointer.
If a put area exists, calls overflow(traits​::​​eof()) to flush characters.
If the last virtual member function called on *this (between underflow, overflow, seekoff, and seekpos) was overflow then calls a_codecvt.unshift (possibly several times) to determine a termination sequence, inserts those characters and calls overflow(traits​::​​eof()) again.
Finally, regardless of whether any of the preceding calls fails or throws an exception, the function closes the file (as if by calling fclose(file)).
If any of the calls made by the function, including fclose, fails, close fails by returning a null pointer.
If one of these calls throws an exception, the exception is caught and rethrown after closing the file.
Postconditions: is_open() == false.
Returns: this on success, a null pointer otherwise.
native_handle_type native_handle() const noexcept;
Preconditions: is_open() is true.
Returns: The native handle associated with *this.
296)296)
The macro SEEK_END is defined, and the function signatures fopen(const char*, const char*) and fseek(FILE*, long, int) are declared, in <cstdio>.

31.10.3.5 Overridden virtual functions [filebuf.virtuals]

streamsize showmanyc() override;
Effects: Behaves the same as basic_streambuf​::​showmanyc() ([streambuf.virtuals]).
Remarks: An implementation may provide an overriding definition for this function signature if it can determine whether more characters can be read from the input sequence.
int_type underflow() override;
Effects: Behaves according to the description of basic_streambuf<charT, traits>​::​underflow(), with the specialization that a sequence of characters is read from the input sequence as if by reading from the associated file into an internal buffer (extern_buf) and then as if by doing: char extern_buf[XSIZE]; char* extern_end; charT intern_buf[ISIZE]; charT* intern_end; codecvt_base::result r = a_codecvt.in(state, extern_buf, extern_buf+XSIZE, extern_end, intern_buf, intern_buf+ISIZE, intern_end);
This shall be done in such a way that the class can recover the position (fpos_t) corresponding to each character between intern_buf and intern_end.
If the value of r indicates that a_codecvt.in() ran out of space in intern_buf, retry with a larger intern_buf.
int_type uflow() override;
Effects: Behaves according to the description of basic_streambuf<charT, traits>​::​uflow(), with the specialization that a sequence of characters is read from the input with the same method as used by underflow.
int_type pbackfail(int_type c = traits::eof()) override;
Effects: Puts back the character designated by c to the input sequence, if possible, in one of three ways:
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false and if the function makes a putback position available and if traits​::​eq(to_char_type(c), gptr()[-1]) returns true, decrements the next pointer for the input sequence, gptr().
    Returns: c.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns false and if the function makes a putback position available and if the function is permitted to assign to the putback position, decrements the next pointer for the input sequence, and stores c there.
    Returns: c.
  • If traits​::​eq_int_type(c, traits​::​eof()) returns true, and if either the input sequence has a putback position available or the function makes a putback position available, decrements the next pointer for the input sequence, gptr().
    Returns: traits​::​not_eof(c).
Returns: As specified above, or traits​::​eof() to indicate failure.
Remarks: If is_open() == false, the function always fails.
The function does not put back a character directly to the input sequence.
If the function can succeed in more than one of these ways, it is unspecified which way is chosen.
The function can alter the number of putback positions available as a result of any call.
int_type overflow(int_type c = traits::eof()) override;
Effects: Behaves according to the description of basic_streambuf<charT, traits>​::​overflow(c), except that the behavior of “consuming characters” is performed by first converting as if by: charT* b = pbase(); charT* p = pptr(); charT* end; char xbuf[XSIZE]; char* xbuf_end; codecvt_base::result r = a_codecvt.out(state, b, p, end, xbuf, xbuf+XSIZE, xbuf_end); and then
  • If r == codecvt_base​::​error then fail.
  • If r == codecvt_base​::​noconv then output characters from b up to (and not including) p.
  • If r == codecvt_base​::​partial then output to the file characters from xbuf up to xbuf_end, and repeat using characters from end to p.
    If output fails, fail (without repeating).
  • Otherwise output from xbuf to xbuf_end, and fail if output fails.
    At this point if b != p and b == end (xbuf isn't large enough) then increase XSIZE and repeat from the beginning.
Returns: traits​::​not_eof(c) to indicate success, and traits​::​eof() to indicate failure.
If is_open() == false, the function always fails.
basic_streambuf* setbuf(char_type* s, streamsize n) override;
Effects: If setbuf(0, 0) is called on a stream before any I/O has occurred on that stream, the stream becomes unbuffered.
Otherwise the results are implementation-defined.
“Unbuffered” means that pbase() and pptr() always return null and output to the file should appear as soon as possible.
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
Effects: Let width denote a_codecvt.encoding().
If is_open() == false, or off != 0 && width <= 0, then the positioning operation fails.
Otherwise, if way != basic_ios​::​cur or off != 0, and if the last operation was output, then update the output sequence and write any unshift sequence.
Next, seek to the new position: if width > 0, call fseek(file, width * off, whence), otherwise call fseek(file, 0, whence).
Returns: A newly constructed pos_type object that stores the resultant stream position, if possible.
If the positioning operation fails, or if the object cannot represent the resultant stream position, returns pos_type(off_type(-1)).
Remarks: “The last operation was output” means either the last virtual operation was overflow or the put buffer is non-empty.
“Write any unshift sequence” means, if width is less than zero then call a_codecvt.unshift(state, xbuf, xbuf+XSIZE, xbuf_end) and output the resulting unshift sequence.
The function determines one of three values for the argument whence, of type int, as indicated in Table 142.
Table 142seekoff effects [tab:filebuf.seekoff]
way Value
stdio Equivalent
basic_ios​::​beg
SEEK_SET
basic_ios​::​cur
SEEK_CUR
basic_ios​::​end
SEEK_END
pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
Alters the file position, if possible, to correspond to the position stored in sp (as described below).
Altering the file position performs as follows:
1.if (om & ios_base​::​out) != 0, then update the output sequence and write any unshift sequence;
2.set the file position to sp as if by a call to fsetpos;
3.if (om & ios_base​::​in) != 0, then update the input sequence;
where om is the open mode passed to the last call to open().
The operation fails if is_open() returns false.
If sp is an invalid stream position, or if the function positions neither sequence, the positioning operation fails.
If sp has not been obtained by a previous successful call to one of the positioning functions (seekoff or seekpos) on the same file the effects are undefined.
Returns: sp on success.
Otherwise returns pos_type(off_type(-1)).
int sync() override;
Effects: If a put area exists, calls filebuf​::​overflow to write the characters to the file, then flushes the file as if by calling fflush(file).
If a get area exists, the effect is implementation-defined.
void imbue(const locale& loc) override;
Preconditions: If the file is not positioned at its beginning and the encoding of the current locale as determined by a_codecvt.encoding() is state-dependent ([locale.codecvt.virtuals]) then that facet is the same as the corresponding facet of loc.
Effects: Causes characters inserted or extracted after this call to be converted according to loc until another call of imbue.
Remarks: This may require reconversion of previously converted characters.
This in turn may require the implementation to be able to reconstruct the original contents of the file.

31.10.4 Class template basic_ifstream [ifstream]

31.10.4.1 General [ifstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_ifstream : public basic_istream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // [ifstream.cons], constructors basic_ifstream(); explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in); explicit basic_ifstream(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in);// wide systems only; see [fstream.syn] explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in); template<class T> explicit basic_ifstream(const T& s, ios_base::openmode mode = ios_base::in); basic_ifstream(const basic_ifstream&) = delete; basic_ifstream(basic_ifstream&& rhs); basic_ifstream& operator=(const basic_ifstream&) = delete; basic_ifstream& operator=(basic_ifstream&& rhs); // [ifstream.swap], swap void swap(basic_ifstream& rhs); // [ifstream.members], members basic_filebuf<charT, traits>* rdbuf() const; native_handle_type native_handle() const noexcept; bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in); void open(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in); // wide systems only; see [fstream.syn] void open(const string& s, ios_base::openmode mode = ios_base::in); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); void close(); private: basic_filebuf<charT, traits> sb; // exposition only }; }
The class basic_ifstream<charT, traits> supports reading from named files.
It uses a basic_filebuf<​charT, traits> object to control the associated sequence.
For the sake of exposition, the maintained data is presented here as:

31.10.4.2 Constructors [ifstream.cons]

basic_ifstream();
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream.cons]) and sb with basic_filebuf<charT, traits>() ([filebuf.cons]).
explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in); explicit basic_ifstream(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in); // wide systems only; see [fstream.syn]
Effects: Initializes the base class with basic_istream<charT, traits>(addressof(sb)) ([istream.cons]) and sb with basic_filebuf<charT, traits>() ([filebuf.cons]), then calls rdbuf()->open(s, mode | ios_base​::​in).
If that function returns a null pointer, calls setstate(failbit).
explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in);
Effects: Equivalent to basic_ifstream(s.c_str(), mode).
template<class T> explicit basic_ifstream(const T& s, ios_base::openmode mode = ios_base::in);
Constraints: is_same_v<T, filesystem​::​path> is true.
Effects: Equivalent to basic_ifstream(s.c_str(), mode).
basic_ifstream(basic_ifstream&& rhs);
Effects: Move constructs the base class, and the contained basic_filebuf.
Then calls basic_istream<charT, traits>​::​set_rdbuf(​addressof(sb)) to install the contained basic_filebuf.

31.10.4.3 Swap [ifstream.swap]

void swap(basic_ifstream& rhs);
Effects: Exchanges the state of *this and rhs by calling basic_istream<charT, traits>​::​swap(rhs) and sb.swap(rhs.sb).
template<class charT, class traits> void swap(basic_ifstream<charT, traits>& x, basic_ifstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.10.4.4 Member functions [ifstream.members]

basic_filebuf<charT, traits>* rdbuf() const;
Returns: const_cast<basic_filebuf<charT, traits>*>(addressof(@sb@)).
native_handle_type native_handle() const noexcept;
Effects: Equivalent to: return rdbuf()->native_handle();
bool is_open() const;
Returns: rdbuf()->is_open().
void open(const char* s, ios_base::openmode mode = ios_base::in); void open(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in); // wide systems only; see [fstream.syn]
Effects: Calls rdbuf()->open(s, mode | ios_base​::​in).
If that function does not return a null pointer calls clear(), otherwise calls setstate(failbit) (which may throw ios_base​::​failure) ([iostate.flags]).
void open(const string& s, ios_base::openmode mode = ios_base::in); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in);
Effects: Calls open(s.c_str(), mode).
void close();
Effects: Calls rdbuf()->close() and, if that function returns a null pointer, calls setstate(failbit) (which may throw ios_base​::​failure) ([iostate.flags]).

31.10.5 Class template basic_ofstream [ofstream]

31.10.5.1 General [ofstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_ofstream : public basic_ostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // [ofstream.cons], constructors basic_ofstream(); explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out); explicit basic_ofstream(const filesystem::path::value_type* s, // wide systems only; see [fstream.syn] ios_base::openmode mode = ios_base::out); explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out); template<class T> explicit basic_ofstream(const T& s, ios_base::openmode mode = ios_base::out); basic_ofstream(const basic_ofstream&) = delete; basic_ofstream(basic_ofstream&& rhs); basic_ofstream& operator=(const basic_ofstream&) = delete; basic_ofstream& operator=(basic_ofstream&& rhs); // [ofstream.swap], swap void swap(basic_ofstream& rhs); // [ofstream.members], members basic_filebuf<charT, traits>* rdbuf() const; native_handle_type native_handle() const noexcept; bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::out); void open(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::out); // wide systems only; see [fstream.syn] void open(const string& s, ios_base::openmode mode = ios_base::out); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::out); void close(); private: basic_filebuf<charT, traits> sb; // exposition only }; }
The class basic_ofstream<charT, traits> supports writing to named files.
It uses a basic_filebuf<​charT, traits> object to control the associated sequence.
For the sake of exposition, the maintained data is presented here as:

31.10.5.2 Constructors [ofstream.cons]

basic_ofstream();
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream.cons]) and sb with basic_filebuf<charT, traits>() ([filebuf.cons]).
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out); explicit basic_ofstream(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::out); // wide systems only; see [fstream.syn]
Effects: Initializes the base class with basic_ostream<charT, traits>(addressof(sb)) ([ostream.cons]) and sb with basic_filebuf<charT, traits>() ([filebuf.cons]), then calls rdbuf()->open(s, mode | ios_base​::​out).
If that function returns a null pointer, calls setstate(​failbit).
explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out);
Effects: Equivalent to basic_ofstream(s.c_str(), mode).
template<class T> explicit basic_ofstream(const T& s, ios_base::openmode mode = ios_base::out);
Constraints: is_same_v<T, filesystem​::​path> is true.
Effects: Equivalent to basic_ofstream(s.c_str(), mode).
basic_ofstream(basic_ofstream&& rhs);
Effects: Move constructs the base class, and the contained basic_filebuf.
Then calls basic_ostream<charT, traits>​::​set_rdbuf(​addressof(sb)) to install the contained basic_filebuf.

31.10.5.3 Swap [ofstream.swap]

void swap(basic_ofstream& rhs);
Effects: Exchanges the state of *this and rhs by calling basic_ostream<charT, traits>​::​swap(rhs) and sb.swap(rhs.sb).
template<class charT, class traits> void swap(basic_ofstream<charT, traits>& x, basic_ofstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.10.5.4 Member functions [ofstream.members]

basic_filebuf<charT, traits>* rdbuf() const;
Returns: const_cast<basic_filebuf<charT, traits>*>(addressof(sb)).
native_handle_type native_handle() const noexcept;
Effects: Equivalent to: return rdbuf()->native_handle();
bool is_open() const;
Returns: rdbuf()->is_open().
void open(const char* s, ios_base::openmode mode = ios_base::out); void open(const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::out); // wide systems only; see [fstream.syn]
Effects: Calls rdbuf()->open(s, mode | ios_base​::​out).
If that function does not return a null pointer calls clear(), otherwise calls setstate(​failbit) (which may throw ios_base​::​failure) ([iostate.flags]).
void close();
Effects: Calls rdbuf()->close() and, if that function fails (returns a null pointer), calls setstate(​failbit) (which may throw ios_base​::​failure) ([iostate.flags]).
void open(const string& s, ios_base::openmode mode = ios_base::out); void open(const filesystem::path& s, ios_base::openmode mode = ios_base::out);
Effects: Calls open(s.c_str(), mode).

31.10.6 Class template basic_fstream [fstream]

31.10.6.1 General [fstream.general]

namespace std { template<class charT, class traits = char_traits<charT>> class basic_fstream : public basic_iostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // [fstream.cons], constructors basic_fstream(); explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out); explicit basic_fstream( const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in|ios_base::out); // wide systems only; see [fstream.syn] explicit basic_fstream( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out); template<class T> explicit basic_fstream(const T& s, ios_base::openmode mode = ios_base::in | ios_base::out); basic_fstream(const basic_fstream&) = delete; basic_fstream(basic_fstream&& rhs); basic_fstream& operator=(const basic_fstream&) = delete; basic_fstream& operator=(basic_fstream&& rhs); // [fstream.swap], swap void swap(basic_fstream& rhs); // [fstream.members], members basic_filebuf<charT, traits>* rdbuf() const; native_handle_type native_handle() const noexcept; bool is_open() const; void open( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out); void open( const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in|ios_base::out); // wide systems only; see [fstream.syn] void open( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out); void open( const filesystem::path& s, ios_base::openmode mode = ios_base::in | ios_base::out); void close(); private: basic_filebuf<charT, traits> sb; // exposition only }; }
The class template basic_fstream<charT, traits> supports reading and writing from named files.
It uses a basic_filebuf<charT, traits> object to control the associated sequences.
For the sake of exposition, the maintained data is presented here as:
  • sb, the basic_filebuf object.

31.10.6.2 Constructors [fstream.cons]

basic_fstream();
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_filebuf<charT, traits>().
explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out); explicit basic_fstream( const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in | ios_base::out); // wide systems only; see [fstream.syn]
Effects: Initializes the base class with basic_iostream<charT, traits>(addressof(sb)) ([iostream.cons]) and sb with basic_filebuf<charT, traits>().
Then calls rdbuf()->open(s, mode).
If that function returns a null pointer, calls setstate(failbit).
explicit basic_fstream( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out);
Effects: Equivalent to basic_fstream(s.c_str(), mode).
template<class T> explicit basic_fstream(const T& s, ios_base::openmode mode = ios_base::in | ios_base::out);
Constraints: is_same_v<T, filesystem​::​path> is true.
Effects: Equivalent to basic_fstream(s.c_str(), mode).
basic_fstream(basic_fstream&& rhs);
Effects: Move constructs the base class, and the contained basic_filebuf.
Then calls basic_istream<charT, traits>​::​set_rdbuf(​addressof(sb)) to install the contained basic_filebuf.

31.10.6.3 Swap [fstream.swap]

void swap(basic_fstream& rhs);
Effects: Exchanges the state of *this and rhs by calling basic_iostream<charT,traits>​::​swap(rhs) and sb.swap(rhs.sb).
template<class charT, class traits> void swap(basic_fstream<charT, traits>& x, basic_fstream<charT, traits>& y);
Effects: Equivalent to x.swap(y).

31.10.6.4 Member functions [fstream.members]

basic_filebuf<charT, traits>* rdbuf() const;
Returns: const_cast<basic_filebuf<charT, traits>*>(addressof(sb)).
native_handle_type native_handle() const noexcept;
Effects: Equivalent to: return rdbuf()->native_handle();
bool is_open() const;
Returns: rdbuf()->is_open().
void open( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out); void open( const filesystem::path::value_type* s, ios_base::openmode mode = ios_base::in | ios_base::out); // wide systems only; see [fstream.syn]
Effects: Calls rdbuf()->open(s, mode).
If that function does not return a null pointer calls clear(), otherwise calls setstate(failbit) (which may throw ios_base​::​failure) ([iostate.flags]).
void open( const string& s, ios_base::openmode mode = ios_base::in | ios_base::out); void open( const filesystem::path& s, ios_base::openmode mode = ios_base::in | ios_base::out);
Effects: Calls open(s.c_str(), mode).
void close();
Effects: Calls rdbuf()->close() and, if that function returns a null pointer, calls setstate(failbit) (which may throw ios_base​::​failure) ([iostate.flags]).

31.11 Synchronized output streams [syncstream]

31.11.1 Header <syncstream> synopsis [syncstream.syn]

#include <ostream> // see [ostream.syn] namespace std { // [syncstream.syncbuf], class template basic_syncbuf template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_syncbuf; // [syncstream.syncbuf.special], specialized algorithms template<class charT, class traits, class Allocator> void swap(basic_syncbuf<charT, traits, Allocator>&, basic_syncbuf<charT, traits, Allocator>&); using syncbuf = basic_syncbuf<char>; using wsyncbuf = basic_syncbuf<wchar_t>; // [syncstream.osyncstream], class template basic_osyncstream template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_osyncstream; using osyncstream = basic_osyncstream<char>; using wosyncstream = basic_osyncstream<wchar_t>; }
The header <syncstream> provides a mechanism to synchronize execution agents writing to the same stream.

31.11.2 Class template basic_syncbuf [syncstream.syncbuf]

31.11.2.1 Overview [syncstream.syncbuf.overview]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_syncbuf : public basic_streambuf<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; using streambuf_type = basic_streambuf<charT, traits>; // [syncstream.syncbuf.cons], construction and destruction basic_syncbuf() : basic_syncbuf(nullptr) {} explicit basic_syncbuf(streambuf_type* obuf) : basic_syncbuf(obuf, Allocator()) {} basic_syncbuf(streambuf_type*, const Allocator&); basic_syncbuf(basic_syncbuf&&); ~basic_syncbuf(); // [syncstream.syncbuf.assign], assignment and swap basic_syncbuf& operator=(basic_syncbuf&&); void swap(basic_syncbuf&); // [syncstream.syncbuf.members], member functions bool emit(); streambuf_type* get_wrapped() const noexcept; allocator_type get_allocator() const noexcept; void set_emit_on_sync(bool) noexcept; protected: // [syncstream.syncbuf.virtuals], overridden virtual functions int sync() override; private: streambuf_type* wrapped; // exposition only bool emit-on-sync{}; // exposition only }; }
Class template basic_syncbuf stores character data written to it, known as the associated output, into internal buffers allocated using the object's allocator.
The associated output is transferred to the wrapped stream buffer object *wrapped when emit() is called or when the basic_syncbuf object is destroyed.
Such transfers are atomic with respect to transfers by other basic_syncbuf objects with the same wrapped stream buffer object.

31.11.2.2 Construction and destruction [syncstream.syncbuf.cons]

basic_syncbuf(streambuf_type* obuf, const Allocator& allocator);
Effects: Sets wrapped to obuf.
Postconditions: get_wrapped() == obuf and get_allocator() == allocator are true.
Throws: Nothing unless an exception is thrown by the construction of a mutex or by memory allocation.
Remarks: A copy of allocator is used to allocate memory for internal buffers holding the associated output.
basic_syncbuf(basic_syncbuf&& other);
Postconditions: The value returned by this->get_wrapped() is the value returned by other.get_wrapped() prior to calling this constructor.
Output stored in other prior to calling this constructor will be stored in *this afterwards.
other.pbase() == other.pptr() and other.get_wrapped() == nullptr are true.
Remarks: This constructor disassociates other from its wrapped stream buffer, ensuring destruction of other produces no output.
~basic_syncbuf();
Effects: Calls emit().
Throws: Nothing.
If an exception is thrown from emit(), the destructor catches and ignores that exception.

31.11.2.3 Assignment and swap [syncstream.syncbuf.assign]

basic_syncbuf& operator=(basic_syncbuf&& rhs);
Effects: Calls emit() then move assigns from rhs.
After the move assignment *this has the observable state it would have had if it had been move constructed from rhs ([syncstream.syncbuf.cons]).
Postconditions:
  • rhs.get_wrapped() == nullptr is true.
  • this->get_allocator() == rhs.get_allocator() is true when allocator_traits<Allocator>::propagate_on_container_move_assignment::value is true; otherwise, the allocator is unchanged.
Returns: *this.
Remarks: This assignment operator disassociates rhs from its wrapped stream buffer, ensuring destruction of rhs produces no output.
void swap(basic_syncbuf& other);
Preconditions: Either allocator_traits<Allocator>​::​propagate_on_container_swap​::​value is true or this->get_allocator() == other.get_allocator() is true.
Effects: Exchanges the state of *this and other.

31.11.2.4 Member functions [syncstream.syncbuf.members]

bool emit();
Effects: Atomically transfers the associated output of *this to the stream buffer *wrapped, so that it appears in the output stream as a contiguous sequence of characters.
wrapped->pubsync() is called if and only if a call was made to sync() since the most recent call to emit(), if any.
Synchronization: All emit() calls transferring characters to the same stream buffer object appear to execute in a total order consistent with the “happens before” relation ([intro.races]), where each emit() call synchronizes with subsequent emit() calls in that total order.
Postconditions: On success, the associated output is empty.
Returns: true if all of the following conditions hold; otherwise false:
  • wrapped == nullptr is false.
  • All of the characters in the associated output were successfully transferred.
  • The call to wrapped->pubsync() (if any) succeeded.
Remarks: May call member functions of wrapped while holding a lock uniquely associated with wrapped.
streambuf_type* get_wrapped() const noexcept;
Returns: wrapped.
allocator_type get_allocator() const noexcept;
Returns: A copy of the allocator that was set in the constructor or assignment operator.
void set_emit_on_sync(bool b) noexcept;
Effects: emit-on-sync = b.

31.11.2.5 Overridden virtual functions [syncstream.syncbuf.virtuals]

int sync() override;
Effects: Records that the wrapped stream buffer is to be flushed.
Then, if emit-on-sync is true, calls emit().
[Note 1: 
If emit-on-sync is false, the actual flush is delayed until a call to emit().
— end note]
Returns: If emit() was called and returned false, returns -1; otherwise 0.

31.11.2.6 Specialized algorithms [syncstream.syncbuf.special]

template<class charT, class traits, class Allocator> void swap(basic_syncbuf<charT, traits, Allocator>& a, basic_syncbuf<charT, traits, Allocator>& b);
Effects: Equivalent to a.swap(b).

31.11.3 Class template basic_osyncstream [syncstream.osyncstream]

31.11.3.1 Overview [syncstream.osyncstream.overview]

namespace std { template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_osyncstream : public basic_ostream<charT, traits> { public: using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; using allocator_type = Allocator; using streambuf_type = basic_streambuf<charT, traits>; using syncbuf_type = basic_syncbuf<charT, traits, Allocator>; // [syncstream.osyncstream.cons], construction and destruction basic_osyncstream(streambuf_type*, const Allocator&); explicit basic_osyncstream(streambuf_type* obuf) : basic_osyncstream(obuf, Allocator()) {} basic_osyncstream(basic_ostream<charT, traits>& os, const Allocator& allocator) : basic_osyncstream(os.rdbuf(), allocator) {} explicit basic_osyncstream(basic_ostream<charT, traits>& os) : basic_osyncstream(os, Allocator()) {} basic_osyncstream(basic_osyncstream&&) noexcept; ~basic_osyncstream(); // assignment basic_osyncstream& operator=(basic_osyncstream&&); // [syncstream.osyncstream.members], member functions void emit(); streambuf_type* get_wrapped() const noexcept; syncbuf_type* rdbuf() const noexcept { return const_cast<syncbuf_type*>(addressof(sb)); } private: syncbuf_type sb; // exposition only }; }
Allocator shall meet the Cpp17Allocator requirements ([allocator.requirements.general]).
[Example 1: 
A named variable can be used within a block statement for streaming.
{ osyncstream bout(cout); bout << "Hello, "; bout << "World!"; bout << endl; // flush is noted bout << "and more!\n"; } // characters are transferred and cout is flushed — end example]
[Example 2: 
A temporary object can be used for streaming within a single statement.
osyncstream(cout) << "Hello, " << "World!" << '\n';
In this example, cout is not flushed.
— end example]

31.11.3.2 Construction and destruction [syncstream.osyncstream.cons]

basic_osyncstream(streambuf_type* buf, const Allocator& allocator);
Effects: Initializes sb from buf and allocator.
Initializes the base class with basic_ostream<charT, traits>(addressof(sb)).
[Note 1: 
The member functions of the provided stream buffer can be called from emit() while a lock is held, which might result in a deadlock if used incautiously.
— end note]
Postconditions: get_wrapped() == buf is true.
basic_osyncstream(basic_osyncstream&& other) noexcept;
Effects: Move constructs the base class and sb from the corresponding subobjects of other, and calls basic_ostream<charT, traits>​::​set_rdbuf(addressof(sb)).
Postconditions: The value returned by get_wrapped() is the value returned by other.get_wrapped() prior to calling this constructor.
nullptr == other.get_wrapped() is true.

31.11.3.3 Member functions [syncstream.osyncstream.members]

void emit();
Effects: Behaves as an unformatted output function ([ostream.unformatted]).
After constructing a sentry object, calls sb.emit().
If that call returns false, calls setstate(ios_base​::​badbit).
[Example 1: 
A flush on a basic_osyncstream does not flush immediately: { osyncstream bout(cout); bout << "Hello," << '\n'; // no flush bout.emit(); // characters transferred; cout not flushed bout << "World!" << endl; // flush noted; cout not flushed bout.emit(); // characters transferred; cout flushed bout << "Greetings." << '\n'; // no flush } // characters transferred; cout not flushed
— end example]
[Example 2: 
The function emit() can be used to handle exceptions from operations on the underlying stream.
{ osyncstream bout(cout); bout << "Hello, " << "World!" << '\n'; try { bout.emit(); } catch (...) { // handle exception } } — end example]
streambuf_type* get_wrapped() const noexcept;
Returns: sb.get_wrapped().
[Example 3: 
Obtaining the wrapped stream buffer with get_wrapped() allows wrapping it again with an osyncstream.
For example, { osyncstream bout1(cout); bout1 << "Hello, "; { osyncstream(bout1.get_wrapped()) << "Goodbye, " << "Planet!" << '\n'; } bout1 << "World!" << '\n'; } produces the uninterleaved output
Goodbye, Planet!
Hello, World!
— end example]

31.12 File systems [filesystems]

31.12.1 General [fs.general]

Subclause [filesystems] describes operations on file systems and their components, such as paths, regular files, and directories.
A file system is a collection of files and their attributes.
A file is an object within a file system that holds user or system data.
Files can be written to, or read from, or both.
A file has certain attributes, including type.
File types include regular files and directories.
Other types of files, such as symbolic links, may be supported by the implementation.
A directory is a file within a file system that acts as a container of directory entries that contain information about other files, possibly including other directory files.
The parent directory of a directory is the directory that both contains a directory entry for the given directory and is represented by the dot-dot filename ([fs.path.generic]) in the given directory.
The parent directory of other types of files is a directory containing a directory entry for the file under discussion.
A link is an object that associates a filename with a file.
Several links can associate names with the same file.
A hard link is a link to an existing file.
Some file systems support multiple hard links to a file.
If the last hard link to a file is removed, the file itself is removed.
[Note 1: 
A hard link can be thought of as a shared-ownership smart pointer to a file.
— end note]
A symbolic link is a type of file with the property that when the file is encountered during pathname resolution ([fs.class.path]), a string stored by the file is used to modify the pathname resolution.
[Note 2: 
Symbolic links are often called symlinks.
A symbolic link can be thought of as a raw pointer to a file.
If the file pointed to does not exist, the symbolic link is said to be a “dangling” symbolic link.
— end note]

31.12.2 Conformance [fs.conformance]

31.12.2.1 General [fs.conformance.general]

Conformance is specified in terms of behavior.
Ideal behavior is not always implementable, so the conformance subclauses take that into account.

31.12.2.2 POSIX conformance [fs.conform.9945]

Some behavior is specified by reference to POSIX.
How such behavior is actually implemented is unspecified.
[Note 1: 
This constitutes an “as if” rule allowing implementations to call native operating system or other APIs.
— end note]
Implementations should provide such behavior as it is defined by POSIX.
Implementations shall document any behavior that differs from the behavior defined by POSIX.
Implementations that do not support exact POSIX behavior should provide behavior as close to POSIX behavior as is reasonable given the limitations of actual operating systems and file systems.
If an implementation cannot provide any reasonable behavior, the implementation shall report an error as specified in [fs.err.report].
[Note 2: 
This allows users to rely on an exception being thrown or an error code being set when an implementation cannot provide any reasonable behavior.
— end note]
Implementations are not required to provide behavior that is not supported by a particular file system.
[Example 1: 
The FAT file system used by some memory cards, camera memory, and floppy disks does not support hard links, symlinks, and many other features of more capable file systems, so implementations are not required to support those features on the FAT file system but instead are required to report an error as described above.
— end example]

31.12.2.3 Operating system dependent behavior conformance [fs.conform.os]

Behavior that is specified as being operating system dependent is dependent upon the behavior and characteristics of an operating system.
The operating system an implementation is dependent upon is implementation-defined.
It is permissible for an implementation to be dependent upon an operating system emulator rather than the actual underlying operating system.

31.12.2.4 File system race behavior [fs.race.behavior]

A file system race is the condition that occurs when multiple threads, processes, or computers interleave access and modification of the same object within a file system.
Behavior is undefined if calls to functions provided by subclause [filesystems] introduce a file system race.
If the possibility of a file system race would make it unreliable for a program to test for a precondition before calling a function described herein, Preconditions: is not specified for the function.
[Note 1: 
As a design practice, preconditions are not specified when it is unreasonable for a program to detect them prior to calling the function.
— end note]

31.12.3 Requirements [fs.req]

Throughout subclause [filesystems], char, wchar_t, char8_t, char16_t, and char32_t are collectively called encoded character types.
Functions with template parameters named EcharT shall not participate in overload resolution unless EcharT is one of the encoded character types.
Template parameters named InputIterator shall meet the Cpp17InputIterator requirements ([input.iterators]) and shall have a value type that is one of the encoded character types.
[Note 1: 
Use of an encoded character type implies an associated character set and encoding.
Since signed char and unsigned char have no implied character set and encoding, they are not included as permitted types.
— end note]
Template parameters named Allocator shall meet the Cpp17Allocator requirements ([allocator.requirements.general]).

31.12.4 Header <filesystem> synopsis [fs.filesystem.syn]

#include <compare> // see [compare.syn] namespace std::filesystem { // [fs.class.path], paths class path; // [fs.path.nonmember], path non-member functions void swap(path& lhs, path& rhs) noexcept; size_t hash_value(const path& p) noexcept; // [fs.class.filesystem.error], filesystem errors class filesystem_error; // [fs.class.directory.entry], directory entries class directory_entry; // [fs.class.directory.iterator], directory iterators class directory_iterator; // [fs.dir.itr.nonmembers], range access for directory iterators directory_iterator begin(directory_iterator iter) noexcept; directory_iterator end(directory_iterator) noexcept; // [fs.class.rec.dir.itr], recursive directory iterators class recursive_directory_iterator; // [fs.rec.dir.itr.nonmembers], range access for recursive directory iterators recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; recursive_directory_iterator end(recursive_directory_iterator) noexcept; // [fs.class.file.status], file status class file_status; struct space_info { uintmax_t capacity; uintmax_t free; uintmax_t available; friend bool operator==(const space_info&, const space_info&) = default; }; // [fs.enum], enumerations enum class file_type; enum class perms; enum class perm_options; enum class copy_options; enum class directory_options; using file_time_type = chrono::time_point<chrono::file_clock>; // [fs.op.funcs], filesystem operations path absolute(const path& p); path absolute(const path& p, error_code& ec); path canonical(const path& p); path canonical(const path& p, error_code& ec); void copy(const path& from, const path& to); void copy(const path& from, const path& to, error_code& ec); void copy(const path& from, const path& to, copy_options options); void copy(const path& from, const path& to, copy_options options, error_code& ec); bool copy_file(const path& from, const path& to); bool copy_file(const path& from, const path& to, error_code& ec); bool copy_file(const path& from, const path& to, copy_options option); bool copy_file(const path& from, const path& to, copy_options option, error_code& ec); void copy_symlink(const path& existing_symlink, const path& new_symlink); void copy_symlink(const path& existing_symlink, const path& new_symlink, error_code& ec) noexcept; bool create_directories(const path& p); bool create_directories(const path& p, error_code& ec); bool create_directory(const path& p); bool create_directory(const path& p, error_code& ec) noexcept; bool create_directory(const path& p, const path& attributes); bool create_directory(const path& p, const path& attributes, error_code& ec) noexcept; void create_directory_symlink(const path& to, const path& new_symlink); void create_directory_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept; void create_hard_link(const path& to, const path& new_hard_link); void create_hard_link(const path& to, const path& new_hard_link, error_code& ec) noexcept; void create_symlink(const path& to, const path& new_symlink); void create_symlink(const path& to, const path& new_symlink, error_code& ec) noexcept; path current_path(); path current_path(error_code& ec); void current_path(const path& p); void current_path(const path& p, error_code& ec) noexcept; bool equivalent(const path& p1, const path& p2); bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept; bool exists(file_status s) noexcept; bool exists(const path& p); bool exists(const path& p, error_code& ec) noexcept; uintmax_t file_size(const path& p); uintmax_t file_size(const path& p, error_code& ec) noexcept; uintmax_t hard_link_count(const path& p); uintmax_t hard_link_count(const path& p, error_code& ec) noexcept; bool is_block_file(file_status s) noexcept; bool is_block_file(const path& p); bool is_block_file(const path& p, error_code& ec) noexcept; bool is_character_file(file_status s) noexcept; bool is_character_file(const path& p); bool is_character_file(const path& p, error_code& ec) noexcept; bool is_directory(file_status s) noexcept; bool is_directory(const path& p); bool is_directory(const path& p, error_code& ec) noexcept; bool is_empty(const path& p); bool is_empty(const path& p, error_code& ec); bool is_fifo(file_status s) noexcept; bool is_fifo(const path& p); bool is_fifo(const path& p, error_code& ec) noexcept; bool is_other(file_status s) noexcept; bool is_other(const path& p); bool is_other(const path& p, error_code& ec) noexcept; bool is_regular_file(file_status s) noexcept; bool is_regular_file(const path& p); bool is_regular_file(const path& p, error_code& ec) noexcept; bool is_socket(file_status s) noexcept; bool is_socket(const path& p); bool is_socket(const path& p, error_code& ec) noexcept; bool is_symlink(file_status s) noexcept; bool is_symlink(const path& p); bool is_symlink(const path& p, error_code& ec) noexcept; file_time_type last_write_time(const path& p); file_time_type last_write_time(const path& p, error_code& ec) noexcept; void last_write_time(const path& p, file_time_type new_time); void last_write_time(const path& p, file_time_type new_time, error_code& ec) noexcept; void permissions(const path& p, perms prms, perm_options opts=perm_options::replace); void permissions(const path& p, perms prms, error_code& ec) noexcept; void permissions(const path& p, perms prms, perm_options opts, error_code& ec); path proximate(const path& p, error_code& ec); path proximate(const path& p, const path& base = current_path()); path proximate(const path& p, const path& base, error_code& ec); path read_symlink(const path& p); path read_symlink(const path& p, error_code& ec); path relative(const path& p, error_code& ec); path relative(const path& p, const path& base = current_path()); path relative(const path& p, const path& base, error_code& ec); bool remove(const path& p); bool remove(const path& p, error_code& ec) noexcept; uintmax_t remove_all(const path& p); uintmax_t remove_all(const path& p, error_code& ec); void rename(const path& from, const path& to); void rename(const path& from, const path& to, error_code& ec) noexcept; void resize_file(const path& p, uintmax_t size); void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept; space_info space(const path& p); space_info space(const path& p, error_code& ec) noexcept; file_status status(const path& p); file_status status(const path& p, error_code& ec) noexcept; bool status_known(file_status s) noexcept; file_status symlink_status(const path& p); file_status symlink_status(const path& p, error_code& ec) noexcept; path temp_directory_path(); path temp_directory_path(error_code& ec); path weakly_canonical(const path& p); path weakly_canonical(const path& p, error_code& ec); } namespace std { // [fs.path.fmtr], formatting support template<class charT> struct formatter<filesystem::path, charT>; // [fs.path.hash], hash support template<class T> struct hash; template<> struct hash<filesystem::path>; } namespace std::ranges { template<> inline constexpr bool enable_borrowed_range<filesystem::directory_iterator> = true; template<> inline constexpr bool enable_borrowed_range<filesystem::recursive_directory_iterator> = true; template<> inline constexpr bool enable_view<filesystem::directory_iterator> = true; template<> inline constexpr bool enable_view<filesystem::recursive_directory_iterator> = true; }
Implementations should ensure that the resolution and range of file_time_type reflect the operating system dependent resolution and range of file time values.

31.12.5 Error reporting [fs.err.report]

Filesystem library functions often provide two overloads, one that throws an exception to report file system errors, and another that sets an error_code.
[Note 1: 
This supports two common use cases:
  • Uses where file system errors are truly exceptional and indicate a serious failure.
    Throwing an exception is an appropriate response.
  • Uses where file system errors are routine and do not necessarily represent failure.
    Returning an error code is the most appropriate response.
    This allows application specific error handling, including simply ignoring the error.
— end note]
Functions not having an argument of type error_code& handle errors as follows, unless otherwise specified:
  • When a call by the implementation to an operating system or other underlying API results in an error that prevents the function from meeting its specifications, an exception of type filesystem_error shall be thrown.
    For functions with a single path argument, that argument shall be passed to the filesystem_error constructor with a single path argument.
    For functions with two path arguments, the first of these arguments shall be passed to the filesystem_error constructor as the path1 argument, and the second shall be passed as the path2 argument.
    The filesystem_error constructor's error_code argument is set as appropriate for the specific operating system dependent error.
  • Failure to allocate storage is reported by throwing an exception as described in [res.on.exception.handling].
  • Destructors throw nothing.
Functions having an argument of type error_code& handle errors as follows, unless otherwise specified:
  • If a call by the implementation to an operating system or other underlying API results in an error that prevents the function from meeting its specifications, the error_code& argument is set as appropriate for the specific operating system dependent error.
    Otherwise, clear() is called on the error_code& argument.

31.12.6 Class path [fs.class.path]

31.12.6.1 General [fs.class.path.general]

An object of class path represents a path and contains a pathname.
Such an object is concerned only with the lexical and syntactic aspects of a path.
The path does not necessarily exist in external storage, and the pathname is not necessarily valid for the current operating system or for a particular file system.
[Note 1: 
Class path is used to support the differences between the string types used by different operating systems to represent pathnames, and to perform conversions between encodings when necessary.
— end note]
A path is a sequence of elements that identify the location of a file within a filesystem.
The elements are the root-name, root-directory, and an optional sequence of filenames ([fs.path.generic]).
The maximum number of elements in the sequence is operating system dependent ([fs.conform.os]).
An absolute path is a path that unambiguously identifies the location of a file without reference to an additional starting location.
The elements of a path that determine if it is absolute are operating system dependent.
A relative path is a path that is not absolute, and as such, only unambiguously identifies the location of a file when resolved relative to an implied starting location.
The elements of a path that determine if it is relative are operating system dependent.
[Note 2: 
Pathnames “.” and “..” are relative paths.
— end note]
A pathname is a character string that represents the name of a path.
Pathnames are formatted according to the generic pathname format grammar ([fs.path.generic]) or according to an operating system dependent native pathname format accepted by the host operating system.
Pathname resolution is the operating system dependent mechanism for resolving a pathname to a particular file in a file hierarchy.
There may be multiple pathnames that resolve to the same file.
[Example 1: 
For POSIX-based operating systems, this mechanism is specified in POSIX, section 4.12, Pathname resolution.
— end example]
namespace std::filesystem { class path { public: using value_type = see below; using string_type = basic_string<value_type>; static constexpr value_type preferred_separator = see below; // [fs.enum.path.format], enumeration format enum format; // [fs.path.construct], constructors and destructor path() noexcept; path(const path& p); path(path&& p) noexcept; path(string_type&& source, format fmt = auto_format); template<class Source> path(const Source& source, format fmt = auto_format); template<class InputIterator> path(InputIterator first, InputIterator last, format fmt = auto_format); template<class Source> path(const Source& source, const locale& loc, format fmt = auto_format); template<class InputIterator> path(InputIterator first, InputIterator last, const locale& loc, format fmt = auto_format); ~path(); // [fs.path.assign], assignments path& operator=(const path& p); path& operator=(path&& p) noexcept; path& operator=(string_type&& source); path& assign(string_type&& source); template<class Source> path& operator=(const Source& source); template<class Source> path& assign(const Source& source); template<class InputIterator> path& assign(InputIterator first, InputIterator last); // [fs.path.append], appends path& operator/=(const path& p); template<class Source> path& operator/=(const Source& source); template<class Source> path& append(const Source& source); template<class InputIterator> path& append(InputIterator first, InputIterator last); // [fs.path.concat], concatenation path& operator+=(const path& x); path& operator+=(const string_type& x); path& operator+=(basic_string_view<value_type> x); path& operator+=(const value_type* x); path& operator+=(value_type x); template<class Source> path& operator+=(const Source& x); template<class EcharT> path& operator+=(EcharT x); template<class Source> path& concat(const Source& x); template<class InputIterator> path& concat(InputIterator first, InputIterator last); // [fs.path.modifiers], modifiers void clear() noexcept; path& make_preferred(); path& remove_filename(); path& replace_filename(const path& replacement); path& replace_extension(const path& replacement = path()); void swap(path& rhs) noexcept; // [fs.path.nonmember], non-member operators friend bool operator==(const path& lhs, const path& rhs) noexcept; friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; friend path operator/(const path& lhs, const path& rhs); // [fs.path.native.obs], native format observers const string_type& native() const noexcept; const value_type* c_str() const noexcept; operator string_type() const; template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const; std::string string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; std::u32string u32string() const; // [fs.path.generic.obs], generic format observers template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const; std::string generic_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const; // [fs.path.compare], compare int compare(const path& p) const noexcept; int compare(const string_type& s) const; int compare(basic_string_view<value_type> s) const; int compare(const value_type* s) const; // [fs.path.decompose], decomposition path root_name() const; path root_directory() const; path root_path() const; path relative_path() const; path parent_path() const; path filename() const; path stem() const; path extension() const; // [fs.path.query], query bool empty() const noexcept; bool has_root_name() const; bool has_root_directory() const; bool has_root_path() const; bool has_relative_path() const; bool has_parent_path() const; bool has_filename() const; bool has_stem() const; bool has_extension() const; bool is_absolute() const; bool is_relative() const; // [fs.path.gen], generation path lexically_normal() const; path lexically_relative(const path& base) const; path lexically_proximate(const path& base) const; // [fs.path.itr], iterators class iterator; using const_iterator = iterator; iterator begin() const; iterator end() const; // [fs.path.io], path inserter and extractor template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const path& p); template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, path& p); }; }
value_type is a typedef for the operating system dependent encoded character type used to represent pathnames.
The value of the preferred_separator member is the operating system dependent preferred-separator character ([fs.path.generic]).
[Example 2: 
For POSIX-based operating systems, value_type is char and preferred_separator is the slash character ('/').
For Windows-based operating systems, value_type is wchar_t and preferred_separator is the backslash character (L'\\').
— end example]

31.12.6.2 Generic pathname format [fs.path.generic]

root-name:
operating system dependent sequences of characters
implementation-defined sequences of characters
filename:
non-empty sequence of characters other than directory-separator characters
preferred-separator:
operating system dependent directory separator character
A filename is the name of a file.
The dot and dot-dot filenames, consisting solely of one and two period characters respectively, have special meaning.
The following characteristics of filenames are operating system dependent:
  • The permitted characters.
    [Example 1: 
    Some operating systems prohibit the ASCII control characters (0x00 – 0x1F) in filenames.
    — end example]
    [Note 1: 
    Wider portability can be achieved by limiting filename characters to the POSIX Portable Filename Character Set:
    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    0 1 2 3 4 5 6 7 8 9 . _ -
    — end note]
  • The maximum permitted length.
  • Filenames that are not permitted.
  • Filenames that have special meaning.
  • Case awareness and sensitivity during path resolution.
  • Special rules that may apply to file types other than regular files, such as directories.
Except in a root-name, multiple successive directory-separator characters are considered to be the same as one directory-separator character.
The dot filename is treated as a reference to the current directory.
The dot-dot filename is treated as a reference to the parent directory.
What the dot-dot filename refers to relative to root-directory is implementation-defined.
Specific filenames may have special meanings for a particular operating system.
A root-name identifies the starting location for pathname resolution ([fs.class.path]).
If there are no operating system dependent root-names, at least one implementation-defined root-name is required.
[Note 2: 
Many operating systems define a name beginning with two directory-separator characters as a root-name that identifies network or other resource locations.
Some operating systems define a single letter followed by a colon as a drive specifier — a root-name identifying a specific device such as a disk drive.
— end note]
If a root-name is otherwise ambiguous, the possibility with the longest sequence of characters is chosen.
[Note 3: 
On a POSIX-like operating system, it is impossible to have a root-name and a relative-path without an intervening root-directory element.
— end note]
Normalization of a generic format pathname means:
1.
If the path is empty, stop.
2.
Replace each slash character in the root-name with a preferred-separator.
3.
[Note 4: 
The generic pathname grammar defines directory-separator as one or more slashes and preferred-separators.
— end note]
4.
Remove each dot filename and any immediately following directory-separator.
5.
As long as any appear, remove a non-dot-dot filename immediately followed by a directory-separator and a dot-dot filename, along with any immediately following directory-separator.
6.
If there is a root-directory, remove all dot-dot filenames and any directory-separators immediately following them.
[Note 5: 
These dot-dot filenames attempt to refer to nonexistent parent directories.
— end note]
7.
If the last filename is dot-dot, remove any trailing directory-separator.
8.
If the path is empty, add a dot.
The result of normalization is a path in normal form, which is said to be normalized.

31.12.6.3 Conversions [fs.path.cvt]

31.12.6.3.1 Argument format conversions [fs.path.fmt.cvt]

[Note 1: 
The format conversions described in this subclause are not applied on POSIX-based operating systems because on these systems:
  • The generic format is acceptable as a native path.
  • There is no need to distinguish between native format and generic format in function arguments.
  • Paths for regular files and paths for directories share the same syntax.
— end note]
Several functions are defined to accept detected-format arguments, which are character sequences.
A detected-format argument represents a path using either a pathname in the generic format ([fs.path.generic]) or a pathname in the native format ([fs.class.path]).
Such an argument is taken to be in the generic format if and only if it matches the generic format and is not acceptable to the operating system as a native path.
[Note 2: 
Some operating systems have no unambiguous way to distinguish between native format and generic format arguments.
This is by design as it simplifies use for operating systems that do not require disambiguation.
It is possible that an implementation for an operating system where disambiguation is needed distinguishes between the formats.
— end note]
Pathnames are converted as needed between the generic and native formats in an operating-system-dependent manner.
Let G(n) and N(g) in a mathematical sense be the implementation's functions that convert native-to-generic and generic-to-native formats respectively.
If g=G(n) for some n, then G(N(g))=g; if n=N(g) for some g, then N(G(n))=n.
[Note 3: 
Neither G nor N need be invertible.
— end note]
If the native format requires paths for regular files to be formatted differently from paths for directories, the path shall be treated as a directory path if its last element is a directory-separator, otherwise it shall be treated as a path to a regular file.
[Note 4: 
A path stores a native format pathname ([fs.path.native.obs]) and acts as if it also stores a generic format pathname, related as given below.
The implementation can generate the generic format pathname based on the native format pathname (and possibly other information) when requested.
— end note]
When a path is constructed from or is assigned a single representation separate from any path, the other representation is selected by the appropriate conversion function (G or N).
When the (new) value p of one representation of a path is derived from the representation of that or another path, a value q is chosen for the other representation.
The value q converts to p (by G or N as appropriate) if any such value does so; q is otherwise unspecified.
[Note 5: 
If q is the result of converting any path at all, it is the result of converting p.
— end note]

31.12.6.3.2 Type and encoding conversions [fs.path.type.cvt]

The native encoding of an ordinary character string is the operating system dependent current encoding for pathnames ([fs.class.path]).
The native encoding for wide character strings is the implementation-defined execution wide-character set encoding ([character.seq]).
For member function arguments that take character sequences representing paths and for member functions returning strings, value type and encoding conversion is performed if the value type of the argument or return value differs from path​::​value_type.
For the argument or return value, the method of conversion and the encoding to be converted to is determined by its value type:
  • char: The encoding is the native ordinary encoding.
    The method of conversion, if any, is operating system dependent.
    [Note 1: 
    For POSIX-based operating systems path​::​value_type is char so no conversion from char value type arguments or to char value type return values is performed.
    For Windows-based operating systems, the native ordinary encoding is determined by calling a Windows API function.
    — end note]
    [Note 2: 
    This results in behavior identical to other C and C++ standard library functions that perform file operations using ordinary character strings to identify paths.
    Changing this behavior would be surprising and error-prone.
    — end note]
  • wchar_t: The encoding is the native wide encoding.
    The method of conversion is unspecified.
    [Note 3: 
    For Windows-based operating systems path​::​value_type is wchar_t so no conversion from wchar_t value type arguments or to wchar_t value type return values is performed.
    — end note]
  • char8_t: The encoding is UTF-8.
    The method of conversion is unspecified.
  • char16_t: The encoding is UTF-16.
    The method of conversion is unspecified.
  • char32_t: The encoding is UTF-32.
    The method of conversion is unspecified.
If the encoding being converted to has no representation for source characters, the resulting converted characters, if any, are unspecified.
Implementations should not modify member function arguments if already of type path​::​value_type.

31.12.6.4 Requirements [fs.path.req]

In addition to the requirements ([fs.req]), function template parameters named Source shall be one of:
  • basic_string<EcharT, traits, Allocator>.
    A function argument const Source& source shall have an effective range [source.begin(), source.end()).
  • basic_string_view<EcharT, traits>.
    A function argument const Source& source shall have an effective range [source.begin(), source.end()).
  • A type meeting the Cpp17InputIterator requirements that iterates over a NTCTS.
    The value type shall be an encoded character type.
    A function argument const Source& source shall have an effective range [source, end) where end is the first iterator value with an element value equal to iterator_traits<Source>​::​value_type().
  • A character array that after array-to-pointer decay results in a pointer to the start of a NTCTS.
    The value type shall be an encoded character type.
    A function argument const Source& source shall have an effective range [source, end) where end is the first iterator value with an element value equal to iterator_traits<decay_t<Source>>​::​value_type().
Functions taking template parameters named Source shall not participate in overload resolution unless Source denotes a type other than path, and either
  • Source is a specialization of basic_string or basic_string_view, or
  • the qualified-id iterator_traits<decay_t<Source>>​::​value_type is valid and denotes a possibly const encoded character type ([temp.deduct]).
[Note 1: 
See path conversions for how the value types above and their encodings convert to path​::​value_type and its encoding.
— end note]
Arguments of type Source shall not be null pointers.

31.12.6.5 Members [fs.path.member]

31.12.6.5.1 Constructors [fs.path.construct]

path() noexcept;
Postconditions: empty() is true.
path(const path& p); path(path&& p) noexcept;
Effects: Constructs an object of class path having the same pathname in the native and generic formats, respectively, as the original value of p.
In the second form, p is left in a valid but unspecified state.
path(string_type&& source, format fmt = auto_format);
Effects: Constructs an object of class path for which the pathname in the detected-format of source has the original value of source ([fs.path.fmt.cvt]), converting format if required ([fs.path.fmt.cvt]).
source is left in a valid but unspecified state.
template<class Source> path(const Source& source, format fmt = auto_format); template<class InputIterator> path(InputIterator first, InputIterator last, format fmt = auto_format);
Effects: Let s be the effective range of source ([fs.path.req]) or the range [first, last), with the encoding converted if required ([fs.path.cvt]).
Finds the detected-format of s ([fs.path.fmt.cvt]) and constructs an object of class path for which the pathname in that format is s.
template<class Source> path(const Source& source, const locale& loc, format fmt = auto_format); template<class InputIterator> path(InputIterator first, InputIterator last, const locale& loc, format fmt = auto_format);
Mandates: The value type of Source and InputIterator is char.
Effects: Let s be the effective range of source or the range [first, last), after converting the encoding as follows:
  • If value_type is wchar_t, converts to the native wide encoding ([fs.path.type.cvt]) using the codecvt<wchar_t, char, mbstate_t> facet of loc.
  • Otherwise a conversion is performed using the codecvt<wchar_t, char, mbstate_t> facet of loc, and then a second conversion to the current ordinary encoding.
Finds the detected-format of s ([fs.path.fmt.cvt]) and constructs an object of class path for which the pathname in that format is s.
[Example 1: 
A string is to be read from a database that is encoded in ISO/IEC 8859-1, and used to create a directory: namespace fs = std::filesystem; std::string latin1_string = read_latin1_data(); codecvt_8859_1<wchar_t> latin1_facet; std::locale latin1_locale(std::locale(), latin1_facet); fs::create_directory(fs::path(latin1_string, latin1_locale));
For POSIX-based operating systems, the path is constructed by first using latin1_facet to convert ISO/IEC 8859-1 encoded latin1_string to a wide character string in the native wide encoding ([fs.path.type.cvt]).
The resulting wide string is then converted to an ordinary character pathname string in the current native ordinary encoding.
If the native wide encoding is UTF-16 or UTF-32, and the current native ordinary encoding is UTF-8, all of the characters in the ISO/IEC 8859-1 character set will be converted to their Unicode representation, but for other native ordinary encodings some characters may have no representation.
For Windows-based operating systems, the path is constructed by using latin1_facet to convert ISO/IEC 8859-1 encoded latin1_string to a UTF-16 encoded wide character pathname string.
All of the characters in the ISO/IEC 8859-1 character set will be converted to their Unicode representation.
— end example]

31.12.6.5.2 Assignments [fs.path.assign]

path& operator=(const path& p);
Effects: If *this and p are the same object, has no effect.
Otherwise, sets both respective pathnames of *this to the respective pathnames of p.
Returns: *this.
path& operator=(path&& p) noexcept;
Effects: If *this and p are the same object, has no effect.
Otherwise, sets both respective pathnames of *this to the respective pathnames of p.
p is left in a valid but unspecified state.
[Note 1: 
A valid implementation is swap(p).
— end note]
Returns: *this.
path& operator=(string_type&& source); path& assign(string_type&& source);
Effects: Sets the pathname in the detected-format of source to the original value of source.
source is left in a valid but unspecified state.
Returns: *this.
template<class Source> path& operator=(const Source& source); template<class Source> path& assign(const Source& source); template<class InputIterator> path& assign(InputIterator first, InputIterator last);
Effects: Let s be the effective range of source ([fs.path.req]) or the range [first, last), with the encoding converted if required ([fs.path.cvt]).
Finds the detected-format of s ([fs.path.fmt.cvt]) and sets the pathname in that format to s.
Returns: *this.

31.12.6.5.3 Appends [fs.path.append]

The append operations use operator/= to denote their semantic effect of appending preferred-separator when needed.
path& operator/=(const path& p);
Effects: If p.is_absolute() || (p.has_root_name() && p.root_name() != root_name()), then operator=(p).
Otherwise, modifies *this as if by these steps:
  • If p.has_root_directory(), then removes any root directory and relative path from the generic format pathname.
    Otherwise, if !has_root_directory() && is_absolute() is true or if has_filename() is true, then appends path​::​preferred_separator to the generic format pathname.
  • Then appends the native format pathname of p, omitting any root-name from its generic format pathname, to the native format pathname.
[Example 1: 
Even if //host is interpreted as a root-name, both of the paths path("//host")/"foo" and path("//host/")/"foo" equal "//host/foo" (although the former might use backslash as the preferred separator).
Expression examples: // On POSIX, path("foo") /= path(""); // yields path("foo/") path("foo") /= path("/bar"); // yields path("/bar") // On Windows, path("foo") /= path(""); // yields path("foo\\") path("foo") /= path("/bar"); // yields path("/bar") path("foo") /= path("c:/bar"); // yields path("c:/bar") path("foo") /= path("c:"); // yields path("c:") path("c:") /= path(""); // yields path("c:") path("c:foo") /= path("/bar"); // yields path("c:/bar") path("c:foo") /= path("c:bar"); // yields path("c:foo\\bar")
— end example]
Returns: *this.
template<class Source> path& operator/=(const Source& source); template<class Source> path& append(const Source& source);
Effects: Equivalent to: return operator/=(path(source));
template<class InputIterator> path& append(InputIterator first, InputIterator last);
Effects: Equivalent to: return operator/=(path(first, last));

31.12.6.5.4 Concatenation [fs.path.concat]

path& operator+=(const path& x); path& operator+=(const string_type& x); path& operator+=(basic_string_view<value_type> x); path& operator+=(const value_type* x); template<class Source> path& operator+=(const Source& x); template<class Source> path& concat(const Source& x);
Effects: Appends path(x).native() to the pathname in the native format.
[Note 1: 
This directly manipulates the value of native(), which is not necessarily portable between operating systems.
— end note]
Returns: *this.
path& operator+=(value_type x); template<class EcharT> path& operator+=(EcharT x);
Effects: Equivalent to: return *this += basic_string_view(&x, 1);
template<class InputIterator> path& concat(InputIterator first, InputIterator last);
Effects: Equivalent to: return *this += path(first, last);

31.12.6.5.5 Modifiers [fs.path.modifiers]

void clear() noexcept;
Postconditions: empty() is true.
path& make_preferred();
Effects: Each directory-separator of the pathname in the generic format is converted to preferred-separator.
Returns: *this.
[Example 1: path p("foo/bar"); std::cout << p << '\n'; p.make_preferred(); std::cout << p << '\n';
On an operating system where preferred-separator is a slash, the output is: "foo/bar" "foo/bar"
On an operating system where preferred-separator is a backslash, the output is: "foo/bar" "foo\bar"
— end example]
path& remove_filename();
Effects: Remove the generic format pathname of filename() from the generic format pathname.
Postconditions: !has_filename().
Returns: *this.
[Example 2: path("foo/bar").remove_filename(); // yields "foo/" path("foo/").remove_filename(); // yields "foo/" path("/foo").remove_filename(); // yields "/" path("/").remove_filename(); // yields "/" — end example]
path& replace_filename(const path& replacement);
Effects: Equivalent to: remove_filename(); operator/=(replacement);
Returns: *this.
[Example 3: path("/foo").replace_filename("bar"); // yields "/bar" on POSIX path("/").replace_filename("bar"); // yields "/bar" on POSIX — end example]
path& replace_extension(const path& replacement = path());
Effects:
  • Any existing extension() ([fs.path.decompose]) is removed from the pathname in the generic format, then
  • If replacement is not empty and does not begin with a dot character, a dot character is appended to the pathname in the generic format, then
  • operator+=(replacement);.
Returns: *this.
void swap(path& rhs) noexcept;
Effects: Swaps the contents (in all formats) of the two paths.
Complexity: Constant time.

31.12.6.5.6 Native format observers [fs.path.native.obs]

The string returned by all native format observers is in the native pathname format ([fs.class.path]).
const string_type& native() const noexcept;
Returns: The pathname in the native format.
const value_type* c_str() const noexcept;
Effects: Equivalent to: return native().c_str();
operator string_type() const;
Returns: native().
template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
Returns: native().
Remarks: All memory allocation, including for the return value, shall be performed by a.
Conversion, if any, is specified by [fs.path.cvt].
std::string string() const; std::wstring wstring() const; std::u8string u8string() const; std::u16string u16string() const; std::u32string u32string() const;
Returns: native().
Remarks: Conversion, if any, is performed as specified by [fs.path.cvt].

31.12.6.5.7 Generic format observers [fs.path.generic.obs]

Generic format observer functions return strings formatted according to the generic pathname format.
A single slash ('/') character is used as the directory-separator.
[Example 1: 
On an operating system that uses backslash as its preferred-separator, path("foo\\bar").generic_string() returns "foo/bar".
— end example]
template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>> basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
Returns: The pathname in the generic format.
Remarks: All memory allocation, including for the return value, shall be performed by a.
Conversion, if any, is specified by [fs.path.cvt].
std::string generic_string() const; std::wstring generic_wstring() const; std::u8string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const;
Returns: The pathname in the generic format.
Remarks: Conversion, if any, is specified by [fs.path.cvt].

31.12.6.5.8 Compare [fs.path.compare]

int compare(const path& p) const noexcept;
Returns:
  • Let rootNameComparison be the result of this->root_name().native().compare(p.root_name().native()).
    If rootNameComparison is not 0, rootNameComparison.
  • Otherwise, if !this->has_root_directory() and p.has_root_directory(), a value less than 0.
  • Otherwise, if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.
  • Otherwise, if native() for the elements of this->relative_path() are lexicographically less than native() for the elements of p.relative_path(), a value less than 0.
  • Otherwise, if native() for the elements of this->relative_path() are lexicographically greater than native() for the elements of p.relative_path(), a value greater than 0.
  • Otherwise, 0.
int compare(const string_type& s) const; int compare(basic_string_view<value_type> s) const; int compare(const value_type* s) const;
Effects: Equivalent to: return compare(path(s));

31.12.6.5.9 Decomposition [fs.path.decompose]

path root_name() const;
Returns: root-name, if the pathname in the generic format includes root-name, otherwise path().
path root_directory() const;
Returns: root-directory, if the pathname in the generic format includes root-directory, otherwise path().
path root_path() const;
Returns: root_name() / root_directory().
path relative_path() const;
Returns: A path composed from the pathname in the generic format, if empty() is false, beginning with the first filename after root_path().
Otherwise, path().
path parent_path() const;
Returns: *this if has_relative_path() is false, otherwise a path whose generic format pathname is the longest prefix of the generic format pathname of *this that produces one fewer element in its iteration.
path filename() const;
Returns: relative_path().empty() ? path() : *--end().
[Example 1: path("/foo/bar.txt").filename(); // yields "bar.txt" path("/foo/bar").filename(); // yields "bar" path("/foo/bar/").filename(); // yields "" path("/").filename(); // yields "" path("//host").filename(); // yields "" path(".").filename(); // yields "." path("..").filename(); // yields ".." — end example]
path stem() const;
Returns: Let f be the generic format pathname of filename().
Returns a path whose pathname in the generic format is
  • f, if it contains no periods other than a leading period or consists solely of one or two periods;
  • otherwise, the prefix of f ending before its last period.
[Example 2: std::cout << path("/foo/bar.txt").stem(); // outputs "bar" path p = "foo.bar.baz.tar"; for (; !p.extension().empty(); p = p.stem()) std::cout << p.extension() << '\n'; // outputs: .tar // .baz // .bar — end example]
path extension() const;
Returns: A path whose pathname in the generic format is the suffix of filename() not included in stem().
[Example 3: path("/foo/bar.txt").extension(); // yields ".txt" and stem() is "bar" path("/foo/bar").extension(); // yields "" and stem() is "bar" path("/foo/.profile").extension(); // yields "" and stem() is ".profile" path(".bar").extension(); // yields "" and stem() is ".bar" path("..bar").extension(); // yields ".bar" and stem() is "." — end example]
[Note 1: 
The period is included in the return value so that it is possible to distinguish between no extension and an empty extension.
— end note]
[Note 2: 
On non-POSIX operating systems, for a path p, it is possible that p.stem() + p.extension() == p.filename() is false, even though the generic format pathnames are the same.
— end note]

31.12.6.5.10 Query [fs.path.query]

bool empty() const noexcept;
Returns: true if the pathname in the generic format is empty, otherwise false.
bool has_root_path() const;
Returns: !root_path().empty().
bool has_root_name() const;
Returns: !root_name().empty().
bool has_root_directory() const;
Returns: !root_directory().empty().
bool has_relative_path() const;
Returns: !relative_path().empty().
bool has_parent_path() const;
Returns: !parent_path().empty().
bool has_filename() const;
Returns: !filename().empty().
bool has_stem() const;
Returns: !stem().empty().
bool has_extension() const;
Returns: !extension().empty().
bool is_absolute() const;
Returns: true if the pathname in the native format contains an absolute path ([fs.class.path]), otherwise false.
[Example 1: 
path("/").is_absolute() is true for POSIX-based operating systems, and false for Windows-based operating systems.
— end example]
bool is_relative() const;
Returns: !is_absolute().

31.12.6.5.11 Generation [fs.path.gen]

path lexically_normal() const;
Returns: A path whose pathname in the generic format is the normal form ([fs.path.generic]) of the pathname in the generic format of *this.
[Example 1: assert(path("foo/./bar/..").lexically_normal() == "foo/"); assert(path("foo/.///bar/../").lexically_normal() == "foo/");
The above assertions will succeed.
On Windows, the returned path's directory-separator characters will be backslashes rather than slashes, but that does not affect path equality.
— end example]
path lexically_relative(const path& base) const;
Effects: If:
  • root_name() != base.root_name() is true, or
  • is_absolute() != base.is_absolute() is true, or
  • !has_root_directory() && base.has_root_directory() is true, or
  • any filename in relative_path() or base.relative_path() can be interpreted as a root-name,
returns path().
[Note 1: 
On a POSIX implementation, no filename in a relative-path is acceptable as a root-name.
— end note]
Determines the first mismatched element of *this and base as if by: auto [a, b] = mismatch(begin(), end(), base.begin(), base.end());
Then,
  • if a == end() and b == base.end(), returns path("."); otherwise
  • let n be the number of filename elements in [b, base.end()) that are not dot or dot-dot or empty, minus the number that are dot-dot.
    If n<0, returns path(); otherwise
  • if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
  • returns an object of class path that is default-constructed, followed by
    • application of operator/=(path("..")) n times, and then
    • application of operator/= for each element in [a, end()).
Returns: *this made relative to base.
Does not resolve ([fs.class.path]) symlinks.
Does not first normalize ([fs.path.generic]) *this or base.
[Example 2: assert(path("/a/d").lexically_relative("/a/b/c") == "../../d"); assert(path("/a/b/c").lexically_relative("/a/d") == "../b/c"); assert(path("a/b/c").lexically_relative("a") == "b/c"); assert(path("a/b/c").lexically_relative("a/b/c/x/y") == "../.."); assert(path("a/b/c").lexically_relative("a/b/c") == "."); assert(path("a/b").lexically_relative("c/d") == "../../a/b");
The above assertions will succeed.
On Windows, the returned path's directory-separator characters will be backslashes rather than slashes, but that does not affect path equality.
— end example]
[Note 2: 
If symlink following semantics are desired, use the operational function relative().
— end note]
[Note 3: 
If normalization ([fs.path.generic]) is needed to ensure consistent matching of elements, apply lexically_normal() to *this, base, or both.
— end note]
path lexically_proximate(const path& base) const;
Returns: If the value of lexically_relative(base) is not an empty path, return it.
Otherwise return *this.
[Note 4: 
If symlink following semantics are desired, use the operational function proximate().
— end note]
[Note 5: 
If normalization ([fs.path.generic]) is needed to ensure consistent matching of elements, apply lexically_normal() to *this, base, or both.
— end note]

31.12.6.6 Iterators [fs.path.itr]

Path iterators iterate over the elements of the pathname in the generic format.
A path​::​iterator is a constant iterator meeting all the requirements of a bidirectional iterator except that, for dereferenceable iterators a and b of type path​::​iterator with a == b, there is no requirement that *a and *b are bound to the same object.
Its value_type is path.
Calling any non-const member function of a path object invalidates all iterators referring to elements of that object.
For the elements of the pathname in the generic format, the forward traversal order is as follows:
The backward traversal order is the reverse of forward traversal.
iterator begin() const;
Returns: An iterator for the first present element in the traversal list above.
If no elements are present, the end iterator.
iterator end() const;
Returns: The end iterator.

31.12.6.7 Inserter and extractor [fs.path.io]

template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const path& p);
Effects: Equivalent to os << quoted(p.string<charT, traits>()).
[Note 1: 
The quoted function is described in [quoted.manip].
— end note]
Returns: os.
template<class charT, class traits> friend basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, path& p);
Effects: Equivalent to: basic_string<charT, traits> tmp; is >> quoted(tmp); p = tmp;
Returns: is.

31.12.6.8 Non-member functions [fs.path.nonmember]

void swap(path& lhs, path& rhs) noexcept;
Effects: Equivalent to lhs.swap(rhs).
size_t hash_value(const path& p) noexcept;
Returns: A hash value for the path p.
If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2).
friend bool operator==(const path& lhs, const path& rhs) noexcept;
Returns: lhs.compare(rhs) == 0.
[Note 1: 
Path equality and path equivalence have different semantics.
  • Equality is determined by the path non-member operator==, which considers the two paths' lexical representations only.
    [Example 1: 
    path("foo") == "bar" is never true.
    — end example]
  • Equivalence is determined by the equivalent() non-member function, which determines if two paths resolve ([fs.class.path]) to the same file system entity.
    [Example 2: 
    equivalent("foo", "bar") will be true when both paths resolve to the same file.
    — end example]
— end note]
friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
Returns: lhs.compare(rhs) <=> 0.
friend path operator/(const path& lhs, const path& rhs);
Effects: Equivalent to: return path(lhs) /= rhs;

31.12.6.9 Formatting support [fs.path.fmtr]

31.12.6.9.1 Formatting support overview [fs.path.fmtr.general]

namespace std { template<class charT> struct formatter<filesystem::path, charT> { constexpr void set_debug_format(); constexpr typename basic_format_parse_context<charT>::iterator parse(basic_format_parse_context<charT>& ctx); template<class FormatContext> typename FormatContext::iterator format(const filesystem::path& path, FormatContext& ctx) const; }; }

31.12.6.9.2 Formatting support functions [fs.path.fmtr.funcs]

Formatting of paths uses formatting specifiers of the form
path-format-spec:
fill-and-align width ? g
where the productions fill-and-align and width are described in [format.string].
If the ? option is used then the path is formatted as an escaped string ([format.string.escaped]).
constexpr void set_debug_format();
Effects: Modifies the state of the formatter to be as if the path-format-spec parsed by the last call to parse contained the ? option.
constexpr typename basic_format_parse_context<charT>::iterator parse(basic_format_parse_context<charT>& ctx);
Effects: Parses the format specifier as a path-format-spec and stores the parsed specifiers in *this.
Returns: An iterator past the end of the path-format-spec.
template<class FormatContext> typename FormatContext::iterator format(const filesystem::path& p, FormatContext& ctx) const;
Effects: Let s be p.generic_string<filesystem​::​path​::​value_type>() if the g option is used, otherwise p.native().
Writes s into ctx.out(), adjusted according to the path-format-spec.
If charT is char, path​::​value_type is wchar_t, and the literal encoding is UTF-8, then the escaped path is transcoded from the native encoding for wide character strings to UTF-8 with maximal subparts of ill-formed subsequences substituted with U+fffd replacement character per the Unicode Standard, Chapter 3.9 U+fffd Substitution in Conversion.
If charT and path​::​value_type are the same then no transcoding is performed.
Otherwise, transcoding is implementation-defined.
Returns: An iterator past the end of the output range.

31.12.6.10 Hash support [fs.path.hash]

template<> struct hash<filesystem::path>;
For an object p of type filesystem​::​path, hash<filesystem​::​path>()(p) evaluates to the same result as filesystem​::​hash_value(p).

31.12.7 Class filesystem_error [fs.class.filesystem.error]

31.12.7.1 General [fs.class.filesystem.error.general]

namespace std::filesystem { class filesystem_error : public system_error { public: filesystem_error(const string& what_arg, error_code ec); filesystem_error(const string& what_arg, const path& p1, error_code ec); filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec); const path& path1() const noexcept; const path& path2() const noexcept; const char* what() const noexcept override; }; }
The class filesystem_error defines the type of objects thrown as exceptions to report file system errors from functions described in subclause [filesystems].

31.12.7.2 Members [fs.filesystem.error.members]

Constructors are provided that store zero, one, or two paths associated with an error.
filesystem_error(const string& what_arg, error_code ec);
Postconditions:
  • code() == ec is true,
  • path1().empty() is true,
  • path2().empty() is true, and
  • string_view(what()).find(what_arg.c_str()) != string_view​::​npos is true.
filesystem_error(const string& what_arg, const path& p1, error_code ec);
Postconditions:
  • code() == ec is true,
  • path1() returns a reference to the stored copy of p1,
  • path2().empty() is true, and
  • string_view(what()).find(what_arg.c_str()) != string_view​::​npos is true.
filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
Postconditions:
  • code() == ec,
  • path1() returns a reference to the stored copy of p1,
  • path2() returns a reference to the stored copy of p2, and
  • string_view(what()).find(what_arg.c_str()) != string_view​::​npos.
const path& path1() const noexcept;
Returns: A reference to the copy of p1 stored by the constructor, or, if none, an empty path.
const path& path2() const noexcept;
Returns: A reference to the copy of p2 stored by the constructor, or, if none, an empty path.
const char* what() const noexcept override;
Returns: An ntbs that incorporates the what_arg argument supplied to the constructor.
The exact format is unspecified.
Implementations should include the system_error​::​what() string and the pathnames of path1 and path2 in the native format in the returned string.

31.12.8 Enumerations [fs.enum]

31.12.8.1 Enum path​::​format [fs.enum.path.format]

This enum specifies constants used to identify the format of the character sequence, with the meanings listed in Table 143.
Table 143 — Enum path​::​format[tab:fs.enum.path.format]
Name
Meaning
native_format
The native pathname format.
generic_format
The generic pathname format.
auto_format
The interpretation of the format of the character sequence is implementation-defined.
The implementation may inspect the content of the character sequence to determine the format.
Recommended practice: For POSIX-based systems, native and generic formats are equivalent and the character sequence should always be interpreted in the same way.

31.12.8.2 Enum class file_type [fs.enum.file.type]

This enum class specifies constants used to identify file types, with the meanings listed in Table 144.
The values of the constants are distinct.
Table 144 — Enum class file_type[tab:fs.enum.file.type]
Constant
Meaning
The type of the file has not been determined or an error occurred while trying to determine the type.
Pseudo-type indicating the file was not found.
[Note 1: 
The file not being found is not considered an error while determining the type of a file.
— end note]
Regular file
Directory file
Symbolic link file
Block special file
Character special file
FIFO or pipe file
Socket file
implementation-defined
Implementations that support file systems having file types in addition to the above file_type types shall supply implementation-defined file_type constants to separately identify each of those additional file types
The file exists but the type cannot be determined

31.12.8.3 Enum class copy_options [fs.enum.copy.opts]

The enum class type copy_options is a bitmask type ([bitmask.types]) that specifies bitmask constants used to control the semantics of copy operations.
The constants are specified in option groups with the meanings listed in Table 145.
The constant none represents the empty bitmask, and is shown in each option group for purposes of exposition; implementations shall provide only a single definition.
Every other constant in the table represents a distinct bitmask element.
Table 145 — Enum class copy_options[tab:fs.enum.copy.opts]
Option group controlling copy_file function effects for existing target files
Constant
Meaning
(Default) Error; file already exists.
Do not overwrite existing file, do not report an error.
Overwrite the existing file.
Overwrite the existing file if it is older than the replacement file.
Option group controlling copy function effects for subdirectories
Constant
Meaning
(Default) Do not copy subdirectories.
Recursively copy subdirectories and their contents.
Option group controlling copy function effects for symbolic links
Constant
Meaning
(Default) Follow symbolic links.
Copy symbolic links as symbolic links rather than copying the files that they point to.
Ignore symbolic links.
Option group controlling copy function effects for choosing the form of copying
Constant
Meaning
(Default) Copy content.
Copy directory structure only, do not copy non-directory files.
Make symbolic links instead of copies of files.
The source path shall be an absolute path unless the destination path is in the current directory.
Make hard links instead of copies of files.

31.12.8.4 Enum class perms [fs.enum.perms]

The enum class type perms is a bitmask type ([bitmask.types]) that specifies bitmask constants used to identify file permissions, with the meanings listed in Table 146.
Table 146 — Enum class perms[tab:fs.enum.perms]
Name
Value
POSIX
Definition or notes
(octal)
macro
0
There are no permissions set for the file.
0400
S_IRUSR
Read permission, owner
0200
S_IWUSR
Write permission, owner
0100
S_IXUSR
Execute/search permission, owner
0700
S_IRWXU
Read, write, execute/search by owner;
owner_read | owner_write | owner_exec
040
S_IRGRP
Read permission, group
020
S_IWGRP
Write permission, group
010
S_IXGRP
Execute/search permission, group
070
S_IRWXG
Read, write, execute/search by group;
group_read | group_write | group_exec
04
S_IROTH
Read permission, others
02
S_IWOTH
Write permission, others
01
S_IXOTH
Execute/search permission, others
07
S_IRWXO
Read, write, execute/search by others;
others_read | others_write | others_exec
0777
owner_all | group_all | others_all
04000
S_ISUID
Set-user-ID on execution
02000
S_ISGID
Set-group-ID on execution
01000
S_ISVTX
Operating system dependent.
07777
all | set_uid | set_gid | sticky_bit
0xFFFF
The permissions are not known, such as when a file_status object is created without specifying the permissions

31.12.8.5 Enum class perm_options [fs.enum.perm.opts]

The enum class type perm_options is a bitmask type ([bitmask.types]) that specifies bitmask constants used to control the semantics of permissions operations, with the meanings listed in Table 147.
The bitmask constants are bitmask elements.
In Table 147 perm denotes a value of type perms passed to permissions.
Table 147 — Enum class perm_options[tab:fs.enum.perm.opts]
Name
Meaning
permissions shall replace the file's permission bits with perm
permissions shall replace the file's permission bits with the bitwise or of perm and the file's current permission bits.
permissions shall replace the file's permission bits with the bitwise and of the complement of perm and the file's current permission bits.
permissions shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to.

31.12.8.6 Enum class directory_options [fs.enum.dir.opts]

The enum class type directory_options is a bitmask type ([bitmask.types]) that specifies bitmask constants used to identify directory traversal options, with the meanings listed in Table 148.
The constant none represents the empty bitmask; every other constant in the table represents a distinct bitmask element.
Table 148 — Enum class directory_options[tab:fs.enum.dir.opts]
Name
Meaning
(Default) Skip directory symlinks, permission denied is an error.
Follow rather than skip directory symlinks.
Skip directories that would otherwise result in permission denied.

31.12.9 Class file_status [fs.class.file.status]

31.12.9.1 General [fs.class.file.status.general]

namespace std::filesystem { class file_status { public: // [fs.file.status.cons], constructors and destructor file_status() noexcept : file_status(file_type::none) {} explicit file_status(file_type ft, perms prms = perms::unknown) noexcept; file_status(const file_status&) noexcept = default; file_status(file_status&&) noexcept = default; ~file_status(); // assignments file_status& operator=(const file_status&) noexcept = default; file_status& operator=(file_status&&) noexcept = default; // [fs.file.status.mods], modifiers void type(file_type ft) noexcept; void permissions(perms prms) noexcept; // [fs.file.status.obs], observers file_type type() const noexcept; perms permissions() const noexcept; friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } }; }
An object of type file_status stores information about the type and permissions of a file.

31.12.9.2 Constructors [fs.file.status.cons]

explicit file_status(file_type ft, perms prms = perms::unknown) noexcept;
Postconditions: type() == ft and permissions() == prms.

31.12.9.3 Observers [fs.file.status.obs]

file_type type() const noexcept;
Returns: The value of type() specified by the postconditions of the most recent call to a constructor, operator=, or type(file_type) function.
perms permissions() const noexcept;
Returns: The value of permissions() specified by the postconditions of the most recent call to a constructor, operator=, or permissions(perms) function.

31.12.9.4 Modifiers [fs.file.status.mods]

void type(file_type ft) noexcept;
Postconditions: type() == ft.
void permissions(perms prms) noexcept;
Postconditions: permissions() == prms.

31.12.10 Class directory_entry [fs.class.directory.entry]

31.12.10.1 General [fs.class.directory.entry.general]

namespace std::filesystem { class directory_entry { public: // [fs.dir.entry.cons], constructors and destructor directory_entry() noexcept = default; directory_entry(const directory_entry&) = default; directory_entry(directory_entry&&) noexcept = default; explicit directory_entry(const filesystem::path& p); directory_entry(const filesystem::path& p, error_code& ec); ~directory_entry(); // assignments directory_entry& operator=(const directory_entry&) = default; directory_entry& operator=(directory_entry&&) noexcept = default; // [fs.dir.entry.mods], modifiers void assign(const filesystem::path& p); void assign(const filesystem::path& p, error_code& ec); void replace_filename(const filesystem::path& p); void replace_filename(const filesystem::path& p, error_code& ec); void refresh(); void refresh(error_code& ec) noexcept; // [fs.dir.entry.obs], observers const filesystem::path& path() const noexcept; operator const filesystem::path&() const noexcept; bool exists() const; bool exists(error_code& ec) const noexcept; bool is_block_file() const; bool is_block_file(error_code& ec) const noexcept; bool is_character_file() const; bool is_character_file(error_code& ec) const noexcept; bool is_directory() const; bool is_directory(error_code& ec) const noexcept; bool is_fifo() const; bool is_fifo(error_code& ec) const noexcept; bool is_other() const; bool is_other(error_code& ec) const noexcept; bool is_regular_file() const; bool is_regular_file(error_code& ec) const noexcept; bool is_socket() const; bool is_socket(error_code& ec) const noexcept; bool is_symlink() const; bool is_symlink(error_code& ec) const noexcept; uintmax_t file_size() const; uintmax_t file_size(error_code& ec) const noexcept; uintmax_t hard_link_count() const; uintmax_t hard_link_count(error_code& ec) const noexcept; file_time_type last_write_time() const; file_time_type last_write_time(error_code& ec) const noexcept; file_status status() const; file_status status(error_code& ec) const noexcept; file_status symlink_status() const; file_status symlink_status(error_code& ec) const noexcept; bool operator==(const directory_entry& rhs) const noexcept; strong_ordering operator<=>(const directory_entry& rhs) const noexcept; // [fs.dir.entry.io], inserter template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const directory_entry& d); private: filesystem::path path-object; // exposition only }; }
A directory_entry object stores a path object and may store additional objects for file attributes such as hard link count, status, symlink status, file size, and last write time.
Implementations should store such additional file attributes during directory iteration if their values are available and storing the values would allow the implementation to eliminate file system accesses by directory_entry observer functions ([fs.op.funcs]).
Such stored file attribute values are said to be cached.
[Note 1: 
directory_iterator can cache already available attribute values directly into a directory_entry object without the cost of a call to refresh().
— end note]
[Example 1: using namespace std::filesystem; // use possibly cached last write time to minimize disk accesses for (auto&& x : directory_iterator(".")) { std::cout << x.path() << " " << x.last_write_time() << std::endl; } // call refresh() to refresh a stale cache for (auto&& x : directory_iterator(".")) { lengthy_function(x.path()); // cache becomes stale x.refresh(); std::cout << x.path() << " " << x.last_write_time() << std::endl; }
On implementations that do not cache the last write time, both loops will result in a potentially expensive call to the std​::​filesystem​::​last_write_time function.
On implementations that do cache the last write time, the first loop will use the cached value and so will not result in a potentially expensive call to the std​::​filesystem​::​last_write_time function.
The code is portable to any implementation, regardless of whether or not it employs caching.
— end example]

31.12.10.2 Constructors [fs.dir.entry.cons]

explicit directory_entry(const filesystem::path& p); directory_entry(const filesystem::path& p, error_code& ec);
Effects: Calls refresh() or refresh(ec), respectively.
Postconditions: path() == p if no error occurs, otherwise path() == filesystem​::​path().
Throws: As specified in [fs.err.report].

31.12.10.3 Modifiers [fs.dir.entry.mods]

void assign(const filesystem::path& p); void assign(const filesystem::path& p, error_code& ec);
Effects: Equivalent to path-object = p, then refresh() or refresh(ec), respectively.
If an error occurs, the values of any cached attributes are unspecified.
Throws: As specified in [fs.err.report].
void replace_filename(const filesystem::path& p); void replace_filename(const filesystem::path& p, error_code& ec);
Effects: Equivalent to path-object.replace_filename(p), then refresh() or refresh(ec), respectively.
If an error occurs, the values of any cached attributes are unspecified.
Throws: As specified in [fs.err.report].
void refresh(); void refresh(error_code& ec) noexcept;
Effects: Stores the current values of any cached attributes of the file p resolves to.
If an error occurs, an error is reported ([fs.err.report]) and the values of any cached attributes are unspecified.
Throws: As specified in [fs.err.report].
[Note 1: 
Implementations of directory_iterator ([fs.class.directory.iterator]) are prohibited from directly or indirectly calling the refresh function as described in [fs.class.directory.iterator.general].
— end note]

31.12.10.4 Observers [fs.dir.entry.obs]

Unqualified function names in the Returns: elements of the directory_entry observers described below refer to members of the std​::​filesystem namespace.
const filesystem::path& path() const noexcept; operator const filesystem::path&() const noexcept;
Returns: path-object.
bool exists() const; bool exists(error_code& ec) const noexcept;
Returns: exists(this->status()) or exists(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_block_file() const; bool is_block_file(error_code& ec) const noexcept;
Returns: is_block_file(this->status()) or is_block_file(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_character_file() const; bool is_character_file(error_code& ec) const noexcept;
Returns: is_character_file(this->status()) or is_character_file(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_directory() const; bool is_directory(error_code& ec) const noexcept;
Returns: is_directory(this->status()) or is_directory(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_fifo() const; bool is_fifo(error_code& ec) const noexcept;
Returns: is_fifo(this->status()) or is_fifo(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_other() const; bool is_other(error_code& ec) const noexcept;
Returns: is_other(this->status()) or is_other(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_regular_file() const; bool is_regular_file(error_code& ec) const noexcept;
Returns: is_regular_file(this->status()) or is_regular_file(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
bool is_socket() const; bool is_socket(error_code& ec) const noexcept;
Returns: is_socket(this->status()) or is_socket(this->status(ec)), respectively.
Throws: As specified in [fs.err.report].
Returns: is_symlink(this->symlink_status()) or is_symlink(this->symlink_status(ec)), respectively.
Throws: As specified in [fs.err.report].
uintmax_t file_size() const; uintmax_t file_size(error_code& ec) const noexcept;
Returns: If cached, the file size attribute value.
Otherwise, file_size(path()) or file_size(path(), ec), respectively.
Throws: As specified in [fs.err.report].
Returns: If cached, the hard link count attribute value.
Otherwise, hard_link_count(path()) or hard_link_count(path(), ec), respectively.
Throws: As specified in [fs.err.report].
file_time_type last_write_time() const; file_time_type last_write_time(error_code& ec) const noexcept;
Returns: If cached, the last write time attribute value.
Otherwise, last_write_time(path()) or last_write_time(path(), ec), respectively.
Throws: As specified in [fs.err.report].
file_status status() const; file_status status(error_code& ec) const noexcept;
Returns: If cached, the status attribute value.
Otherwise, status(path()) or status(path(), ec), respectively.
Throws: As specified in [fs.err.report].
Returns: If cached, the symlink status attribute value.
Otherwise, symlink_status(path()) or symlink_status(path(), ec), respectively.
Throws: As specified in [fs.err.report].
bool operator==(const directory_entry& rhs) const noexcept;
Returns: path-object == rhs.path-object.
strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
Returns: path-object <=> rhs.path-object.

31.12.10.5 Inserter [fs.dir.entry.io]

template<class charT, class traits> friend basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
Effects: Equivalent to: return os << d.path();

31.12.11 Class directory_iterator [fs.class.directory.iterator]

31.12.11.1 General [fs.class.directory.iterator.general]

An object of type directory_iterator provides an iterator for a sequence of directory_entry elements representing the path and any cached attribute values ([fs.class.directory.entry]) for each file in a directory or in an implementation-defined directory-like file type.
[Note 1: 
For iteration into subdirectories, see class recursive_directory_iterator ([fs.class.rec.dir.itr]).
— end note]
namespace std::filesystem { class directory_iterator { public: using iterator_category = input_iterator_tag; using value_type = directory_entry; using difference_type = ptrdiff_t; using pointer = const directory_entry*; using reference = const directory_entry&; // [fs.dir.itr.members], member functions directory_iterator() noexcept; explicit directory_iterator(const path& p); directory_iterator(const path& p, directory_options options); directory_iterator(const path& p, error_code& ec); directory_iterator(const path& p, directory_options options, error_code& ec); directory_iterator(const directory_iterator& rhs); directory_iterator(directory_iterator&& rhs) noexcept; ~directory_iterator(); directory_iterator& operator=(const directory_iterator& rhs); directory_iterator& operator=(directory_iterator&& rhs) noexcept; const directory_entry& operator*() const; const directory_entry* operator->() const; directory_iterator& operator++(); directory_iterator& increment(error_code& ec); bool operator==(default_sentinel_t) const noexcept { return *this == directory_iterator(); } // other members as required by [input.iterators], input iterators }; }
directory_iterator meets the Cpp17InputIterator requirements ([input.iterators]).
If an iterator of type directory_iterator reports an error or is advanced past the last directory element, that iterator shall become equal to the end iterator value.
The directory_iterator default constructor shall create an iterator equal to the end iterator value, and this shall be the only valid iterator for the end condition.
The end iterator is not dereferenceable.
Two end iterators are always equal.
An end iterator shall not be equal to a non-end iterator.
The result of calling the path() member of the directory_entry object obtained by dereferencing a directory_iterator is a reference to a path object composed of the directory argument from which the iterator was constructed with the filename of the directory entry appended as if by operator/=.
Directory iteration shall not yield directory entries for the current (dot) and parent (dot-dot) directories.
The order of directory entries obtained by dereferencing successive increments of a directory_iterator is unspecified.
Constructors and non-const directory_iterator member functions store the values of any cached attributes ([fs.class.directory.entry]) in the directory_entry element returned by operator*().
directory_iterator member functions shall not directly or indirectly call any directory_entry refresh function.
[Note 2: 
The exact mechanism for storing cached attribute values is not exposed to users.
— end note]
[Note 3: 
A path obtained by dereferencing a directory iterator might not actually exist; it could be a symbolic link to a non-existent file.
Recursively walking directory trees for purposes of removing and renaming entries might invalidate symbolic links that are being followed.
— end note]
[Note 4: 
If a file is removed from or added to a directory after the construction of a directory_iterator for the directory, it is unspecified whether or not subsequently incrementing the iterator will ever result in an iterator referencing the removed or added directory entry.
See POSIX readdir.
— end note]

31.12.11.2 Members [fs.dir.itr.members]

directory_iterator() noexcept;
Effects: Constructs the end iterator.
explicit directory_iterator(const path& p); directory_iterator(const path& p, directory_options options); directory_iterator(const path& p, error_code& ec); directory_iterator(const path& p, directory_options options, error_code& ec);
Effects: For the directory that p resolves to, constructs an iterator for the first element in a sequence of directory_entry elements representing the files in the directory, if any; otherwise the end iterator.
However, if (options & directory_options::skip_permission_denied) != directory_options::none and construction encounters an error indicating that permission to access p is denied, constructs the end iterator and does not report an error.
Throws: As specified in [fs.err.report].
[Note 1: 
To iterate over the current directory, use directory_iterator(".") rather than directory_iterator("").
— end note]
directory_iterator(const directory_iterator& rhs); directory_iterator(directory_iterator&& rhs) noexcept;
Postconditions: *this has the original value of rhs.
directory_iterator& operator=(const directory_iterator& rhs); directory_iterator& operator=(directory_iterator&& rhs) noexcept;
Effects: If *this and rhs are the same object, the member has no effect.
Postconditions: *this has the original value of rhs.
Returns: *this.
directory_iterator& operator++(); directory_iterator& increment(error_code& ec);
Effects: As specified for the prefix increment operation of Input iterators.
Returns: *this.
Throws: As specified in [fs.err.report].

31.12.11.3 Non-member functions [fs.dir.itr.nonmembers]

These functions enable range access for directory_iterator.
directory_iterator begin(directory_iterator iter) noexcept;
Returns: iter.
directory_iterator end(directory_iterator) noexcept;
Returns: directory_iterator().

31.12.12 Class recursive_directory_iterator [fs.class.rec.dir.itr]

31.12.12.1 General [fs.class.rec.dir.itr.general]

An object of type recursive_directory_iterator provides an iterator for a sequence of directory_entry elements representing the files in a directory or in an implementation-defined directory-like file type, and its subdirectories.
namespace std::filesystem { class recursive_directory_iterator { public: using iterator_category = input_iterator_tag; using value_type = directory_entry; using difference_type = ptrdiff_t; using pointer = const directory_entry*; using reference = const directory_entry&; // [fs.rec.dir.itr.members], constructors and destructor recursive_directory_iterator() noexcept; explicit recursive_directory_iterator(const path& p); recursive_directory_iterator(const path& p, directory_options options); recursive_directory_iterator(const path& p, directory_options options, error_code& ec); recursive_directory_iterator(const path& p, error_code& ec); recursive_directory_iterator(const recursive_directory_iterator& rhs); recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; ~recursive_directory_iterator(); // [fs.rec.dir.itr.members], observers directory_options options() const; int depth() const; bool recursion_pending() const; const directory_entry& operator*() const; const directory_entry* operator->() const; // [fs.rec.dir.itr.members], modifiers recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs); recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept; recursive_directory_iterator& operator++(); recursive_directory_iterator& increment(error_code& ec); void pop(); void pop(error_code& ec); void disable_recursion_pending(); bool operator==(default_sentinel_t) const noexcept { return *this == recursive_directory_iterator(); } // other members as required by [input.iterators], input iterators }; }
Calling options, depth, recursion_pending, pop or disable_recursion_pending on an iterator that is not dereferenceable results in undefined behavior.
The behavior of a recursive_directory_iterator is the same as a directory_iterator unless otherwise specified.
[Note 1: 
If the directory structure being iterated over contains cycles then it is possible that the end iterator is unreachable.
— end note]

31.12.12.2 Members [fs.rec.dir.itr.members]

recursive_directory_iterator() noexcept;
Effects: Constructs the end iterator.
explicit recursive_directory_iterator(const path& p); recursive_directory_iterator(const path& p, directory_options options); recursive_directory_iterator(const path& p, directory_options options, error_code& ec); recursive_directory_iterator(const path& p, error_code& ec);
Effects: Constructs an iterator representing the first entry in the directory to which p resolves, if any; otherwise, the end iterator.
However, if (options & directory_options::skip_permission_denied) != directory_options::none and construction encounters an error indicating that permission to access p is denied, constructs the end iterator and does not report an error.
Postconditions: options() == options for the signatures with a directory_options argument, otherwise options() == directory_options​::​none.
Throws: As specified in [fs.err.report].
[Note 1: 
Use recursive_directory_iterator(".") rather than recursive_directory_iterator("") to iterate over the current directory.
— end note]
[Note 2: 
By default, recursive_directory_iterator does not follow directory symlinks.
To follow directory symlinks, specify options as directory_options​::​follow_directory_symlink.
— end note]
recursive_directory_iterator(const recursive_directory_iterator& rhs);
Postconditions:
  • options() == rhs.options()
  • depth() == rhs.depth()
  • recursion_pending() == rhs.recursion_pending()
recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
Postconditions: options(), depth(), and recursion_pending() have the values that rhs.options(), rhs.depth(), and rhs.recursion_pending(), respectively, had before the function call.
recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
Effects: If *this and rhs are the same object, the member has no effect.
Postconditions:
  • options() == rhs.options()
  • depth() == rhs.depth()
  • recursion_pending() == rhs.recursion_pending()
Returns: *this.
recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
Effects: If *this and rhs are the same object, the member has no effect.
Postconditions: options(), depth(), and recursion_pending() have the values that rhs.options(), rhs.depth(), and rhs.recursion_pending(), respectively, had before the function call.
Returns: *this.
directory_options options() const;
Returns: The value of the argument passed to the constructor for the options parameter, if present, otherwise directory_options​::​none.
Throws: Nothing.
int depth() const;
Returns: The current depth of the directory tree being traversed.
[Note 3: 
The initial directory is depth 0, its immediate subdirectories are depth 1, and so forth.
— end note]
Throws: Nothing.
bool recursion_pending() const;
Returns: true if disable_recursion_pending() has not been called subsequent to the prior construction or increment operation, otherwise false.
Throws: Nothing.
recursive_directory_iterator& operator++(); recursive_directory_iterator& increment(error_code& ec);
Effects: As specified for the prefix increment operation of Input iterators, except that:
  • If there are no more entries at the current depth, then if depth() != 0 iteration over the parent directory resumes; otherwise *this = recursive_directory_iterator().
  • Otherwise if recursion_pending() && is_directory((*this)->status()) && (!is_symlink((*this)->symlink_status()) || (options() & directory_options::follow_directory_symlink) != directory_options::none) then either directory (*this)->path() is recursively iterated into or, if (options() & directory_options::skip_permission_denied) != directory_options::none and an error occurs indicating that permission to access directory (*this)->path() is denied, then directory (*this)->path() is treated as an empty directory and no error is reported.
Returns: *this.
Throws: As specified in [fs.err.report].
void pop(); void pop(error_code& ec);
Effects: If depth() == 0, set *this to recursive_directory_iterator().
Otherwise, cease iteration of the directory currently being iterated over, and continue iteration over the parent directory.
Throws: As specified in [fs.err.report].
Remarks: Any copies of the previous value of *this are no longer required to be dereferenceable nor to be in the domain of ==.
void disable_recursion_pending();
Postconditions: recursion_pending() == false.
[Note 4: 
disable_recursion_pending() is used to prevent unwanted recursion into a directory.
— end note]

31.12.12.3 Non-member functions [fs.rec.dir.itr.nonmembers]

These functions enable use of recursive_directory_iterator with range-based for statements.
recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
Returns: iter.
recursive_directory_iterator end(recursive_directory_iterator) noexcept;
Returns: recursive_directory_iterator().

31.12.13 Filesystem operation functions [fs.op.funcs]

31.12.13.1 General [fs.op.funcs.general]

Filesystem operation functions query or modify files, including directories, in external storage.
[Note 1: 
Because hardware failures, network failures, file system races ([fs.race.behavior]), and many other kinds of errors occur frequently in file system operations, any filesystem operation function, no matter how apparently innocuous, can encounter an error; see [fs.err.report].
— end note]

31.12.13.2 Absolute [fs.op.absolute]

path filesystem::absolute(const path& p); path filesystem::absolute(const path& p, error_code& ec);
Effects: Composes an absolute path referencing the same file system location as p according to the operating system ([fs.conform.os]).
Returns: The composed path.
The signature with argument ec returns path() if an error occurs.
[Note 1: 
For the returned path, rp, rp.is_absolute() is true unless an error occurs.
— end note]
Throws: As specified in [fs.err.report].
[Note 2: 
To resolve symlinks or perform other sanitization that can involve queries to secondary storage, such as hard disks, consider canonical ([fs.op.canonical]).
— end note]
[Note 3: 
Implementations are strongly encouraged to not query secondary storage, and not consider !exists(p) an error.
— end note]
[Example 1: 
For POSIX-based operating systems, absolute(p) is simply current_path()/p.
For Windows-based operating systems, absolute might have the same semantics as GetFullPathNameW.
— end example]

31.12.13.3 Canonical [fs.op.canonical]

path filesystem::canonical(const path& p); path filesystem::canonical(const path& p, error_code& ec);
Effects: Converts p to an absolute path that has no symbolic link, dot, or dot-dot elements in its pathname in the generic format.
Returns: A path that refers to the same file system object as absolute(p).
The signature with argument ec returns path() if an error occurs.
Throws: As specified in [fs.err.report].
Remarks: !exists(p) is an error.

31.12.13.4 Copy [fs.op.copy]

void filesystem::copy(const path& from, const path& to);
Effects: Equivalent to copy(from, to, copy_options​::​none).
void filesystem::copy(const path& from, const path& to, error_code& ec);
Effects: Equivalent to copy(from, to, copy_options​::​none, ec).
void filesystem::copy(const path& from, const path& to, copy_options options); void filesystem::copy(const path& from, const path& to, copy_options options, error_code& ec);
Preconditions: At most one element from each option group ([fs.enum.copy.opts]) is set in options.
Effects: Before the first use of f and t:
  • If (options & copy_options::create_symlinks) != copy_options::none || (options & copy_options::skip_symlinks) != copy_options::none then auto f = symlink_status(from) and if needed auto t = symlink_status(to).
  • Otherwise, if (options & copy_options::copy_symlinks) != copy_options::none then auto f = symlink_status(from) and if needed auto t = status(to).
  • Otherwise, auto f = status(from) and if needed auto t = status(to).
Effects are then as follows:
  • If f.type() or t.type() is an implementation-defined file type ([fs.enum.file.type]), then the effects are implementation-defined.
  • Otherwise, an error is reported as specified in [fs.err.report] if
    • exists(f) is false, or
    • equivalent(from, to) is true, or
    • is_other(f) || is_other(t) is true, or
    • is_directory(f) && is_regular_file(t) is true.
  • Otherwise, if is_symlink(f), then:
    • If (options & copy_options​::​skip_symlinks) != copy_options​::​none then return.
    • Otherwise if !exists(t) && (options & copy_options::copy_symlinks) != copy_options::none then copy_symlink(from, to).
    • Otherwise report an error as specified in [fs.err.report].
  • Otherwise, if is_regular_file(f), then:
    • If (options & copy_options​::​directories_only) != copy_options​::​none, then return.
    • Otherwise, if (options & copy_options​::​create_symlinks) != copy_options​::​none, then create a symbolic link to the source file.
    • Otherwise, if (options & copy_options​::​create_hard_links) != copy_options​::​none, then create a hard link to the source file.
    • Otherwise, if is_directory(t), then copy_file(from, to/from.filename(), options).
    • Otherwise, copy_file(from, to, options).
  • Otherwise, if is_directory(f) && (options & copy_options::create_symlinks) != copy_options::none then report an error with an error_code argument equal to make_error_code(errc​::​is_a_directory).
  • Otherwise, if is_directory(f) && ((options & copy_options::recursive) != copy_options::none || options == copy_options::none) then:
    • If exists(t) is false, then create_directory(to, from).
    • Then, iterate over the files in from, as if by for (const directory_entry& x : directory_iterator(from)) copy(x.path(), to/x.path().filename(), options | copy_options::in-recursive-copy); where in-recursive-copy is a bitmask element of copy_options that is not one of the elements in [fs.enum.copy.opts].
  • Otherwise, for the signature with argument ec, ec.clear().
  • Otherwise, no effects.
Throws: As specified in [fs.err.report].
Remarks: For the signature with argument ec, any library functions called by the implementation shall have an error_code argument if applicable.
[Example 1: 
Given this directory structure:
/dir1
  file1
  file2
  dir2
    file3
Calling copy("/dir1", "/dir3") would result in:
/dir1
  file1
  file2
  dir2
    file3
/dir3
  file1
  file2
Alternatively, calling copy("/dir1", "/dir3", copy_options​::​recursive) would result in:
/dir1
  file1
  file2
  dir2
    file3
/dir3
  file1
  file2
  dir2
    file3
— end example]

31.12.13.5 Copy file [fs.op.copy.file]

bool filesystem::copy_file(const path& from, const path& to); bool filesystem::copy_file(const path& from, const path& to, error_code& ec);
Returns: copy_file(from, to, copy_options​::​none) or
copy_file(from, to, copy_options​::​none, ec), respectively.
Throws: As specified in [fs.err.report].
bool filesystem::copy_file(const path& from, const path& to, copy_options options); bool filesystem::copy_file(const path& from, const path& to, copy_options options, error_code& ec);
Preconditions: At most one element from each option group ([fs.enum.copy.opts]) is set in options.
Effects: As follows:
  • Report an error as specified in [fs.err.report] if
    • is_regular_file(from) is false, or
    • exists(to) is true and is_regular_file(to) is false, or
    • exists(to) is true and equivalent(from, to) is true, or
    • exists(to) is true and (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none
  • Otherwise, copy the contents and attributes of the file from resolves to, to the file to resolves to, if
    • exists(to) is false, or
    • (options & copy_options​::​overwrite_existing) != copy_options​::​none, or
    • (options & copy_options​::​update_existing) != copy_options​::​none and from is more recent than to, determined as if by use of the last_write_time function ([fs.op.last.write.time]).
  • Otherwise, no effects.
Returns: true if the from file was copied, otherwise false.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].
Complexity: At most one direct or indirect invocation of status(to).

31.12.13.7 Create directories [fs.op.create.directories]

bool filesystem::create_directories(const path& p); bool filesystem::create_directories(const path& p, error_code& ec);
Effects: Calls create_directory() for each element of p that does not exist.
Returns: true if a new directory was created for the directory p resolves to, otherwise false.
Throws: As specified in [fs.err.report].
Complexity: where n is the number of elements of p.

31.12.13.8 Create directory [fs.op.create.directory]

bool filesystem::create_directory(const path& p); bool filesystem::create_directory(const path& p, error_code& ec) noexcept;
Effects: Creates the directory p resolves to, as if by POSIX mkdir with a second argument of static_cast<int>(perms​::​all).
If mkdir fails because p resolves to an existing directory, no error is reported.
Otherwise on failure an error is reported.
Returns: true if a new directory was created, otherwise false.
Throws: As specified in [fs.err.report].
bool filesystem::create_directory(const path& p, const path& existing_p); bool filesystem::create_directory(const path& p, const path& existing_p, error_code& ec) noexcept;
Effects: Creates the directory p resolves to, with attributes copied from directory existing_p.
The set of attributes copied is operating system dependent.
If mkdir fails because p resolves to an existing directory, no error is reported.
Otherwise on failure an error is reported.
[Note 1: 
For POSIX-based operating systems, the attributes are those copied by native API stat(existing_p.c_str(), &attributes_stat) followed by mkdir(p.c_str(), attributes_stat.st_mode).
For Windows-based operating systems, the attributes are those copied by native API CreateDirectoryExW(existing_p.c_str(), p.c_str(), 0).
— end note]
Returns: true if a new directory was created with attributes copied from directory existing_p, otherwise false.
Throws: As specified in [fs.err.report].

31.12.13.9 Create directory symlink [fs.op.create.dir.symlk]

Effects: Establishes the postcondition, as if by POSIX symlink().
Postconditions: new_symlink resolves to a symbolic link file that contains an unspecified representation of to.
Throws: As specified in [fs.err.report].
[Note 1: 
Some operating systems require symlink creation to identify that the link is to a directory.
Thus, create_symlink() (instead of create_directory_symlink()) cannot be used reliably to create directory symlinks.
— end note]
[Note 2: 
Some operating systems do not support symbolic links at all or support them only for regular files.
Some file systems (such as the FAT file system) do not support symbolic links regardless of the operating system.
— end note]

31.12.13.10 Create hard link [fs.op.create.hard.lk]

Effects: Establishes the postcondition, as if by POSIX link().
Postconditions:
  • exists(to) && exists(new_hard_link) && equivalent(to, new_hard_link)
  • The contents of the file or directory to resolves to are unchanged.
Throws: As specified in [fs.err.report].
[Note 1: 
Some operating systems do not support hard links at all or support them only for regular files.
Some file systems (such as the FAT file system) do not support hard links regardless of the operating system.
Some file systems limit the number of links per file.
— end note]

31.12.13.12 Current path [fs.op.current.path]

path filesystem::current_path(); path filesystem::current_path(error_code& ec);
Returns: The absolute path of the current working directory, whose pathname in the native format is obtained as if by POSIX getcwd().
The signature with argument ec returns path() if an error occurs.
Throws: As specified in [fs.err.report].
Remarks: The current working directory is the directory, associated with the process, that is used as the starting location in pathname resolution for relative paths.
[Note 1: 
The current_path() name was chosen to emphasize that the returned value is a path, not just a single directory name.
— end note]
[Note 2: 
The current path as returned by many operating systems is a dangerous global variable and can be changed unexpectedly by third-party or system library functions, or by another thread.
— end note]
void filesystem::current_path(const path& p); void filesystem::current_path(const path& p, error_code& ec) noexcept;
Effects: Establishes the postcondition, as if by POSIX chdir().
Postconditions: equivalent(p, current_path()).
Throws: As specified in [fs.err.report].
[Note 3: 
The current path for many operating systems is a dangerous global state and can be changed unexpectedly by third-party or system library functions, or by another thread.
— end note]

31.12.13.13 Equivalent [fs.op.equivalent]

bool filesystem::equivalent(const path& p1, const path& p2); bool filesystem::equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
Two paths are considered to resolve to the same file system entity if two candidate entities reside on the same device at the same location.
[Note 1: 
On POSIX platforms, this is determined as if by the values of the POSIX stat class, obtained as if by stat() for the two paths, having equal st_dev values and equal st_ino values.
— end note]
Returns: true, if p1 and p2 resolve to the same file system entity, otherwise false.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].
Remarks: !exists(p1) || !exists(p2) is an error.

31.12.13.14 Exists [fs.op.exists]

bool filesystem::exists(file_status s) noexcept;
Returns: status_known(s) && s.type() != file_type​::​not_found.
bool filesystem::exists(const path& p); bool filesystem::exists(const path& p, error_code& ec) noexcept;
Let s be a file_status, determined as if by status(p) or status(p, ec), respectively.
Effects: The signature with argument ec calls ec.clear() if status_known(s).
Returns: exists(s).
Throws: As specified in [fs.err.report].

31.12.13.15 File size [fs.op.file.size]

uintmax_t filesystem::file_size(const path& p); uintmax_t filesystem::file_size(const path& p, error_code& ec) noexcept;
Effects: If exists(p) is false, an error is reported ([fs.err.report]).
Returns:
  • If is_regular_file(p), the size in bytes of the file p resolves to, determined as if by the value of the POSIX stat class member st_size obtained as if by POSIX stat().
  • Otherwise, the result is implementation-defined.
The signature with argument ec returns static_cast<uintmax_t>(-1) if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.16 Hard link count [fs.op.hard.lk.ct]

Returns: The number of hard links for p.
The signature with argument ec returns static_cast<uintmax_t>(-1) if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.17 Is block file [fs.op.is.block.file]

bool filesystem::is_block_file(file_status s) noexcept;
Returns: s.type() == file_type​::​block.
bool filesystem::is_block_file(const path& p); bool filesystem::is_block_file(const path& p, error_code& ec) noexcept;
Returns: is_block_file(status(p)) or is_block_file(status(p, ec)), respectively.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.18 Is character file [fs.op.is.char.file]

bool filesystem::is_character_file(file_status s) noexcept;
Returns: s.type() == file_type​::​character.
bool filesystem::is_character_file(const path& p); bool filesystem::is_character_file(const path& p, error_code& ec) noexcept;
Returns: is_character_file(status(p)) or is_character_file(status(p, ec)), respectively.

The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.19 Is directory [fs.op.is.directory]

bool filesystem::is_directory(file_status s) noexcept;
Returns: s.type() == file_type​::​directory.
bool filesystem::is_directory(const path& p); bool filesystem::is_directory(const path& p, error_code& ec) noexcept;
Returns: is_directory(status(p)) or is_directory(status(p, ec)), respectively.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.20 Is empty [fs.op.is.empty]

bool filesystem::is_empty(const path& p); bool filesystem::is_empty(const path& p, error_code& ec);
Effects:
  • Determine file_status s, as if by status(p) or status(p, ec), respectively.
  • For the signature with argument ec, return false if an error occurred.
  • Otherwise, if is_directory(s):
    • Create a variable itr, as if by directory_iterator itr(p) or directory_iterator itr(p, ec), respectively.
    • For the signature with argument ec, return false if an error occurred.
    • Otherwise, return itr == directory_iterator().
  • Otherwise:
    • Determine uintmax_t sz, as if by file_size(p) or file_size(p, ec), respectively.
    • For the signature with argument ec, return false if an error occurred.
    • Otherwise, return sz == 0.
Throws: As specified in [fs.err.report].

31.12.13.21 Is fifo [fs.op.is.fifo]

bool filesystem::is_fifo(file_status s) noexcept;
Returns: s.type() == file_type​::​fifo.
bool filesystem::is_fifo(const path& p); bool filesystem::is_fifo(const path& p, error_code& ec) noexcept;
Returns: is_fifo(status(p)) or is_fifo(status(p, ec)), respectively.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.22 Is other [fs.op.is.other]

bool filesystem::is_other(file_status s) noexcept;
Returns: exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s).
bool filesystem::is_other(const path& p); bool filesystem::is_other(const path& p, error_code& ec) noexcept;
Returns: is_other(status(p)) or is_other(status(p, ec)), respectively.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.23 Is regular file [fs.op.is.regular.file]

bool filesystem::is_regular_file(file_status s) noexcept;
Returns: s.type() == file_type​::​regular.
bool filesystem::is_regular_file(const path& p);
Returns: is_regular_file(status(p)).
Throws: filesystem_error if status(p) would throw filesystem_error.
bool filesystem::is_regular_file(const path& p, error_code& ec) noexcept;
Effects: Sets ec as if by status(p, ec).
[Note 1: 
file_type​::​none, file_type​::​not_found and file_type​::​unknown cases set ec to error values.
To distinguish between cases, call the status function directly.
— end note]
Returns: is_regular_file(status(p, ec)).
Returns false if an error occurs.

31.12.13.24 Is socket [fs.op.is.socket]

bool filesystem::is_socket(file_status s) noexcept;
Returns: s.type() == file_type​::​socket.
bool filesystem::is_socket(const path& p); bool filesystem::is_socket(const path& p, error_code& ec) noexcept;
Returns: is_socket(status(p)) or is_socket(status(p, ec)), respectively.
The signature with argument ec returns false if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.26 Last write time [fs.op.last.write.time]

file_time_type filesystem::last_write_time(const path& p); file_time_type filesystem::last_write_time(const path& p, error_code& ec) noexcept;
Returns: The time of last data modification of p, determined as if by the value of the POSIX stat class member st_mtime obtained as if by POSIX stat().
The signature with argument ec returns file_time_type​::​min() if an error occurs.
Throws: As specified in [fs.err.report].
void filesystem::last_write_time(const path& p, file_time_type new_time); void filesystem::last_write_time(const path& p, file_time_type new_time, error_code& ec) noexcept;
Effects: Sets the time of last data modification of the file resolved to by p to new_time, as if by POSIX futimens().
Throws: As specified in [fs.err.report].
[Note 1: 
A postcondition of last_write_time(p) == new_time is not specified because it does not necessarily hold for file systems with coarse time granularity.
— end note]

31.12.13.27 Permissions [fs.op.permissions]

void filesystem::permissions(const path& p, perms prms, perm_options opts=perm_options::replace); void filesystem::permissions(const path& p, perms prms, error_code& ec) noexcept; void filesystem::permissions(const path& p, perms prms, perm_options opts, error_code& ec);
Preconditions: Exactly one of the perm_options constants replace, add, or remove is present in opts.
Effects: Applies the action specified by opts to the file p resolves to, or to file p itself if p is a symbolic link and perm_options​::​nofollow is set in opts.
The action is applied as if by POSIX fchmodat().
[Note 1: 
Conceptually permissions are viewed as bits, but the actual implementation can use some other mechanism.
— end note]
Throws: As specified in [fs.err.report].
Remarks: The second signature behaves as if it had an additional parameter perm_options opts with an argument of perm_options​::​replace.

31.12.13.28 Proximate [fs.op.proximate]

path filesystem::proximate(const path& p, error_code& ec);
Returns: proximate(p, current_path(), ec).
Throws: As specified in [fs.err.report].
path filesystem::proximate(const path& p, const path& base = current_path()); path filesystem::proximate(const path& p, const path& base, error_code& ec);
Returns: For the first form: weakly_canonical(p).lexically_proximate(weakly_canonical(base));
For the second form: weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec)); or path() at the first error occurrence, if any.
Throws: As specified in [fs.err.report].

31.12.13.30 Relative [fs.op.relative]

path filesystem::relative(const path& p, error_code& ec);
Returns: relative(p, current_path(), ec).
Throws: As specified in [fs.err.report].
path filesystem::relative(const path& p, const path& base = current_path()); path filesystem::relative(const path& p, const path& base, error_code& ec);
Returns: For the first form: weakly_canonical(p).lexically_relative(weakly_canonical(base));
For the second form: weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec)); or path() at the first error occurrence, if any.
Throws: As specified in [fs.err.report].

31.12.13.31 Remove [fs.op.remove]

bool filesystem::remove(const path& p); bool filesystem::remove(const path& p, error_code& ec) noexcept;
Effects: If exists(symlink_status(p, ec)), the file p is removed as if by POSIX remove().
[Note 1: 
A symbolic link is itself removed, rather than the file it resolves to.
— end note]
Postconditions: exists(symlink_status(p)) is false.
Returns: true if a file p has been removed and false otherwise.
[Note 2: 
Absence of a file p is not an error.
— end note]
Throws: As specified in [fs.err.report].

31.12.13.32 Remove all [fs.op.remove.all]

uintmax_t filesystem::remove_all(const path& p); uintmax_t filesystem::remove_all(const path& p, error_code& ec);
Effects: Recursively deletes the contents of p if it exists, then deletes file p itself, as if by POSIX remove().
[Note 1: 
A symbolic link is itself removed, rather than the file it resolves to.
— end note]
Postconditions: exists(symlink_status(p)) is false.
Returns: The number of files removed.
The signature with argument ec returns static_cast< uintmax_t>(-1) if an error occurs.
Throws: As specified in [fs.err.report].

31.12.13.33 Rename [fs.op.rename]

void filesystem::rename(const path& old_p, const path& new_p); void filesystem::rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
Effects: Renames old_p to new_p, as if by POSIX rename().
[Note 1: 
  • If old_p and new_p resolve to the same existing file, no action is taken.
  • Otherwise, the rename can include the following effects:
    • if new_p resolves to an existing non-directory file, new_p is removed; otherwise,
    • if new_p resolves to an existing directory, new_p is removed if empty on POSIX compliant operating systems but might be an error on other operating systems.
A symbolic link is itself renamed, rather than the file it resolves to.
— end note]
Throws: As specified in [fs.err.report].

31.12.13.34 Resize file [fs.op.resize.file]

void filesystem::resize_file(const path& p, uintmax_t new_size); void filesystem::resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
Effects: Causes the size that would be returned by file_size(p) to be equal to new_size, as if by POSIX truncate().
Throws: As specified in [fs.err.report].

31.12.13.35 Space [fs.op.space]

space_info filesystem::space(const path& p); space_info filesystem::space(const path& p, error_code& ec) noexcept;
Returns: An object of type space_info.
The value of the space_info object is determined as if by using POSIX statvfs to obtain a POSIX struct statvfs, and then multiplying its f_blocks, f_bfree, and f_bavail members by its f_frsize member, and assigning the results to the capacity, free, and available members respectively.
Any members for which the value cannot be determined shall be set to static_cast<uintmax_t>(-1).
For the signature with argument ec, all members are set to static_cast<uintmax_t>(-1) if an error occurs.
Throws: As specified in [fs.err.report].
Remarks: The value of member space_info​::​available is operating system dependent.
[Note 1: 
available might be less than free.
— end note]

31.12.13.36 Status [fs.op.status]

file_status filesystem::status(const path& p);
Effects: As if by: error_code ec; file_status result = status(p, ec); if (result.type() == file_type::none) throw filesystem_error(implementation-supplied-message, p, ec); return result;
Returns: See above.
Throws: filesystem_error.
[Note 1: 
result values of file_status(file_type​::​not_found) and file_status(file_type​::​unknown) are not considered failures and do not cause an exception to be thrown.
— end note]
file_status filesystem::status(const path& p, error_code& ec) noexcept;
Effects: If possible, determines the attributes of the file p resolves to, as if by using POSIX stat() to obtain a POSIX struct stat.
If, during attribute determination, the underlying file system API reports an error, sets ec to indicate the specific error reported.
Otherwise, ec.clear().
[Note 2: 
This allows users to inspect the specifics of underlying API errors even when the value returned by status() is not file_status(file_type​::​none).
— end note]
Let prms denote the result of (m & perms​::​mask), where m is determined as if by converting the st_mode member of the obtained struct stat to the type perms.
Returns:
  • If ec != error_code():
    • If the specific error indicates that p cannot be resolved because some element of the path does not exist, returns file_status(file_type​::​not_found).
    • Otherwise, if the specific error indicates that p can be resolved but the attributes cannot be determined, returns file_status(file_type​::​unknown).
    • Otherwise, returns file_status(file_type​::​none).
    [Note 3: 
    These semantics distinguish between p being known not to exist, p existing but not being able to determine its attributes, and there being an error that prevents even knowing if p exists.
    These distinctions are important to some use cases.
    — end note]
  • Otherwise,
    • If the attributes indicate a regular file, as if by POSIX S_ISREG, returns file_status(file_type​::​regular, prms).
      [Note 4: 
      file_type​::​regular implies appropriate <fstream> operations would succeed, assuming no hardware, permission, access, or file system race errors.
      Lack of file_type​::​regular does not necessarily imply <fstream> operations would fail on a directory.
      — end note]
    • Otherwise, if the attributes indicate a directory, as if by POSIX S_ISDIR, returns file_status(file_type​::​directory, prms).
      [Note 5: 
      file_type​::​directory implies that calling directory_iterator(p) would succeed.
      — end note]
    • Otherwise, if the attributes indicate a block special file, as if by POSIX S_ISBLK, returns file_status(file_type​::​block, prms).
    • Otherwise, if the attributes indicate a character special file, as if by POSIX S_ISCHR, returns file_status(file_type​::​character, prms).
    • Otherwise, if the attributes indicate a fifo or pipe file, as if by POSIX S_ISFIFO, returns file_status(file_type​::​fifo, prms).
    • Otherwise, if the attributes indicate a socket, as if by POSIX S_ISSOCK, returns file_status(file_type​::​socket, prms).
    • Otherwise, if the attributes indicate an implementation-defined file type ([fs.enum.file.type]), returns file_status(file_type​::​A, prms), where A is the constant for the implementation-defined file type.
    • Otherwise, returns file_status(file_type​::​unknown, prms).
Remarks: If a symbolic link is encountered during pathname resolution, pathname resolution continues using the contents of the symbolic link.

31.12.13.37 Status known [fs.op.status.known]

bool filesystem::status_known(file_status s) noexcept;
Returns: s.type() != file_type​::​none.

31.12.13.38 Symlink status [fs.op.symlink.status]

Effects: Same as status(), above, except that the attributes of p are determined as if by using POSIX lstat() to obtain a POSIX struct stat.
Let prms denote the result of (m & perms​::​mask), where m is determined as if by converting the st_mode member of the obtained struct stat to the type perms.
Returns: Same as status(), above, except that if the attributes indicate a symbolic link, as if by POSIX S_ISLNK, returns file_status(file_type​::​symlink, prms).
The signature with argument ec returns file_status(file_type​::​none) if an error occurs.
Throws: As specified in [fs.err.report].
Remarks: Pathname resolution terminates if p names a symbolic link.

31.12.13.39 Temporary directory path [fs.op.temp.dir.path]

path filesystem::temp_directory_path(); path filesystem::temp_directory_path(error_code& ec);
Let p be an unspecified directory path suitable for temporary files.
Effects: If exists(p) is false or is_directory(p) is false, an error is reported ([fs.err.report]).
Returns: The path p.
The signature with argument ec returns path() if an error occurs.
Throws: As specified in [fs.err.report].
[Example 1: 
For POSIX-based operating systems, an implementation might return the path supplied by the first environment variable found in the list TMPDIR, TMP, TEMP, TEMPDIR, or if none of these are found, "/tmp".
For Windows-based operating systems, an implementation might return the path reported by the Windows GetTempPath API function.
— end example]

31.12.13.40 Weakly canonical [fs.op.weakly.canonical]

path filesystem::weakly_canonical(const path& p); path filesystem::weakly_canonical(const path& p, error_code& ec);
Effects: Using status(p) or status(p, ec), respectively, to determine existence, return a path composed by operator/= from the result of calling canonical() with a path argument composed of the leading elements of p that exist, if any, followed by the elements of p that do not exist, if any.
For the first form, canonical() is called without an error_code argument.
For the second form, canonical() is called with ec as an error_code argument, and path() is returned at the first error occurrence, if any.
Postconditions: The returned path is in normal form ([fs.path.generic]).
Returns: p with symlinks resolved and the result normalized ([fs.path.generic]).
Throws: As specified in [fs.err.report].

31.13 C library files [c.files]

31.13.1 Header <cstdio> synopsis [cstdio.syn]

namespace std { using size_t = see [support.types.layout]; using FILE = see below; using fpos_t = see below; } #define NULL see [support.types.nullptr] #define _IOFBF see below #define _IOLBF see below #define _IONBF see below #define BUFSIZ see below #define EOF see below #define FOPEN_MAX see below #define FILENAME_MAX see below #define L_tmpnam see below #define SEEK_CUR see below #define SEEK_END see below #define SEEK_SET see below #define TMP_MAX see below #define stderr see below #define stdin see below #define stdout see below namespace std { int remove(const char* filename); int rename(const char* old_p, const char* new_p); FILE* tmpfile(); char* tmpnam(char* s); int fclose(FILE* stream); int fflush(FILE* stream); FILE* fopen(const char* filename, const char* mode); FILE* freopen(const char* filename, const char* mode, FILE* stream); void setbuf(FILE* stream, char* buf); int setvbuf(FILE* stream, char* buf, int mode, size_t size); int fprintf(FILE* stream, const char* format, ...); int fscanf(FILE* stream, const char* format, ...); int printf(const char* format, ...); int scanf(const char* format, ...); int snprintf(char* s, size_t n, const char* format, ...); int sprintf(char* s, const char* format, ...); int sscanf(const char* s, const char* format, ...); int vfprintf(FILE* stream, const char* format, va_list arg); int vfscanf(FILE* stream, const char* format, va_list arg); int vprintf(const char* format, va_list arg); int vscanf(const char* format, va_list arg); int vsnprintf(char* s, size_t n, const char* format, va_list arg); int vsprintf(char* s, const char* format, va_list arg); int vsscanf(const char* s, const char* format, va_list arg); int fgetc(FILE* stream); char* fgets(char* s, int n, FILE* stream); int fputc(int c, FILE* stream); int fputs(const char* s, FILE* stream); int getc(FILE* stream); int getchar(); int putc(int c, FILE* stream); int putchar(int c); int puts(const char* s); int ungetc(int c, FILE* stream); size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream); size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream); int fgetpos(FILE* stream, fpos_t* pos); int fseek(FILE* stream, long int offset, int whence); int fsetpos(FILE* stream, const fpos_t* pos); long int ftell(FILE* stream); void rewind(FILE* stream); void clearerr(FILE* stream); int feof(FILE* stream); int ferror(FILE* stream); void perror(const char* s); }
The contents and meaning of the header <cstdio> are the same as the C standard library header <stdio.h>.
Calls to the function tmpnam with an argument that is a null pointer value may introduce a data race ([res.on.data.races]) with other calls to tmpnam with an argument that is a null pointer value.
See also: ISO/IEC 9899:2018, 7.21

31.13.2 Header <cinttypes> synopsis [cinttypes.syn]

#include <cstdint> // see [cstdint.syn] namespace std { using imaxdiv_t = see below; constexpr intmax_t imaxabs(intmax_t j); constexpr imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); intmax_t strtoimax(const char* nptr, char** endptr, int base); uintmax_t strtoumax(const char* nptr, char** endptr, int base); intmax_t wcstoimax(const wchar_t* nptr, wchar_t** endptr, int base); uintmax_t wcstoumax(const wchar_t* nptr, wchar_t** endptr, int base); constexpr intmax_t abs(intmax_t); // optional, see below constexpr imaxdiv_t div(intmax_t, intmax_t); // optional, see below } #define PRIdN see below #define PRIiN see below #define PRIoN see below #define PRIuN see below #define PRIxN see below #define PRIXN see below #define SCNdN see below #define SCNiN see below #define SCNoN see below #define SCNuN see below #define SCNxN see below #define PRIdLEASTN see below #define PRIiLEASTN see below #define PRIoLEASTN see below #define PRIuLEASTN see below #define PRIxLEASTN see below #define PRIXLEASTN see below #define SCNdLEASTN see below #define SCNiLEASTN see below #define SCNoLEASTN see below #define SCNuLEASTN see below #define SCNxLEASTN see below #define PRIdFASTN see below #define PRIiFASTN see below #define PRIoFASTN see below #define PRIuFASTN see below #define PRIxFASTN see below #define PRIXFASTN see below #define SCNdFASTN see below #define SCNiFASTN see below #define SCNoFASTN see below #define SCNuFASTN see below #define SCNxFASTN see below #define PRIdMAX see below #define PRIiMAX see below #define PRIoMAX see below #define PRIuMAX see below #define PRIxMAX see below #define PRIXMAX see below #define SCNdMAX see below #define SCNiMAX see below #define SCNoMAX see below #define SCNuMAX see below #define SCNxMAX see below #define PRIdPTR see below #define PRIiPTR see below #define PRIoPTR see below #define PRIuPTR see below #define PRIxPTR see below #define PRIXPTR see below #define SCNdPTR see below #define SCNiPTR see below #define SCNoPTR see below #define SCNuPTR see below #define SCNxPTR see below
The contents and meaning of the header <cinttypes> are the same as the C standard library header <inttypes.h>, with the following changes:
  • The header <cinttypes> includes the header <cstdint> instead of <stdint.h>, and
  • intmax_t and uintmax_t are not required to be able to represent all values of extended integer types wider than long long and unsigned long long, respectively, and
  • if and only if the type intmax_t designates an extended integer type ([basic.fundamental]), the following function signatures are added: constexpr intmax_t abs(intmax_t); constexpr imaxdiv_t div(intmax_t, intmax_t); which shall have the same semantics as the function signatures constexpr intmax_t imaxabs(intmax_t) and constexpr imaxdiv_t imaxdiv(intmax_t, intmax_t), respectively.
See also: ISO/IEC 9899:2018, 7.8
Each of the PRI macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef-name in [cstdint.syn].
Each of the SCN macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef-name in [cstdint.syn] and has a suitable fscanf length modifier for the type.

32 Concurrency support library [thread]

32.1 General [thread.general]

The following subclauses describe components to create and manage threads, perform mutual exclusion, and communicate conditions and values between threads, as summarized in Table 149.
Table 149 — Concurrency support library summary [tab:thread.summary]
Subclause
Header
Requirements
Stop tokens
<stop_token>
Threads
<thread>
Atomic operations
<atomic>, <stdatomic.h>
Mutual exclusion
<mutex>, <shared_mutex>
Condition variables
<condition_variable>
Semaphores
<semaphore>
Coordination types
<latch>, <barrier>
Futures
<future>
Safe reclamation
<rcu>, <hazard_pointer>

32.2 Requirements [thread.req]

32.2.1 Template parameter names [thread.req.paramname]

Throughout this Clause, the names of template parameters are used to express type requirements.
Predicate is a function object type ([function.objects]).
Let pred denote an lvalue of type Predicate.
Then the expression pred() shall be well-formed and the type decltype(pred()) shall model boolean-testable ([concept.booleantestable]).
The return value of pred(), converted to bool, yields true if the corresponding test condition is satisfied, and false otherwise.
If a template parameter is named Clock, the corresponding template argument shall be a type C that meets the Cpp17Clock requirements ([time.clock.req]); the program is ill-formed if is_clock_v<C> is false.

32.2.2 Exceptions [thread.req.exception]

Some functions described in this Clause are specified to throw exceptions of type system_error ([syserr.syserr]).
Such exceptions are thrown if any of the function's error conditions is detected or a call to an operating system or other underlying API results in an error that prevents the library function from meeting its specifications.
Failure to allocate storage is reported as described in [res.on.exception.handling].
[Example 1: 
Consider a function in this Clause that is specified to throw exceptions of type system_error and specifies error conditions that include operation_not_permitted for a thread that does not have the privilege to perform the operation.
Assume that, during the execution of this function, an errno of EPERM is reported by a POSIX API call used by the implementation.
Since POSIX specifies an errno of EPERM when “the caller does not have the privilege to perform the operation”, the implementation maps EPERM to an error_condition of operation_not_permitted ([syserr]) and an exception of type system_error is thrown.
— end example]
The error_code reported by such an exception's code() member function compares equal to one of the conditions specified in the function's error condition element.

32.2.3 Native handles [thread.req.native]

Several classes described in this Clause have members native_handle_type and native_handle.
The presence of these members and their semantics is implementation-defined.
[Note 1: 
These members allow implementations to provide access to implementation details.
Their names are specified to facilitate portable compile-time detection.
Actual use of these members is inherently non-portable.
— end note]

32.2.4 Timing specifications [thread.req.timing]

Several functions described in this Clause take an argument to specify a timeout.
These timeouts are specified as either a duration or a time_point type as specified in [time].
Implementations necessarily have some delay in returning from a timeout.
Any overhead in interrupt response, function return, and scheduling induces a “quality of implementation” delay, expressed as duration .
Ideally, this delay would be zero.
Further, any contention for processor and memory resources induces a “quality of management” delay, expressed as duration .
The delay durations may vary from timeout to timeout, but in all cases shorter is better.
The functions whose names end in _for take an argument that specifies a duration.
These functions produce relative timeouts.
Implementations should use a steady clock to measure time for these functions.297
Given a duration argument , the real-time duration of the timeout is .
The functions whose names end in _until take an argument that specifies a time point.
These functions produce absolute timeouts.
Implementations should use the clock specified in the time point to measure time for these functions.
Given a clock time point argument , the clock time point of the return from timeout should be when the clock is not adjusted during the timeout.
If the clock is adjusted to the time during the timeout, the behavior should be as follows:
  • If , the waiting function should wake as soon as possible, i.e., , since the timeout is already satisfied.
    This specification may result in the total duration of the wait decreasing when measured against a steady clock.
  • If , the waiting function should not time out until Clock​::​now() returns a time , i.e., waking at .
    [Note 1: 
    When the clock is adjusted backwards, this specification can result in the total duration of the wait increasing when measured against a steady clock.
    When the clock is adjusted forwards, this specification can result in the total duration of the wait decreasing when measured against a steady clock.
    — end note]
An implementation returns from such a timeout at any point from the time specified above to the time it would return from a steady-clock relative timeout on the difference between and the time point of the call to the _until function.
Recommended practice: Implementations should decrease the duration of the wait when the clock is adjusted forwards.
[Note 2: 
If the clock is not synchronized with a steady clock, e.g., a CPU time clock, these timeouts can fail to provide useful functionality.
— end note]
The resolution of timing provided by an implementation depends on both operating system and hardware.
The finest resolution provided by an implementation is called the native resolution.
Implementation-provided clocks that are used for these functions meet the Cpp17TrivialClock requirements ([time.clock.req]).
A function that takes an argument which specifies a timeout will throw if, during its execution, a clock, time point, or time duration throws an exception.
Such exceptions are referred to as timeout-related exceptions.
[Note 3: 
Instantiations of clock, time point and duration types supplied by the implementation as specified in [time.clock] do not throw exceptions.
— end note]
297)297)
Implementations for which standard time units are meaningful will typically have a steady clock within their hardware implementation.

32.2.5 Requirements for Cpp17Lockable types [thread.req.lockable]

32.2.5.1 General [thread.req.lockable.general]

An execution agent is an entity such as a thread that may perform work in parallel with other execution agents.
[Note 1: 
Implementations or users can introduce other kinds of agents such as processes or thread-pool tasks.
— end note]
The calling agent is determined by context, e.g., the calling thread that contains the call, and so on.
[Note 2: 
Some lockable objects are “agent oblivious” in that they work for any execution agent model because they do not determine or store the agent's ID (e.g., an ordinary spin lock).
— end note]
The standard library templates unique_lock ([thread.lock.unique]), shared_lock ([thread.lock.shared]), scoped_lock ([thread.lock.scoped]), lock_guard ([thread.lock.guard]), lock, try_lock ([thread.lock.algorithm]), and condition_variable_any ([thread.condition.condvarany]) all operate on user-supplied lockable objects.
The Cpp17BasicLockable requirements, the Cpp17Lockable requirements, the Cpp17TimedLockable requirements, the Cpp17SharedLockable requirements, and the Cpp17SharedTimedLockable requirements list the requirements imposed by these library types in order to acquire or release ownership of a lock by a given execution agent.
[Note 3: 
The nature of any lock ownership and any synchronization it entails are not part of these requirements.
— end note]
A lock on an object m is said to be
  • a non-shared lock if it is acquired by a call to lock, try_lock, try_lock_for, or try_lock_until on m, or
  • a shared lock if it is acquired by a call to lock_shared, try_lock_shared, try_lock_shared_for, or try_lock_shared_until on m.
[Note 4: 
Only the method of lock acquisition is considered; the nature of any lock ownership is not part of these definitions.
— end note]

32.2.5.2 Cpp17BasicLockable requirements [thread.req.lockable.basic]

A type L meets the Cpp17BasicLockable requirements if the following expressions are well-formed and have the specified semantics (m denotes a value of type L).
m.lock()
Effects: Blocks until a lock can be acquired for the current execution agent.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
m.unlock()
Preconditions: The current execution agent holds a non-shared lock on m.
Effects: Releases a non-shared lock on m held by the current execution agent.
Throws: Nothing.

32.2.5.3 Cpp17Lockable requirements [thread.req.lockable.req]

A type L meets the Cpp17Lockable requirements if it meets the Cpp17BasicLockable requirements and the following expressions are well-formed and have the specified semantics (m denotes a value of type L).
m.try_lock()
Effects: Attempts to acquire a lock for the current execution agent without blocking.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.

32.2.5.4 Cpp17TimedLockable requirements [thread.req.lockable.timed]

A type L meets the Cpp17TimedLockable requirements if it meets the Cpp17Lockable requirements and the following expressions are well-formed and have the specified semantics (m denotes a value of type L, rel_time denotes a value of an instantiation of duration, and abs_time denotes a value of an instantiation of time_point).
m.try_lock_for(rel_time)
Effects: Attempts to acquire a lock for the current execution agent within the relative timeout ([thread.req.timing]) specified by rel_time.
The function will not return within the timeout specified by rel_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.
m.try_lock_until(abs_time)
Effects: Attempts to acquire a lock for the current execution agent before the absolute timeout ([thread.req.timing]) specified by abs_time.
The function will not return before the timeout specified by abs_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Return type: bool.
Returns: true if the lock was acquired, otherwise false.

32.2.5.5 Cpp17SharedLockable requirements [thread.req.lockable.shared]

A type L meets the Cpp17SharedLockable requirements if the following expressions are well-formed, have the specified semantics, and the expression m.try_lock_shared() has type bool (m denotes a value of type L):
m.lock_shared()
Effects: Blocks until a lock can be acquired for the current execution agent.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
m.try_lock_shared()
Effects: Attempts to acquire a lock for the current execution agent without blocking.
If an exception is thrown then a lock shall not have been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.
m.unlock_shared()
Preconditions: The current execution agent holds a shared lock on m.
Effects: Releases a shared lock on m held by the current execution agent.
Throws: Nothing.

32.2.5.6 Cpp17SharedTimedLockable requirements [thread.req.lockable.shared.timed]

A type L meets the Cpp17SharedTimedLockable requirements if it meets the Cpp17SharedLockable requirements, and the following expressions are well-formed, have type bool, and have the specified semantics (m denotes a value of type L, rel_time denotes a value of a specialization of chrono​::​duration, and abs_time denotes a value of a specialization of chrono​::​time_point).
m.try_lock_shared_for(rel_time)
Effects: Attempts to acquire a lock for the current execution agent within the relative timeout ([thread.req.timing]) specified by rel_time.
The function will not return within the timeout specified by rel_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.
m.try_lock_shared_until(abs_time)
Effects: Attempts to acquire a lock for the current execution agent before the absolute timeout ([thread.req.timing]) specified by abs_time.
The function will not return before the timeout specified by abs_time unless it has obtained a lock on m for the current execution agent.
If an exception is thrown then a lock has not been acquired for the current execution agent.
Returns: true if the lock was acquired, false otherwise.

32.3 Stop tokens [thread.stoptoken]

32.3.1 Introduction [thread.stoptoken.intro]

Subclause [thread.stoptoken] describes components that can be used to asynchronously request that an operation stops execution in a timely manner, typically because the result is no longer required.
Such a request is called a stop request.
The concepts stoppable-source, stoppable_token, and stoppable-callback-for specify the required syntax and semantics of shared access to a stop state.
Any object modeling stoppable-source, stoppable_token, or stoppable-callback-for that refers to the same stop state is an associated stoppable-source, stoppable_token, or stoppable-callback-for, respectively.
An object of a type that models stoppable_token can be passed to an operation that can either
  • actively poll the token to check if there has been a stop request, or
  • register a callback that will be called in the event that a stop request is made.
A stop request made via an object whose type models stoppable-source will be visible to all associated stoppable_token and stoppable-source objects.
Once a stop request has been made it cannot be withdrawn (a subsequent stop request has no effect).
Callbacks registered via an object whose type models stoppable-callback-for are called when a stop request is first made by any associated stoppable-source object.
The types stop_source and stop_token and the class template stop_callback implement the semantics of shared ownership of a stop state.
The last remaining owner of the stop state automatically releases the resources associated with the stop state.
An object of type inplace_stop_source is the sole owner of its stop state.
An object of type inplace_stop_token or of a specialization of the class template inplace_stop_callback does not participate in ownership of its associated stop state.
[Note 1: 
They are for use when all uses of the associated token and callback objects are known to nest within the lifetime of the inplace_stop_source object.
— end note]

32.3.2 Header <stop_token> synopsis [thread.stoptoken.syn]

namespace std { // [stoptoken.concepts], stop token concepts template<class CallbackFn, class Token, class Initializer = CallbackFn> concept stoppable-callback-for = see below; // exposition only template<class Token> concept stoppable_token = see below; template<class Token> concept unstoppable_token = see below; template<class Source> concept stoppable-source = see below; // exposition only // [stoptoken], class stop_token class stop_token; // [stopsource], class stop_source class stop_source; // no-shared-stop-state indicator struct nostopstate_t { explicit nostopstate_t() = default; }; inline constexpr nostopstate_t nostopstate{}; // [stopcallback], class template stop_callback template<class Callback> class stop_callback; // [stoptoken.never], class never_stop_token class never_stop_token; // [stoptoken.inplace], class inplace_stop_token class inplace_stop_token; // [stopsource.inplace], class inplace_stop_source class inplace_stop_source; // [stopcallback.inplace], class template inplace_stop_callback template<class CallbackFn> class inplace_stop_callback; template<class T, class CallbackFn> using stop_callback_for_t = T::template callback_type<CallbackFn>; }

32.3.3 Stop token concepts [stoptoken.concepts]

The exposition-only stoppable-callback-for concept checks for a callback compatible with a given Token type.
template<class CallbackFn, class Token, class Initializer = CallbackFn> concept stoppable-callback-for = // exposition only invocable<CallbackFn> && constructible_from<CallbackFn, Initializer> && requires { typename stop_callback_for_t<Token, CallbackFn>; } && constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
Let t and u be distinct, valid objects of type Token that reference the same logical stop state; let init be an expression such that same_as<decltype(init), Initializer> is true; and let SCB denote the type stop_callback_for_t<Token, CallbackFn>.
The concept stoppable-callback-for<CallbackFn, Token, Initializer> is modeled only if:
  • The following concepts are modeled:
  • An object of type SCB has an associated callback function of type CallbackFn.
    Let scb be an object of type SCB and let callback_fn denote scb's associated callback function.
    Direct-non-list-initializing scb from arguments t and init shall execute a stoppable callback registration as follows:
    • If t.stop_possible() is true:
      • callback_fn shall be direct-initialized with init.
      • Construction of scb shall only throw exceptions thrown by the initialization of callback_fn from init.
      • The callback invocation std​::​forward<CallbackFn>(callback_fn)() shall be registered with t's associated stop state as follows:
        • If t.stop_requested() evaluates to false at the time of registration, the callback invocation is added to the stop state's list of callbacks such that std​::​forward<CallbackFn>(
          callback_fn)()
          is evaluated if a stop request is made on the stop state.
        • Otherwise, std​::​forward<CallbackFn>(callback_fn)() shall be immediately evaluated on the thread executing scb's constructor, and the callback invocation shall not be added to the list of callback invocations.
        If the callback invocation was added to stop state's list of callbacks, scb shall be associated with the stop state.
    • [Note 1: 
      If t.stop_possible() is false, there is no requirement that the initialization of scb causes the initialization of callback_fn.
      — end note]
  • Destruction of scb shall execute a stoppable callback deregistration as follows (in order):
    • If the constructor of scb did not register a callback invocation with t's stop state, then the stoppable callback deregistration shall have no effect other than destroying callback_fn if it was constructed.
    • Otherwise, the invocation of callback_fn shall be removed from the associated stop state.
    • If callback_fn is concurrently executing on another thread, then the stoppable callback deregistration shall block ([defns.block]) until the invocation of callback_fn returns such that the return from the invocation of callback_fn strongly happens before ([intro.races]) the destruction of callback_fn.
    • If callback_fn is executing on the current thread, then the destructor shall not block waiting for the return from the invocation of callback_fn.
    • A stoppable callback deregistration shall not block on the completion of the invocation of some other callback registered with the same logical stop state.
    • The stoppable callback deregistration shall destroy callback_fn.
The stoppable_token concept checks for the basic interface of a stop token that is copyable and allows polling to see if stop has been requested and also whether a stop request is possible.
The unstoppable_token concept checks for a stoppable_token type that does not allow stopping.
template<template<class> class> struct check-type-alias-exists; // exposition only template<class Token> concept stoppable_token = requires (const Token tok) { typename check-type-alias-exists<Token::template callback_type>; { tok.stop_requested() } noexcept -> same_as<bool>; { tok.stop_possible() } noexcept -> same_as<bool>; { Token(tok) } noexcept; // see implicit expression variations ([concepts.equality]) } && copyable<Token> && equality_comparable<Token>; template<class Token> concept unstoppable_token = stoppable_token<Token> && requires (const Token tok) { requires bool_constant<(!tok.stop_possible())>::value; };
An object whose type models stoppable_token has at most one associated logical stop state.
A stoppable_token object with no associated stop state is said to be disengaged.
Let SP be an evaluation of t.stop_possible() that is false, and let SR be an evaluation of t.stop_requested() that is true.
The type Token models stoppable_token only if:
  • Any evaluation of u.stop_possible() or u.stop_requested() that happens after ([intro.races]) SP is false.
  • Any evaluation of u.stop_possible() or u.stop_requested() that happens after SR is true.
  • For any types CallbackFn and Initializer such that stoppable-callback-for<CallbackFn, Token, Initializer> is satisfied, stoppable-callback-for<CallbackFn, Token, Initializer> is modeled.
  • If t is disengaged, evaluations of t.stop_possible() and t.stop_requested() are false.
  • If t and u reference the same stop state, or if both t and u are disengaged, t == u is true; otherwise, it is false.
An object whose type models the exposition-only stoppable-source concept can be queried whether stop has been requested (stop_requested) and whether stop is possible (stop_possible).
It is a factory for associated stop tokens (get_token), and a stop request can be made on it (request_stop).
It maintains a list of registered stop callback invocations that it executes when a stop request is first made.
template<class Source> concept stoppable-source = // exposition only requires (Source& src, const Source csrc) { // see implicit expression variations ([concepts.equality]) { csrc.get_token() } -> stoppable_token; { csrc.stop_possible() } noexcept -> same_as<bool>; { csrc.stop_requested() } noexcept -> same_as<bool>; { src.request_stop() } -> same_as<bool>; };
An object whose type models stoppable-source has at most one associated logical stop state.
If it has no associated stop state, it is said to be disengaged.
Let s be an object whose type models stoppable-source and that is disengaged.
s.stop_possible() and s.stop_requested() shall be false.
Let t be an object whose type models stoppable-source.
If t is disengaged, t.get_token() shall return a disengaged stop token; otherwise, it shall return a stop token that is associated with the stop state of t.
Calls to the member functions request_stop, stop_requested, and stop_possible and similarly named member functions on associated stoppable_token objects do not introduce data races.
A call to request_stop that returns true synchronizes with a call to stop_requested on an associated stoppable_token or stoppable-source object that returns true.
Registration of a callback synchronizes with the invocation of that callback.
If the stoppable-source is disengaged, request_stop shall have no effect and return false.
Otherwise, it shall execute a stop request operation on the associated stop state.
A stop request operation determines whether the stop state has received a stop request, and if not, makes a stop request.
The determination and making of the stop request shall happen atomically, as-if by a read-modify-write operation ([intro.races]).
If the request was made, the stop state's registered callback invocations shall be synchronously executed.
If an invocation of a callback exits via an exception then terminate shall be invoked ([except.terminate]).
[Note 2: 
No constraint is placed on the order in which the callback invocations are executed.
— end note]
request_stop shall return true if a stop request was made, and false otherwise.
After a call to request_stop either a call to stop_possible shall return false or a call to stop_requested shall return true.
[Note 3: 
A stop request includes notifying all condition variables of type condition_variable_any temporarily registered during an interruptible wait ([thread.condvarany.intwait]).
— end note]

32.3.4 Class stop_token [stoptoken]

32.3.4.1 General [stoptoken.general]

The class stop_token models the concept stoppable_token.
It shares ownership of its stop state, if any, with its associated stop_source object ([stopsource]) and any stop_token objects to which it compares equal.
namespace std { class stop_token { public: template<class CallbackFn> using callback_type = stop_callback<CallbackFn>; stop_token() noexcept = default; // [stoptoken.mem], member functions void swap(stop_token&) noexcept; bool stop_requested() const noexcept; bool stop_possible() const noexcept; bool operator==(const stop_token& rhs) noexcept = default; private: shared_ptr<unspecified> stop-state; // exposition only }; }
stop-state refers to the stop_token's associated stop state.
A stop_token object is disengaged when stop-state is empty.

32.3.4.2 Member functions [stoptoken.mem]

void swap(stop_token& rhs) noexcept;
Effects: Equivalent to: stop-state.swap(rhs.stop-state);
bool stop_requested() const noexcept;
Returns: true if stop-state refers to a stop state that has received a stop request; otherwise, false.
bool stop_possible() const noexcept;
Returns: false if
  • *this is disengaged, or
  • a stop request was not made and there are no associated stop_source objects;
otherwise, true.

32.3.5 Class stop_source [stopsource]

32.3.5.1 General [stopsource.general]

namespace std { class stop_source { public: // [stopsource.cons], constructors, copy, and assignment stop_source(); explicit stop_source(nostopstate_t) noexcept {} // [stopsource.mem], member functions void swap(stop_source&) noexcept; bool request_stop() noexcept; bool operator==(const stop_source& rhs) noexcept = default; private: shared_ptr<unspecified> stop-state; // exposition only }; }
stop-state refers to the stop_source's associated stop state.
A stop_source object is disengaged when stop-state is empty.

32.3.5.2 Constructors, copy, and assignment [stopsource.cons]

stop_source();
Effects: Initializes stop-state with a pointer to a new stop state.
Postconditions: stop_possible() is true and stop_requested() is false.
Throws: bad_alloc if memory cannot be allocated for the stop state.

32.3.5.3 Member functions [stopsource.mem]

void swap(stop_source& rhs) noexcept;
Effects: Equivalent to: stop-state.swap(rhs.stop-state);
stop_token get_token() const noexcept;
Returns: stop_token() if stop_possible() is false; otherwise a new associated stop_token object; i.e., its stop-state member is equal to the stop-state member of *this.
bool stop_possible() const noexcept;
Returns: stop-state != nullptr.
bool stop_requested() const noexcept;
Returns: true if stop-state refers to a stop state that has received a stop request; otherwise, false.
bool request_stop() noexcept;
Effects: Executes a stop request operation ([stoptoken.concepts]) on the associated stop state, if any.

32.3.6 Class template stop_callback [stopcallback]

32.3.6.1 General [stopcallback.general]

namespace std { template<class CallbackFn> class stop_callback { public: using callback_type = CallbackFn; // [stopcallback.cons], constructors and destructor template<class Initializer> explicit stop_callback(const stop_token& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>); template<class Initializer> explicit stop_callback(stop_token&& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>); ~stop_callback(); stop_callback(const stop_callback&) = delete; stop_callback(stop_callback&&) = delete; stop_callback& operator=(const stop_callback&) = delete; stop_callback& operator=(stop_callback&&) = delete; private: CallbackFn callback-fn; // exposition only }; template<class CallbackFn> stop_callback(stop_token, CallbackFn) -> stop_callback<CallbackFn>; }
Mandates: stop_callback is instantiated with an argument for the template parameter CallbackFn that satisfies both invocable and destructible.
Remarks: For a type Initializer, if stoppable-callback-for<CallbackFn, stop_token, Initializer> is satisfied, then stoppable-callback-for<CallbackFn, stop_token, Initializer> is modeled.
The exposition-only callback-fn member is the associated callback function ([stoptoken.concepts]) of stop_callback<
CallbackFn>
objects.

32.3.6.2 Constructors and destructor [stopcallback.cons]

template<class Initializer> explicit stop_callback(const stop_token& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>); template<class Initializer> explicit stop_callback(stop_token&& st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
Constraints: CallbackFn and Initializer satisfy constructible_from<CallbackFn, Initializer>.
Effects: Initializes callback-fn with std​::​forward<Initializer>(init) and executes a stoppable callback registration ([stoptoken.concepts]).
If a callback is registered with st's shared stop state, then *this acquires shared ownership of that stop state.
~stop_callback();
Effects: Executes a stoppable callback deregistration ([stoptoken.concepts]) and releases ownership of the stop state, if any.

32.3.7 Class never_stop_token [stoptoken.never]

The class never_stop_token models the unstoppable_token concept.
It provides a stop token interface, but also provides static information that a stop is never possible nor requested.
namespace std { class never_stop_token { struct callback-type { // exposition only explicit callback-type(never_stop_token, auto&&) noexcept {} }; public: template<class> using callback_type = callback-type; static constexpr bool stop_requested() noexcept { return false; } static constexpr bool stop_possible() noexcept { return false; } bool operator==(const never_stop_token&) const = default; }; }

32.3.8 Class inplace_stop_token [stoptoken.inplace]

32.3.8.1 General [stoptoken.inplace.general]

The class inplace_stop_token models the concept stoppable_token.
It references the stop state of its associated inplace_stop_source object ([stopsource.inplace]), if any.
namespace std { class inplace_stop_token { public: template<class CallbackFn> using callback_type = inplace_stop_callback<CallbackFn>; inplace_stop_token() = default; bool operator==(const inplace_stop_token&) const = default; // [stoptoken.inplace.mem], member functions bool stop_requested() const noexcept; bool stop_possible() const noexcept; void swap(inplace_stop_token&) noexcept; private: const inplace_stop_source* stop-source = nullptr; // exposition only }; }

32.3.8.2 Member functions [stoptoken.inplace.mem]

void swap(inplace_stop_token& rhs) noexcept;
Effects: Exchanges the values of stop-source and rhs.stop-source.
bool stop_requested() const noexcept;
Effects: Equivalent to: return stop-source != nullptr && stop-source->stop_requested();
[Note 1: 
As specified in [basic.life], the behavior of stop_requested is undefined unless the call strongly happens before the start of the destructor of the associated inplace_stop_source object, if any.
— end note]
stop_possible() const noexcept;
Returns: stop-source != nullptr.
[Note 2: 
As specified in [basic.stc.general], the behavior of stop_possible is implementation-defined unless the call strongly happens before the end of the storage duration of the associated inplace_stop_source object, if any.
— end note]

32.3.9 Class inplace_stop_source [stopsource.inplace]

32.3.9.1 General [stopsource.inplace.general]

The class inplace_stop_source models stoppable-source.
namespace std { class inplace_stop_source { public: // [stopsource.inplace.cons], constructors constexpr inplace_stop_source() noexcept; inplace_stop_source(inplace_stop_source&&) = delete; inplace_stop_source(const inplace_stop_source&) = delete; inplace_stop_source& operator=(inplace_stop_source&&) = delete; inplace_stop_source& operator=(const inplace_stop_source&) = delete; ~inplace_stop_source(); // [stopsource.inplace.mem], stop handling constexpr inplace_stop_token get_token() const noexcept; static constexpr bool stop_possible() noexcept { return true; } bool stop_requested() const noexcept; bool request_stop() noexcept; }; }

32.3.9.2 Constructors [stopsource.inplace.cons]

constexpr inplace_stop_source() noexcept;
Effects: Initializes a new stop state inside *this.
Postconditions: stop_requested() is false.

32.3.9.3 Member functions [stopsource.inplace.mem]

constexpr inplace_stop_token get_token() const noexcept;
Returns: A new associated inplace_stop_token object whose stop-source member is equal to this.
bool stop_requested() const noexcept;
Returns: true if the stop state inside *this has received a stop request; otherwise, false.
bool request_stop() noexcept;
Effects: Executes a stop request operation ([stoptoken.concepts]).
Postconditions: stop_requested() is true.

32.3.10 Class template inplace_stop_callback [stopcallback.inplace]

32.3.10.1 General [stopcallback.inplace.general]

namespace std { template<class CallbackFn> class inplace_stop_callback { public: using callback_type = CallbackFn; // [stopcallback.inplace.cons], constructors and destructor template<class Initializer> explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>); ~inplace_stop_callback(); inplace_stop_callback(inplace_stop_callback&&) = delete; inplace_stop_callback(const inplace_stop_callback&) = delete; inplace_stop_callback& operator=(inplace_stop_callback&&) = delete; inplace_stop_callback& operator=(const inplace_stop_callback&) = delete; private: CallbackFn callback-fn; // exposition only }; template<class CallbackFn> inplace_stop_callback(inplace_stop_token, CallbackFn) -> inplace_stop_callback<CallbackFn>; }
Mandates: CallbackFn satisfies both invocable and destructible.
Remarks: For a type Initializer, if stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer> is satisfied, then stoppable-callback-for<CallbackFn, inplace_stop_token, Initializer> is modeled.
For an inplace_stop_callback<CallbackFn> object, the exposition-only callback-fn member is its associated callback function ([stoptoken.concepts]).

32.3.10.2 Constructors and destructor [stopcallback.inplace.cons]

template<class Initializer> explicit inplace_stop_callback(inplace_stop_token st, Initializer&& init) noexcept(is_nothrow_constructible_v<CallbackFn, Initializer>);
Constraints: constructible_from<CallbackFn, Initializer> is satisfied.
Effects: Initializes callback-fn with std​::​forward<Initializer>(init) and executes a stoppable callback registration ([stoptoken.concepts]).
~inplace_stop_callback();
Effects: Executes a stoppable callback deregistration ([stoptoken.concepts]).

32.4 Threads [thread.threads]

32.4.1 General [thread.threads.general]

[thread.threads] describes components that can be used to create and manage threads.
[Note 1: 
These threads are intended to map one-to-one with operating system threads.
— end note]

32.4.2 Header <thread> synopsis [thread.syn]

#include <compare> // see [compare.syn] namespace std { // [thread.thread.class], class thread class thread; void swap(thread& x, thread& y) noexcept; // [thread.jthread.class], class jthread class jthread; // [thread.thread.this], namespace this_thread namespace this_thread { thread::id get_id() noexcept; void yield() noexcept; template<class Clock, class Duration> void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& rel_time); } }

32.4.3 Class thread [thread.thread.class]

32.4.3.1 General [thread.thread.class.general]

The class thread provides a mechanism to create a new thread of execution, to join with a thread (i.e., wait for a thread to complete), and to perform other operations that manage and query the state of a thread.
A thread object uniquely represents a particular thread of execution.
That representation may be transferred to other thread objects in such a way that no two thread objects simultaneously represent the same thread of execution.
A thread of execution is detached when no thread object represents that thread.
Objects of class thread can be in a state that does not represent a thread of execution.
[Note 1: 
A thread object does not represent a thread of execution after default construction, after being moved from, or after a successful call to detach or join.
— end note]
namespace std { class thread { public: // [thread.thread.id], class thread​::​id class id; using native_handle_type = implementation-defined; // see [thread.req.native] // construct/copy/destroy thread() noexcept; template<class F, class... Args> explicit thread(F&& f, Args&&... args); ~thread(); thread(const thread&) = delete; thread(thread&&) noexcept; thread& operator=(const thread&) = delete; thread& operator=(thread&&) noexcept; // [thread.thread.member], members void swap(thread&) noexcept; bool joinable() const noexcept; void join(); void detach(); id get_id() const noexcept; native_handle_type native_handle(); // see [thread.req.native] // static members static unsigned int hardware_concurrency() noexcept; }; }

32.4.3.2 Class thread​::​id [thread.thread.id]

namespace std { class thread::id { public: id() noexcept; }; bool operator==(thread::id x, thread::id y) noexcept; strong_ordering operator<=>(thread::id x, thread::id y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, thread::id id); template<class charT> struct formatter<thread::id, charT>; // hash support template<class T> struct hash; template<> struct hash<thread::id>; }
An object of type thread​::​id provides a unique identifier for each thread of execution and a single distinct value for all thread objects that do not represent a thread of execution ([thread.thread.class]).
Each thread of execution has an associated thread​::​id object that is not equal to the thread​::​id object of any other thread of execution and that is not equal to the thread​::​id object of any thread object that does not represent threads of execution.
The text representation for the character type charT of an object of type thread​::​id is an unspecified sequence of charT such that, for two objects of type thread​::​id x and y, if x == y is true, the thread​::​id objects have the same text representation, and if x != y is true, the thread​::​id objects have distinct text representations.
thread​::​id is a trivially copyable class ([class.prop]).
The library may reuse the value of a thread​::​id of a terminated thread that can no longer be joined.
[Note 1: 
Relational operators allow thread​::​id objects to be used as keys in associative containers.
— end note]
id() noexcept;
Postconditions: The constructed object does not represent a thread of execution.
bool operator==(thread::id x, thread::id y) noexcept;
Returns: true only if x and y represent the same thread of execution or neither x nor y represents a thread of execution.
strong_ordering operator<=>(thread::id x, thread::id y) noexcept;
Let P(x, y) be an unspecified total ordering over thread​::​id as described in [alg.sorting].
Returns: strong_ordering​::​less if P(x, y) is true.
Otherwise, strong_ordering​::​greater if P(y, x) is true.
Otherwise, strong_ordering​::​equal.
template<class charT, class traits> basic_ostream<charT, traits>& operator<< (basic_ostream<charT, traits>& out, thread::id id);
Effects: Inserts the text representation for charT of id into out.
Returns: out.
template<class charT> struct formatter<thread::id, charT>;
formatter<thread​::​id, charT> interprets format-spec as a thread-id-format-spec.
The syntax of format specifications is as follows:
thread-id-format-spec:
fill-and-align width
[Note 2: 
The productions fill-and-align and width are described in [format.string.std].
— end note]
If the align option is omitted it defaults to >.
A thread​::​id object is formatted by writing its text representation for charT to the output with additional padding and adjustments as specified by the format specifiers.
template<> struct hash<thread::id>;
The specialization is enabled ([unord.hash]).

32.4.3.3 Constructors [thread.thread.constr]

thread() noexcept;
Effects: The object does not represent a thread of execution.
Postconditions: get_id() == id().
template<class F, class... Args> explicit thread(F&& f, Args&&... args);
Constraints: remove_cvref_t<F> is not the same type as thread.
Mandates: The following are all true:
  • is_constructible_v<decay_t<F>, F>,
  • (is_constructible_v<decay_t<Args>, Args> && ...), and
  • is_invocable_v<decay_t<F>, decay_t<Args>...>.
Effects: The new thread of execution executes invoke(auto(std::forward<F>(f)), // for invoke, see [func.invoke] auto(std::forward<Args>(args))...) with the values produced by auto being materialized ([conv.rval]) in the constructing thread.
Any return value from this invocation is ignored.
[Note 1: 
This implies that any exceptions not thrown from the invocation of the copy of f will be thrown in the constructing thread, not the new thread.
— end note]
If the invocation of invoke terminates with an uncaught exception, terminate is invoked ([except.terminate]).
Synchronization: The completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.
Postconditions: get_id() != id().
*this represents the newly started thread.
Throws: system_error if unable to start the new thread.
Error conditions:
  • resource_unavailable_try_again — the system lacked the necessary resources to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.
thread(thread&& x) noexcept;
Postconditions: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the start of construction.

32.4.3.4 Destructor [thread.thread.destr]

~thread();
Effects: If joinable(), invokes terminate ([except.terminate]).
Otherwise, has no effects.
[Note 1: 
Either implicitly detaching or joining a joinable() thread in its destructor can result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is thrown.
These bugs can be avoided by ensuring that the destructor is never executed while the thread is still joinable.
— end note]

32.4.3.5 Assignment [thread.thread.assign]

thread& operator=(thread&& x) noexcept;
Effects: If joinable(), invokes terminate ([except.terminate]).
Otherwise, assigns the state of x to *this and sets x to a default constructed state.
Postconditions: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the assignment.
Returns: *this.

32.4.3.6 Members [thread.thread.member]

void swap(thread& x) noexcept;
Effects: Swaps the state of *this and x.
bool joinable() const noexcept;
Returns: get_id() != id().
void join();
Effects: Blocks until the thread represented by *this has completed.
Synchronization: The completion of the thread represented by *this synchronizes with ([intro.multithread]) the corresponding successful join() return.
[Note 1: 
Operations on *this are not synchronized.
— end note]
Postconditions: The thread represented by *this has completed.
get_id() == id().
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • resource_deadlock_would_occur — if deadlock is detected or get_id() == this_thread​::​​get_id().
  • no_such_process — if the thread is not valid.
  • invalid_argument — if the thread is not joinable.
void detach();
Effects: The thread represented by *this continues execution without the calling thread blocking.
When detach() returns, *this no longer represents the possibly continuing thread of execution.
When the thread previously represented by *this ends execution, the implementation releases any owned resources.
Postconditions: get_id() == id().
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • no_such_process — if the thread is not valid.
  • invalid_argument — if the thread is not joinable.
id get_id() const noexcept;
Returns: A default constructed id object if *this does not represent a thread, otherwise this_thread​::​get_id() for the thread of execution represented by *this.

32.4.3.7 Static members [thread.thread.static]

unsigned hardware_concurrency() noexcept;
Returns: The number of hardware thread contexts.
[Note 1: 
This value should only be considered to be a hint.
— end note]
If this value is not computable or well-defined, an implementation should return 0.

32.4.3.8 Specialized algorithms [thread.thread.algorithm]

void swap(thread& x, thread& y) noexcept;
Effects: As if by x.swap(y).

32.4.4 Class jthread [thread.jthread.class]

32.4.4.1 General [thread.jthread.class.general]

The class jthread provides a mechanism to create a new thread of execution.
The functionality is the same as for class thread ([thread.thread.class]) with the additional abilities to provide a stop_token ([thread.stoptoken]) to the new thread of execution, make stop requests, and automatically join.
namespace std { class jthread { public: // types using id = thread::id; using native_handle_type = thread::native_handle_type; // [thread.jthread.cons], constructors, move, and assignment jthread() noexcept; template<class F, class... Args> explicit jthread(F&& f, Args&&... args); ~jthread(); jthread(const jthread&) = delete; jthread(jthread&&) noexcept; jthread& operator=(const jthread&) = delete; jthread& operator=(jthread&&) noexcept; // [thread.jthread.mem], members void swap(jthread&) noexcept; bool joinable() const noexcept; void join(); void detach(); id get_id() const noexcept; native_handle_type native_handle(); // see [thread.req.native] // [thread.jthread.stop], stop token handling stop_source get_stop_source() noexcept; stop_token get_stop_token() const noexcept; bool request_stop() noexcept; // [thread.jthread.special], specialized algorithms friend void swap(jthread& lhs, jthread& rhs) noexcept; // [thread.jthread.static], static members static unsigned int hardware_concurrency() noexcept; private: stop_source ssource; // exposition only }; }

32.4.4.2 Constructors, move, and assignment [thread.jthread.cons]

jthread() noexcept;
Effects: Constructs a jthread object that does not represent a thread of execution.
Postconditions: get_id() == id() is true and ssource.stop_possible() is false.
template<class F, class... Args> explicit jthread(F&& f, Args&&... args);
Constraints: remove_cvref_t<F> is not the same type as jthread.
Mandates: The following are all true:
  • is_constructible_v<decay_t<F>, F>,
  • (is_constructible_v<decay_t<Args>, Args> && ...), and
  • is_invocable_v<decay_t<F>, decay_t<Args>...> ||
    is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>.
Effects: Initializes ssource.
The new thread of execution executes invoke(auto(std::forward<F>(f)), get_stop_token(), // for invoke, see [func.invoke] auto(std::forward<Args>(args))...) if that expression is well-formed, otherwise invoke(auto(std::forward<F>(f)), auto(std::forward<Args>(args))...) with the values produced by auto being materialized ([conv.rval]) in the constructing thread.
Any return value from this invocation is ignored.
[Note 1: 
This implies that any exceptions not thrown from the invocation of the copy of f will be thrown in the constructing thread, not the new thread.
— end note]
If the invoke expression exits via an exception, terminate is called.
Synchronization: The completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.
Postconditions: get_id() != id() is true and ssource.stop_possible() is true and *this represents the newly started thread.
[Note 2: 
The calling thread can make a stop request only once, because it cannot replace this stop token.
— end note]
Throws: system_error if unable to start the new thread.
Error conditions:
  • resource_unavailable_try_again — the system lacked the necessary resources to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.
jthread(jthread&& x) noexcept;
Postconditions: x.get_id() == id() and get_id() returns the value of x.get_id() prior to the start of construction.
ssource has the value of x.ssource prior to the start of construction and x.ssource.stop_possible() is false.
~jthread();
Effects: If joinable() is true, calls request_stop() and then join().
[Note 3: 
Operations on *this are not synchronized.
— end note]
jthread& operator=(jthread&& x) noexcept;
Effects: If &x == this is true, there are no effects.
Otherwise, if joinable() is true, calls request_stop() and then join(), then assigns the state of x to *this and sets x to a default constructed state.
Postconditions: get_id() returns the value of x.get_id() prior to the assignment.
ssource has the value of x.ssource prior to the assignment.
Returns: *this.

32.4.4.3 Members [thread.jthread.mem]

void swap(jthread& x) noexcept;
Effects: Exchanges the values of *this and x.
bool joinable() const noexcept;
Returns: get_id() != id().
void join();
Effects: Blocks until the thread represented by *this has completed.
Synchronization: The completion of the thread represented by *this synchronizes with ([intro.multithread]) the corresponding successful join() return.
[Note 1: 
Operations on *this are not synchronized.
— end note]
Postconditions: The thread represented by *this has completed.
get_id() == id().
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • resource_deadlock_would_occur — if deadlock is detected or get_id() == this_thread​::​​get_id().
  • no_such_process — if the thread is not valid.
  • invalid_argument — if the thread is not joinable.
void detach();
Effects: The thread represented by *this continues execution without the calling thread blocking.
When detach() returns, *this no longer represents the possibly continuing thread of execution.
When the thread previously represented by *this ends execution, the implementation releases any owned resources.
Postconditions: get_id() == id().
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • no_such_process — if the thread is not valid.
  • invalid_argument — if the thread is not joinable.
id get_id() const noexcept;
Returns: A default constructed id object if *this does not represent a thread, otherwise this_thread​::​get_id() for the thread of execution represented by *this.

32.4.4.4 Stop token handling [thread.jthread.stop]

stop_source get_stop_source() noexcept;
Effects: Equivalent to: return ssource;
stop_token get_stop_token() const noexcept;
Effects: Equivalent to: return ssource.get_token();
bool request_stop() noexcept;
Effects: Equivalent to: return ssource.request_stop();

32.4.4.5 Specialized algorithms [thread.jthread.special]

friend void swap(jthread& x, jthread& y) noexcept;
Effects: Equivalent to: x.swap(y).

32.4.4.6 Static members [thread.jthread.static]

static unsigned int hardware_concurrency() noexcept;
Returns: thread​::​hardware_concurrency().

32.4.5 Namespace this_thread [thread.thread.this]

namespace std::this_thread { thread::id get_id() noexcept; void yield() noexcept; template<class Clock, class Duration> void sleep_until(const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& rel_time); }
thread::id this_thread::get_id() noexcept;
Returns: An object of type thread​::​id that uniquely identifies the current thread of execution.
Every invocation from this thread of execution returns the same value.
The object returned does not compare equal to a default-constructed thread​::​id.
void this_thread::yield() noexcept;
Effects: Offers the implementation the opportunity to reschedule.
Synchronization: None.
template<class Clock, class Duration> void sleep_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: Blocks the calling thread for the absolute timeout ([thread.req.timing]) specified by abs_time.
Synchronization: None.
Throws: Timeout-related exceptions ([thread.req.timing]).
template<class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& rel_time);
Effects: Blocks the calling thread for the relative timeout ([thread.req.timing]) specified by rel_time.
Synchronization: None.
Throws: Timeout-related exceptions ([thread.req.timing]).

32.5 Atomic operations [atomics]

32.5.1 General [atomics.general]

Subclause [atomics] describes components for fine-grained atomic access.
This access is provided via operations on atomic objects.

32.5.2 Header <atomic> synopsis [atomics.syn]

namespace std { // [atomics.order], order and consistency enum class memory_order : unspecified; // freestanding inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; // freestanding inline constexpr memory_order memory_order_consume = memory_order::consume; // freestanding inline constexpr memory_order memory_order_acquire = memory_order::acquire; // freestanding inline constexpr memory_order memory_order_release = memory_order::release; // freestanding inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; // freestanding inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; // freestanding template<class T> constexpr T kill_dependency(T y) noexcept; // freestanding } // [atomics.lockfree], lock-free property #define ATOMIC_BOOL_LOCK_FREE unspecified // freestanding #define ATOMIC_CHAR_LOCK_FREE unspecified // freestanding #define ATOMIC_CHAR8_T_LOCK_FREE unspecified // freestanding #define ATOMIC_CHAR16_T_LOCK_FREE unspecified // freestanding #define ATOMIC_CHAR32_T_LOCK_FREE unspecified // freestanding #define ATOMIC_WCHAR_T_LOCK_FREE unspecified // freestanding #define ATOMIC_SHORT_LOCK_FREE unspecified // freestanding #define ATOMIC_INT_LOCK_FREE unspecified // freestanding #define ATOMIC_LONG_LOCK_FREE unspecified // freestanding #define ATOMIC_LLONG_LOCK_FREE unspecified // freestanding #define ATOMIC_POINTER_LOCK_FREE unspecified // freestanding namespace std { // [atomics.ref.generic], class template atomic_ref template<class T> struct atomic_ref; // freestanding // [atomics.ref.pointer], partial specialization for pointers template<class T> struct atomic_ref<T*>; // freestanding // [atomics.types.generic], class template atomic template<class T> struct atomic; // freestanding // [atomics.types.pointer], partial specialization for pointers template<class T> struct atomic<T*>; // freestanding // [atomics.nonmembers], non-member functions template<class T> bool atomic_is_lock_free(const volatile atomic<T>*) noexcept; // freestanding template<class T> bool atomic_is_lock_free(const atomic<T>*) noexcept; // freestanding template<class T> void atomic_store(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr void atomic_store(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> void atomic_store_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr void atomic_store_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> T atomic_load(const volatile atomic<T>*) noexcept; // freestanding template<class T> constexpr T atomic_load(const atomic<T>*) noexcept; // freestanding template<class T> T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept; // freestanding template<class T> constexpr T atomic_load_explicit(const atomic<T>*, memory_order) noexcept; // freestanding template<class T> T atomic_exchange(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_exchange(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_exchange_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_exchange_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> bool atomic_compare_exchange_weak(volatile atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type) noexcept; template<class T> constexpr bool atomic_compare_exchange_weak(atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type) noexcept; template<class T> bool atomic_compare_exchange_strong(volatile atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type) noexcept; template<class T> constexpr bool atomic_compare_exchange_strong(atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type) noexcept; template<class T> bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type, memory_order, memory_order) noexcept; template<class T> constexpr bool atomic_compare_exchange_weak_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type, memory_order, memory_order) noexcept; template<class T> bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type, memory_order, memory_order) noexcept; template<class T> constexpr bool atomic_compare_exchange_strong_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type*, typename atomic<T>::value_type, memory_order, memory_order) noexcept; template<class T> T atomic_fetch_add(volatile atomic<T>*, // freestanding typename atomic<T>::difference_type) noexcept; template<class T> constexpr T atomic_fetch_add(atomic<T>*, // freestanding typename atomic<T>::difference_type) noexcept; template<class T> T atomic_fetch_add_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::difference_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_add_explicit(atomic<T>*, // freestanding typename atomic<T>::difference_type, memory_order) noexcept; template<class T> T atomic_fetch_sub(volatile atomic<T>*, // freestanding typename atomic<T>::difference_type) noexcept; template<class T> constexpr T atomic_fetch_sub(atomic<T>*, // freestanding typename atomic<T>::difference_type) noexcept; template<class T> T atomic_fetch_sub_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::difference_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_sub_explicit(atomic<T>*, // freestanding typename atomic<T>::difference_type, memory_order) noexcept; template<class T> T atomic_fetch_and(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_fetch_and(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_fetch_and_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_and_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> T atomic_fetch_or(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_fetch_or(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_fetch_or_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_or_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> T atomic_fetch_xor(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_fetch_xor(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_fetch_xor_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_xor_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> T atomic_fetch_max(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_fetch_max(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_fetch_max_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_max_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> T atomic_fetch_min(volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr T atomic_fetch_min(atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> T atomic_fetch_min_explicit(volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr T atomic_fetch_min_explicit(atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> void atomic_wait(const volatile atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> constexpr void atomic_wait(const atomic<T>*, // freestanding typename atomic<T>::value_type) noexcept; template<class T> void atomic_wait_explicit(const volatile atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> constexpr void atomic_wait_explicit(const atomic<T>*, // freestanding typename atomic<T>::value_type, memory_order) noexcept; template<class T> void atomic_notify_one(volatile atomic<T>*) noexcept; // freestanding template<class T> constexpr void atomic_notify_one(atomic<T>*) noexcept; // freestanding template<class T> void atomic_notify_all(volatile atomic<T>*) noexcept; // freestanding template<class T> constexpr void atomic_notify_all(atomic<T>*) noexcept; // freestanding // [atomics.alias], type aliases using atomic_bool = atomic<bool>; // freestanding using atomic_char = atomic<char>; // freestanding using atomic_schar = atomic<signed char>; // freestanding using atomic_uchar = atomic<unsigned char>; // freestanding using atomic_short = atomic<short>; // freestanding using atomic_ushort = atomic<unsigned short>; // freestanding using atomic_int = atomic<int>; // freestanding using atomic_uint = atomic<unsigned int>; // freestanding using atomic_long = atomic<long>; // freestanding using atomic_ulong = atomic<unsigned long>; // freestanding using atomic_llong = atomic<long long>; // freestanding using atomic_ullong = atomic<unsigned long long>; // freestanding using atomic_char8_t = atomic<char8_t>; // freestanding using atomic_char16_t = atomic<char16_t>; // freestanding using atomic_char32_t = atomic<char32_t>; // freestanding using atomic_wchar_t = atomic<wchar_t>; // freestanding using atomic_int8_t = atomic<int8_t>; // freestanding using atomic_uint8_t = atomic<uint8_t>; // freestanding using atomic_int16_t = atomic<int16_t>; // freestanding using atomic_uint16_t = atomic<uint16_t>; // freestanding using atomic_int32_t = atomic<int32_t>; // freestanding using atomic_uint32_t = atomic<uint32_t>; // freestanding using atomic_int64_t = atomic<int64_t>; // freestanding using atomic_uint64_t = atomic<uint64_t>; // freestanding using atomic_int_least8_t = atomic<int_least8_t>; // freestanding using atomic_uint_least8_t = atomic<uint_least8_t>; // freestanding using atomic_int_least16_t = atomic<int_least16_t>; // freestanding using atomic_uint_least16_t = atomic<uint_least16_t>; // freestanding using atomic_int_least32_t = atomic<int_least32_t>; // freestanding using atomic_uint_least32_t = atomic<uint_least32_t>; // freestanding using atomic_int_least64_t = atomic<int_least64_t>; // freestanding using atomic_uint_least64_t = atomic<uint_least64_t>; // freestanding using atomic_int_fast8_t = atomic<int_fast8_t>; // freestanding using atomic_uint_fast8_t = atomic<uint_fast8_t>; // freestanding using atomic_int_fast16_t = atomic<int_fast16_t>; // freestanding using atomic_uint_fast16_t = atomic<uint_fast16_t>; // freestanding using atomic_int_fast32_t = atomic<int_fast32_t>; // freestanding using atomic_uint_fast32_t = atomic<uint_fast32_t>; // freestanding using atomic_int_fast64_t = atomic<int_fast64_t>; // freestanding using atomic_uint_fast64_t = atomic<uint_fast64_t>; // freestanding using atomic_intptr_t = atomic<intptr_t>; // freestanding using atomic_uintptr_t = atomic<uintptr_t>; // freestanding using atomic_size_t = atomic<size_t>; // freestanding using atomic_ptrdiff_t = atomic<ptrdiff_t>; // freestanding using atomic_intmax_t = atomic<intmax_t>; // freestanding using atomic_uintmax_t = atomic<uintmax_t>; // freestanding using atomic_signed_lock_free = see below; using atomic_unsigned_lock_free = see below; // [atomics.flag], flag type and operations struct atomic_flag; // freestanding bool atomic_flag_test(const volatile atomic_flag*) noexcept; // freestanding constexpr bool atomic_flag_test(const atomic_flag*) noexcept; // freestanding bool atomic_flag_test_explicit(const volatile atomic_flag*, // freestanding memory_order) noexcept; constexpr bool atomic_flag_test_explicit(const atomic_flag*, // freestanding memory_order) noexcept; bool atomic_flag_test_and_set(volatile atomic_flag*) noexcept; // freestanding constexpr bool atomic_flag_test_and_set(atomic_flag*) noexcept; // freestanding bool atomic_flag_test_and_set_explicit(volatile atomic_flag*, // freestanding memory_order) noexcept; constexpr bool atomic_flag_test_and_set_explicit(atomic_flag*, // freestanding memory_order) noexcept; void atomic_flag_clear(volatile atomic_flag*) noexcept; // freestanding constexpr void atomic_flag_clear(atomic_flag*) noexcept; // freestanding void atomic_flag_clear_explicit(volatile atomic_flag*, memory_order) noexcept; // freestanding constexpr void atomic_flag_clear_explicit(atomic_flag*, memory_order) noexcept; // freestanding void atomic_flag_wait(const volatile atomic_flag*, bool) noexcept; // freestanding constexpr void atomic_flag_wait(const atomic_flag*, bool) noexcept; // freestanding void atomic_flag_wait_explicit(const volatile atomic_flag*, // freestanding bool, memory_order) noexcept; constexpr void atomic_flag_wait_explicit(const atomic_flag*, // freestanding bool, memory_order) noexcept; void atomic_flag_notify_one(volatile atomic_flag*) noexcept; // freestanding constexpr void atomic_flag_notify_one(atomic_flag*) noexcept; // freestanding void atomic_flag_notify_all(volatile atomic_flag*) noexcept; // freestanding constexpr void atomic_flag_notify_all(atomic_flag*) noexcept; // freestanding #define ATOMIC_FLAG_INIT see below // freestanding // [atomics.fences], fences extern "C" constexpr void atomic_thread_fence(memory_order) noexcept; // freestanding extern "C" constexpr void atomic_signal_fence(memory_order) noexcept; // freestanding }

32.5.3 Type aliases [atomics.alias]

The type aliases atomic_intN_t, atomic_uintN_t, atomic_intptr_t, and atomic_uintptr_t are defined if and only if intN_t, uintN_t, intptr_t, and uintptr_t are defined, respectively.
The type aliases atomic_signed_lock_free and atomic_unsigned_lock_free name specializations of atomic whose template arguments are integral types, respectively signed and unsigned, and whose is_always_lock_free property is true.
[Note 1: 
These aliases are optional in freestanding implementations ([compliance]).
— end note]
Implementations should choose for these aliases the integral specializations of atomic for which the atomic waiting and notifying operations ([atomics.wait]) are most efficient.

32.5.4 Order and consistency [atomics.order]

namespace std { enum class memory_order : unspecified { relaxed, consume, acquire, release, acq_rel, seq_cst }; }
The enumeration memory_order specifies the detailed regular (non-atomic) memory synchronization order as defined in [intro.multithread] and may provide for operation ordering.
Its enumerated values and their meanings are as follows:
  • memory_order​::​relaxed: no operation orders memory.
  • memory_order​::​release, memory_order​::​acq_rel, and memory_order​::​seq_cst: a store operation performs a release operation on the affected memory location.
  • memory_order​::​consume: a load operation performs a consume operation on the affected memory location.
    [Note 1: 
    Prefer memory_order​::​acquire, which provides stronger guarantees than memory_order​::​consume.
    Implementations have found it infeasible to provide performance better than that of memory_order​::​acquire.
    Specification revisions are under consideration.
    — end note]
  • memory_order​::​acquire, memory_order​::​acq_rel, and memory_order​::​seq_cst: a load operation performs an acquire operation on the affected memory location.
[Note 2: 
Atomic operations specifying 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]
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.
An atomic operation A on some atomic object M is coherence-ordered before another atomic operation B on M if
  • A is a modification, and B reads the value stored by A, or
  • A precedes B in the modification order of M, or
  • 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
  • there exists an atomic modification X of M such that A is coherence-ordered before X and X is coherence-ordered before B.
There is a single total order S on all memory_order​::​seq_cst operations, including fences, that satisfies the following constraints.
First, if A and B are 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:
  • if A and B are both memory_order​::​seq_cst operations, then A precedes B in S; and
  • if A is a memory_order​::​seq_cst operation and B happens before a memory_order​::​seq_cst fence Y, then A precedes Y in S; and
  • if a memory_order​::​seq_cst fence X happens before A and B is a memory_order​::​seq_cst operation, then X precedes B in S; and
  • if a memory_order​::​seq_cst fence X happens before A and B happens before a memory_order​::​seq_cst fence Y, then X precedes Y in S.
[Note 3: 
This definition ensures that S is consistent with the modification order of any atomic object M.
It also ensures that a 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-memory_order​::​seq_cst modification of M that does not happen before any modification of M that precedes A in S.
— end note]
[Note 4: 
We do not require that S be consistent with “happens before” ([intro.races]).
This allows more efficient implementation of memory_order​::​acquire and memory_order​::​release on some machine architectures.
It can produce surprising results when these are mixed with memory_order​::​seq_cst accesses.
— end note]
[Note 5: 
memory_order​::​seq_cst ensures sequential consistency only for a program that is free of data races and uses exclusively memory_order​::​seq_cst atomic operations.
Any use of weaker ordering will invalidate this guarantee unless extreme care is used.
In many cases, memory_order​::​seq_cst atomic operations are reorderable with respect to other atomic operations performed by the same thread.
— end note]
Implementations should ensure that no “out-of-thin-air” values are computed that circularly depend on their own computation.
[Note 6: 
For example, with x and y initially zero, // Thread 1: r1 = y.load(memory_order::relaxed); x.store(r1, memory_order::relaxed);
// Thread 2: r2 = x.load(memory_order::relaxed); y.store(r2, memory_order::relaxed); this recommendation discourages producing r1 == r2 == 42, since the store of 42 to y is only possible if the store to x stores 42, which circularly depends on the store to y storing 42.
Note that without this restriction, such an execution is possible.
— end note]
[Note 7: 
The recommendation similarly disallows r1 == r2 == 42 in the following example, with x and y again initially zero:
// Thread 1: r1 = x.load(memory_order::relaxed); if (r1 == 42) y.store(42, memory_order::relaxed);
// Thread 2: r2 = y.load(memory_order::relaxed); if (r2 == 42) x.store(42, memory_order::relaxed); — end note]
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.
Recommended practice: The implementation should make atomic stores visible to atomic loads, and atomic loads should observe atomic stores, within a reasonable amount of time.
template<class T> constexpr T kill_dependency(T y) noexcept;
Effects: The argument does not carry a dependency to the return value ([intro.multithread]).
Returns: y.

32.5.5 Lock-free property [atomics.lockfree]

#define ATOMIC_BOOL_LOCK_FREE unspecified #define ATOMIC_CHAR_LOCK_FREE unspecified #define ATOMIC_CHAR8_T_LOCK_FREE unspecified #define ATOMIC_CHAR16_T_LOCK_FREE unspecified #define ATOMIC_CHAR32_T_LOCK_FREE unspecified #define ATOMIC_WCHAR_T_LOCK_FREE unspecified #define ATOMIC_SHORT_LOCK_FREE unspecified #define ATOMIC_INT_LOCK_FREE unspecified #define ATOMIC_LONG_LOCK_FREE unspecified #define ATOMIC_LLONG_LOCK_FREE unspecified #define ATOMIC_POINTER_LOCK_FREE unspecified
The 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 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.
On a hosted implementation ([compliance]), at least one signed integral specialization of the atomic template, along with the specialization for the corresponding unsigned type ([basic.fundamental]), is always lock-free.
The functions atomic<T>​::​is_lock_free and atomic_is_lock_free ([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.
Atomic operations that are not lock-free are considered to potentially block ([intro.progress]).
Recommended practice: Operations that are lock-free should also be address-free.298
The implementation of these operations should not depend on any per-process state.
[Note 1: 
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]
298)298)
That is, atomic operations on the same memory location via two different addresses will communicate atomically.

32.5.6 Waiting and notifying [atomics.wait]

Atomic waiting operations and atomic notifying operations 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.
[Note 1: 
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]
[Note 2: 
The following functions are atomic waiting operations:
  • atomic<T>​::​wait,
  • atomic_flag​::​wait,
  • atomic_wait and atomic_wait_explicit,
  • atomic_flag_wait and atomic_flag_wait_explicit, and
  • atomic_ref<T>​::​wait.
— end note]
[Note 3: 
The following functions are atomic notifying operations:
  • atomic<T>​::​notify_one and atomic<T>​::​notify_all,
  • atomic_flag​::​notify_one and atomic_flag​::​notify_all,
  • atomic_notify_one and atomic_notify_all,
  • atomic_flag_notify_one and atomic_flag_notify_all, and
  • atomic_ref<T>​::​notify_one and atomic_ref<T>​::​notify_all.
— end note]
A call to an atomic waiting operation on an atomic object M is eligible to be unblocked by a call to an atomic notifying operation on M if there exist side effects X and Y on M such that:
  • the atomic waiting operation has blocked after observing the result of X,
  • X precedes Y in the modification order of M, and
  • Y happens before the call to the atomic notifying operation.

32.5.7 Class template atomic_ref [atomics.ref.generic]

32.5.7.1 General [atomics.ref.generic.general]

namespace std { template<class T> struct atomic_ref { private: T* ptr; // exposition only public: using value_type = remove_cv_t<T>; static constexpr size_t required_alignment = implementation-defined; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(T&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr T* address() const noexcept; }; }
An atomic_ref object applies atomic operations ([atomics.general]) to the object referenced by *ptr such that, for the lifetime ([basic.life]) of the atomic_ref object, the object referenced by *ptr is an atomic object ([intro.races]).
The program is ill-formed if is_trivially_copyable_v<T> is false.
The lifetime ([basic.life]) of an object referenced by *ptr shall exceed the lifetime of all atomic_refs that reference the object.
While any atomic_ref instances exist that reference the *ptr object, all accesses to that object shall exclusively occur through those atomic_ref instances.
No subobject of the object referenced by atomic_ref shall be concurrently referenced by any other atomic_ref object.
Atomic operations applied to an object through a referencing atomic_ref are atomic with respect to atomic operations applied through any other atomic_ref referencing the same object.
[Note 1: 
Atomic operations or the 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]
The program is ill-formed if is_always_lock_free is false and is_volatile_v<T> is true.

32.5.7.2 Operations [atomics.ref.ops]

static constexpr size_t required_alignment;
The alignment required for an object to be referenced by an atomic reference, which is at least alignof(T).
[Note 1: 
Hardware could require an object referenced by an atomic_ref to have stricter alignment ([basic.align]) than other objects of type T.
Further, whether operations on an atomic_ref are lock-free could depend on the alignment of the referenced object.
For example, lock-free operations on std​::​complex<double> could be supported only if aligned to 2*alignof(double).
— end note]
static constexpr bool is_always_lock_free;
The static data member is_always_lock_free is true if the atomic_ref type's operations are always lock-free, and false otherwise.
bool is_lock_free() const noexcept;
Returns: true if operations on all objects of the type atomic_ref<T> are lock-free, false otherwise.
constexpr atomic_ref(T& obj);
Preconditions: The referenced object is aligned to required_alignment.
Postconditions: *this references obj.
Throws: Nothing.
constexpr atomic_ref(const atomic_ref& ref) noexcept;
Postconditions: *this references the object referenced by ref.
constexpr void store(value_type desired, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<T> is false.
Preconditions: order is memory_order​::​relaxed, memory_order​::​release, or memory_order​::​seq_cst.
Effects: Atomically replaces the value referenced by *ptr with the value of desired.
Memory is affected according to the value of order.
constexpr value_type operator=(value_type desired) const noexcept;
Constraints: is_const_v<T> is false.
Effects: Equivalent to: store(desired); return desired;
constexpr value_type load(memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns the value referenced by *ptr.
constexpr operator value_type() const noexcept;
Effects: Equivalent to: return load();
constexpr value_type exchange(value_type desired, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<T> is false.
Effects: Atomically replaces the value referenced by *ptr with desired.
Memory is affected according to the value of order.
This operation is an atomic read-modify-write operation ([intro.multithread]).
Returns: Atomically returns the value referenced by *ptr immediately before the effects.
constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success, memory_order failure) const noexcept; constexpr bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<T> is false.
Preconditions: failure is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​acquire, or memory_order​::​seq_cst.
Effects: Retrieves the value in expected.
It then atomically compares the value representation of the value referenced by *ptr for equality with that previously retrieved from expected, and if true, replaces the value referenced by *ptr with that in desired.
If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure.
When only one memory_order argument is supplied, the value of success is order, and the value of failure is order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
If and only if the comparison is false then, after the atomic operation, the value in expected is replaced by the value read from the value referenced by *ptr during the atomic comparison.
If the operation returns true, these operations are atomic read-modify-write operations ([intro.races]) on the value referenced by *ptr.
Otherwise, these operations are atomic load operations on that memory.
Returns: The result of the comparison.
Remarks: A weak compare-and-exchange operation may fail spuriously.
That is, even when the contents of memory referred to by expected and ptr are equal, it may return false and store back to expected the same memory contents that were originally there.
[Note 2: 
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]
constexpr void wait(value_type old, memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Repeatedly performs the following steps, in order:
  • Evaluates load(order) and compares its value representation for equality against that of old.
  • If they compare unequal, returns.
  • Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.
Remarks: This function is an atomic waiting operation ([atomics.wait]) on atomic object *ptr.
constexpr void notify_one() const noexcept;
Constraints: is_const_v<T> is false.
Effects: Unblocks the execution of at least one atomic waiting operation on *ptr that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.
Remarks: This function is an atomic notifying operation ([atomics.wait]) on atomic object *ptr.
constexpr void notify_all() const noexcept;
Constraints: is_const_v<T> is false.
Effects: Unblocks the execution of all atomic waiting operations on *ptr that are eligible to be unblocked ([atomics.wait]) by this call.
Remarks: This function is an atomic notifying operation ([atomics.wait]) on atomic object *ptr.
constexpr T* address() const noexcept;
Returns: ptr.

32.5.7.3 Specializations for integral types [atomics.ref.int]

There are specializations of the atomic_ref class template for all integral types except cv bool.
For each such type integral-type, the specialization atomic_ref<integral-type> provides additional atomic operations appropriate to integral types.
[Note 1: 
The specialization atomic_ref<bool> uses the primary template ([atomics.ref.generic]).
— end note]
The program is ill-formed if is_always_lock_free is false and is_volatile_v<T> is true.
namespace std { template<> struct atomic_ref<integral-type> { private: integral-type* ptr; // exposition only public: using value_type = remove_cv_t<integral-type>; using difference_type = value_type; static constexpr size_t required_alignment = implementation-defined; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(integral-type&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_and(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_or(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_xor(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator++(int) const noexcept; constexpr value_type operator--(int) const noexcept; constexpr value_type operator++() const noexcept; constexpr value_type operator--() const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr value_type operator&=(value_type) const noexcept; constexpr value_type operator|=(value_type) const noexcept; constexpr value_type operator^=(value_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr integral-type* address() const noexcept; }; }
Descriptions are provided below only for members that differ from the primary template.
The following operations perform arithmetic computations.
The correspondence among key, operator, and computation is specified in Table 150.
constexpr value_type fetch_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<integral-type> is false.
Effects: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.races]).
Returns: Atomically, the value referenced by *ptr immediately before the effects.
Remarks: Except for fetch_max and fetch_min, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type.
[Note 2: 
There are no undefined results arising from the computation.
— end note]
For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.
constexpr value_type operator op=(value_type operand) const noexcept;
Constraints: is_const_v<integral-type> is false.
Effects: Equivalent to: return fetch_key(operand) op operand;

32.5.7.4 Specializations for floating-point types [atomics.ref.float]

There are specializations of the atomic_ref class template for all floating-point types.
For each such type floating-point-type, the specialization atomic_ref<floating-point> provides additional atomic operations appropriate to floating-point types.
The program is ill-formed if is_always_lock_free is false and is_volatile_v<T> is true.
namespace std { template<> struct atomic_ref<floating-point-type> { private: floating-point-type* ptr; // exposition only public: using value_type = remove_cv_t<floating-point-type>; using difference_type = value_type; static constexpr size_t required_alignment = implementation-defined; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(floating-point-type&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator floating-point-type() const noexcept; constexpr value_type exchange(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, floating-point-type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, floating-point-type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr floating-point-type* address() const noexcept; }; }
Descriptions are provided below only for members that differ from the primary template.
The following operations perform arithmetic computations.
The correspondence among key, operator, and computation is specified in Table 150.
constexpr value_type fetch_key(value_type operand, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<floating-point-type> is false.
Effects: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.races]).
Returns: Atomically, the value referenced by *ptr immediately before the effects.
Remarks: If the result is not a representable value for its type ([expr.pre]), the result is unspecified, but the operations otherwise have no undefined behavior.
Atomic arithmetic operations on floating-point-type should conform to the std​::​numeric_limits<value_type> traits associated with the floating-point type ([limits.syn]).
The floating-point environment ([cfenv]) for atomic arithmetic operations on floating-
point-type
may be different than the calling thread's floating-point environment.
constexpr value_type operator op=(value_type operand) const noexcept;
Constraints: is_const_v<floating-point-type> is false.
Effects: Equivalent to: return fetch_key(operand) op operand;

32.5.7.5 Partial specialization for pointers [atomics.ref.pointer]

There are specializations of the atomic_ref class template for all pointer-to-object types.
For each such type pointer-type, the specialization atomic_ref<pointer-type> provides additional atomic operations appropriate to pointer types.
The program is ill-formed if is_always_lock_free is false and is_volatile_v<T> is true.
namespace std { template<class T> struct atomic_ref<pointer-type> { private: pointer-type* ptr; // exposition only public: using value_type = remove_cv_t<pointer-type>; using difference_type = ptrdiff_t; static constexpr size_t required_alignment = implementation-defined; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(pointer-type&); constexpr atomic_ref(const atomic_ref&) noexcept; atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator++(int) const noexcept; constexpr value_type operator--(int) const noexcept; constexpr value_type operator++() const noexcept; constexpr value_type operator--() const noexcept; constexpr value_type operator+=(difference_type) const noexcept; constexpr value_type operator-=(difference_type) const noexcept; constexpr void wait(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr pointer-type* address() const noexcept; }; }
Descriptions are provided below only for members that differ from the primary template.
The following operations perform arithmetic computations.
The correspondence among key, operator, and computation is specified in Table 151.
constexpr value_type fetch_key(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
Constraints: is_const_v<pointer-type> is false.
Mandates: remove_pointer_t<pointer-type> is a complete object type.
Effects: Atomically replaces the value referenced by *ptr with the result of the computation applied to the value referenced by *ptr and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.races]).
Returns: Atomically, the value referenced by *ptr immediately before the effects.
Remarks: The result may be an undefined address, but the operations otherwise have no undefined behavior.
For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.
[Note 1: 
If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table 29, [expr.rel]).
— end note]
constexpr value_type operator op=(difference_type operand) const noexcept;
Constraints: is_const_v<pointer-type> is false.
Effects: Equivalent to: return fetch_key(operand) op operand;

32.5.7.6 Member operators common to integers and pointers to objects [atomics.ref.memop]

Let referred-type be pointer-type for the specializations in [atomics.ref.pointer] and be integral-type for the specializations in [atomics.ref.int].
constexpr value_type operator++(int) const noexcept;
Constraints: is_const_v<referred-type> is false.
Effects: Equivalent to: return fetch_add(1);
constexpr value_type operator--(int) const noexcept;
Constraints: is_const_v<referred-type> is false.
Effects: Equivalent to: return fetch_sub(1);
constexpr value_type operator++() const noexcept;
Constraints: is_const_v<referred-type> is false.
Effects: Equivalent to: return fetch_add(1) + 1;
constexpr value_type operator--() const noexcept;
Constraints: is_const_v<referred-type> is false.
Effects: Equivalent to: return fetch_sub(1) - 1;

32.5.8 Class template atomic [atomics.types.generic]

32.5.8.1 General [atomics.types.generic.general]

namespace std { template<class T> struct atomic { using value_type = T; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; // [atomics.types.operations], operations on atomic types constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>); 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; constexpr T load(memory_order = memory_order::seq_cst) const noexcept; operator T() const volatile noexcept; constexpr operator T() const noexcept; void store(T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(T, memory_order = memory_order::seq_cst) noexcept; T operator=(T) volatile noexcept; constexpr T operator=(T) noexcept; T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T exchange(T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T&, T, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_strong(T&, T, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(T&, T, memory_order, memory_order) noexcept; bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) noexcept; void wait(T, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; }; }
The template argument for T shall meet the Cpp17CopyConstructible and Cpp17CopyAssignable requirements.
The program is ill-formed if any of
  • is_trivially_copyable_v<T>,
  • is_copy_constructible_v<T>,
  • is_move_constructible_v<T>,
  • is_copy_assignable_v<T>,
  • is_move_assignable_v<T>, or
  • same_as<T, remove_cv_t<T>>,
is false.
[Note 1: 
Type arguments that are not also statically initializable can be difficult to use.
— end note]
The specialization atomic<bool> is a standard-layout struct.
It has a trivial destructor.
[Note 2: 
The representation of an atomic specialization need not have the same size and alignment requirement as its corresponding argument type.
— end note]

32.5.8.2 Operations on atomic types [atomics.types.operations]

constexpr atomic() noexcept(is_nothrow_default_constructible_v<T>);
Constraints: is_default_constructible_v<T> is true.
Effects: Initializes the atomic object with the value of T().
Initialization is not an atomic operation ([intro.multithread]).
constexpr atomic(T desired) noexcept;
Effects: Initializes the object with the value desired.
Initialization is not an atomic operation ([intro.multithread]).
[Note 1: 
It is possible to have an access to an atomic object A race with its construction, for example by communicating the address of the just-constructed object A to another thread via memory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread.
This results in undefined behavior.
— end note]
static constexpr bool is_always_lock_free = implementation-defined;
The static data member is_always_lock_free is true if the atomic type's operations are always lock-free, and false otherwise.
[Note 2: 
The value of is_always_lock_free is consistent with the value of the corresponding ATOMIC_..._LOCK_FREE macro, if defined.
— end note]
bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept;
Returns: true if the object's operations are lock-free, false otherwise.
[Note 3: 
The return value of the is_lock_free member function is consistent with the value of is_always_lock_free for the same type.
— end note]
void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void store(T desired, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Preconditions: order is memory_order​::​relaxed, memory_order​::​release, or memory_order​::​seq_cst.
Effects: Atomically replaces the value pointed to by this with the value of desired.
Memory is affected according to the value of order.
T operator=(T desired) volatile noexcept; constexpr T operator=(T desired) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to store(desired).
Returns: desired.
T load(memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr T load(memory_order order = memory_order::seq_cst) const noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns the value pointed to by this.
operator T() const volatile noexcept; constexpr operator T() const noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return load();
T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Atomically replaces the value pointed to by this with desired.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.multithread]).
Returns: Atomically returns the value pointed to by this immediately before the effects.
bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T& expected, T desired, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Preconditions: failure is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​acquire, or memory_order​::​seq_cst.
Effects: Retrieves the value in expected.
It then atomically compares the value representation of the value pointed to by this for equality with that previously retrieved from expected, and if true, replaces the value pointed to by this with that in desired.
If and only if the comparison is true, memory is affected according to the value of success, and if the comparison is false, memory is affected according to the value of failure.
When only one memory_order argument is supplied, the value of success is order, and the value of failure is order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
If and only if the comparison is false then, after the atomic operation, the value in expected is replaced by the value pointed to by this during the atomic comparison.
If the operation returns true, these operations are atomic read-modify-write operations ([intro.multithread]) on the memory pointed to by this.
Otherwise, these operations are atomic load operations on that memory.
Returns: The result of the comparison.
[Note 4: 
For example, the effect of compare_exchange_strong on objects without padding bits ([basic.types.general]) is if (memcmp(this, &expected, sizeof(*this)) == 0) memcpy(this, &desired, sizeof(*this)); else memcpy(&expected, this, sizeof(*this));
— end note]
[Example 1: 
The expected use of the compare-and-exchange operations is as follows.
The compare-and-exchange operations will update expected when another iteration of the loop is needed.
expected = current.load(); do { desired = function(expected); } while (!current.compare_exchange_weak(expected, desired)); — end example]
[Example 2: 
Because the expected value is updated only on failure, code releasing the memory containing the 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: 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 example]
Implementations should ensure that weak compare-and-exchange operations do not consistently return false unless either the atomic object has value different from expected or there are concurrent modifications to the atomic object.
Remarks: A weak compare-and-exchange operation may fail spuriously.
That is, even when the contents of memory referred to by expected and this are equal, it may return false and store back to expected the same memory contents that were originally there.
[Note 5: 
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]
[Note 6: 
Under cases where the memcpy and memcmp semantics of the compare-and-exchange operations apply, the comparisons can fail for values that compare equal with operator== if the value representation has trap bits or alternate representations of the same value.
Notably, on implementations conforming to ISO/IEC 60559, floating-point -0.0 and +0.0 will not compare equal with memcmp but will compare equal with operator==, and NaNs with the same payload will compare equal with memcmp but will not compare equal with operator==.
— end note]
[Note 7: 
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: struct padded { char clank = 0x42; // Padding here. unsigned biff = 0xC0DEFEFE; }; atomic<padded> pad = {}; bool zap() { padded expected, desired{0, 0}; return pad.compare_exchange_strong(expected, desired); }
— end note]
[Note 8: 
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: union pony { double celestia = 0.; short luna; // padded }; atomic<pony> princesses = {}; bool party(pony desired) { pony expected; return princesses.compare_exchange_strong(expected, desired); }
— end note]
void wait(T old, memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Repeatedly performs the following steps, in order:
  • Evaluates load(order) and compares its value representation for equality against that of old.
  • If they compare unequal, returns.
  • Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.
Remarks: This function is an atomic waiting operation ([atomics.wait]).
void notify_one() volatile noexcept; constexpr void notify_one() noexcept;
Effects: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.
Remarks: This function is an atomic notifying operation ([atomics.wait]).
void notify_all() volatile noexcept; constexpr void notify_all() noexcept;
Effects: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([atomics.wait]) by this call.
Remarks: This function is an atomic notifying operation ([atomics.wait]).

32.5.8.3 Specializations for integers [atomics.types.int]

There are specializations of the atomic class template for the integral types char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, char8_t, char16_t, char32_t, wchar_t, and any other types needed by the typedefs in the header <cstdint>.
For each such type integral-type, the specialization atomic<integral-type> provides additional atomic operations appropriate to integral types.
[Note 1: 
The specialization atomic<bool> uses the primary template ([atomics.types.generic]).
— end note]
namespace std { template<> struct atomic<integral-type> { using value_type = integral-type; using difference_type = value_type; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(integral-type) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; void store(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type operator=(integral-type) volatile noexcept; constexpr integral-type operator=(integral-type) noexcept; integral-type load(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr integral-type load(memory_order = memory_order::seq_cst) const noexcept; operator integral-type() const volatile noexcept; constexpr operator integral-type() const noexcept; integral-type exchange(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type exchange(integral-type, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(integral-type&, integral-type, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(integral-type&, integral-type, memory_order, memory_order) noexcept; bool compare_exchange_strong(integral-type&, integral-type, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(integral-type&, integral-type, memory_order, memory_order) noexcept; bool compare_exchange_weak(integral-type&, integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(integral-type&, integral-type, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(integral-type&, integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(integral-type&, integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_add(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_add(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_sub(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_sub(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_and(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_and(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_or(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_or(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_xor(integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_xor(integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_max( integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_max( integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type fetch_min( integral-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr integral-type fetch_min( integral-type, memory_order = memory_order::seq_cst) noexcept; integral-type operator++(int) volatile noexcept; constexpr integral-type operator++(int) noexcept; integral-type operator--(int) volatile noexcept; constexpr integral-type operator--(int) noexcept; integral-type operator++() volatile noexcept; constexpr integral-type operator++() noexcept; integral-type operator--() volatile noexcept; constexpr integral-type operator--() noexcept; integral-type operator+=(integral-type) volatile noexcept; constexpr integral-type operator+=(integral-type) noexcept; integral-type operator-=(integral-type) volatile noexcept; constexpr integral-type operator-=(integral-type) noexcept; integral-type operator&=(integral-type) volatile noexcept; constexpr integral-type operator&=(integral-type) noexcept; integral-type operator|=(integral-type) volatile noexcept; constexpr integral-type operator|=(integral-type) noexcept; integral-type operator^=(integral-type) volatile noexcept; constexpr integral-type operator^=(integral-type) noexcept; void wait(integral-type, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(integral-type, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; }; }
The atomic integral specializations are standard-layout structs.
They each have a trivial destructor.
Descriptions are provided below only for members that differ from the primary template.
The following operations perform arithmetic computations.
The correspondence among key, operator, and computation is specified in Table 150.
Table 150 — Atomic arithmetic computations [tab:atomic.types.int.comp]
key
Op
Computation
key
Op
Computation
add
+
addition
and
&
bitwise and
sub
-
subtraction
or
|
bitwise inclusive or
max
maximum
xor
^
bitwise exclusive or
min
minimum
T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.multithread]).
Returns: Atomically, the value pointed to by this immediately before the effects.
Remarks: Except for fetch_max and fetch_min, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type.
[Note 2: 
There are no undefined results arising from the computation.
— end note]
For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.
T operator op=(T operand) volatile noexcept; constexpr T operator op=(T operand) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_key(operand) op operand;

32.5.8.4 Specializations for floating-point types [atomics.types.float]

There are specializations of the atomic class template for all cv-unqualified floating-point types.
For each such type floating-point-type, the specialization atomic<floating-point-type> provides additional atomic operations appropriate to floating-point types.
namespace std { template<> struct atomic<floating-point-type> { using value_type = floating-point-type; using difference_type = value_type; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(floating-point-type) noexcept; atomic(const atomic&) = delete; atomic& operator=(const atomic&) = delete; atomic& operator=(const atomic&) volatile = delete; void store(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(floating-point-type, memory_order = memory_order::seq_cst) noexcept; floating-point-type operator=(floating-point-type) volatile noexcept; constexpr floating-point-type operator=(floating-point-type) noexcept; floating-point-type load(memory_order = memory_order::seq_cst) volatile noexcept; constexpr floating-point-type load(memory_order = memory_order::seq_cst) noexcept; operator floating-point-type() volatile noexcept; constexpr operator floating-point-type() noexcept; floating-point-type exchange(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr floating-point-type exchange(floating-point-type, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(floating-point-type&, floating-point-type, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type, memory_order, memory_order) noexcept; bool compare_exchange_strong(floating-point-type&, floating-point-type, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type, memory_order, memory_order) noexcept; bool compare_exchange_weak(floating-point-type&, floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(floating-point-type&, floating-point-type, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(floating-point-type&, floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(floating-point-type&, floating-point-type, memory_order = memory_order::seq_cst) noexcept; floating-point-type fetch_add(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr floating-point-type fetch_add(floating-point-type, memory_order = memory_order::seq_cst) noexcept; floating-point-type fetch_sub(floating-point-type, memory_order = memory_order::seq_cst) volatile noexcept; constexpr floating-point-type fetch_sub(floating-point-type, memory_order = memory_order::seq_cst) noexcept; floating-point-type operator+=(floating-point-type) volatile noexcept; constexpr floating-point-type operator+=(floating-point-type) noexcept; floating-point-type operator-=(floating-point-type) volatile noexcept; constexpr floating-point-type operator-=(floating-point-type) noexcept; void wait(floating-point-type, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(floating-point-type, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; }; }
The atomic floating-point specializations are standard-layout structs.
They each have a trivial destructor.
Descriptions are provided below only for members that differ from the primary template.
The following operations perform arithmetic addition and subtraction computations.
The correspondence among key, operator, and computation is specified in Table 150.
T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T fetch_key(T operand, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.multithread]).
Returns: Atomically, the value pointed to by this immediately before the effects.
Remarks: If the result is not a representable value for its type ([expr.pre]) the result is unspecified, but the operations otherwise have no undefined behavior.
Atomic arithmetic operations on floating-point-type should conform to the std​::​numeric_limits<floating-point-type> traits associated with the floating-point type ([limits.syn]).
The floating-point environment ([cfenv]) for atomic arithmetic operations on floating-point-type may be different than the calling thread's floating-point environment.
T operator op=(T operand) volatile noexcept; constexpr T operator op=(T operand) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_key(operand) op operand;
Remarks: If the result is not a representable value for its type ([expr.pre]) the result is unspecified, but the operations otherwise have no undefined behavior.
Atomic arithmetic operations on floating-point-type should conform to the std​::​numeric_limits<floating-point-type> traits associated with the floating-point type ([limits.syn]).
The floating-point environment ([cfenv]) for atomic arithmetic operations on floating-point-type may be different than the calling thread's floating-point environment.

32.5.8.5 Partial specialization for pointers [atomics.types.pointer]

namespace std { template<class T> struct atomic<T*> { using value_type = T*; using difference_type = ptrdiff_t; static constexpr bool is_always_lock_free = implementation-defined; 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; constexpr void store(T*, memory_order = memory_order::seq_cst) noexcept; T* operator=(T*) volatile noexcept; constexpr T* operator=(T*) noexcept; T* load(memory_order = memory_order::seq_cst) const volatile noexcept; constexpr T* load(memory_order = memory_order::seq_cst) const noexcept; operator T*() const volatile noexcept; constexpr operator T*() const noexcept; T* exchange(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* exchange(T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(T*&, T*, memory_order, memory_order) noexcept; bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(T*&, T*, memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(T*&, T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_add(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_sub(ptrdiff_t, memory_order = memory_order::seq_cst) noexcept; T* fetch_max(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_max(T*, memory_order = memory_order::seq_cst) noexcept; T* fetch_min(T*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_min(T*, memory_order = memory_order::seq_cst) noexcept; T* operator++(int) volatile noexcept; constexpr T* operator++(int) noexcept; T* operator--(int) volatile noexcept; constexpr T* operator--(int) noexcept; T* operator++() volatile noexcept; constexpr T* operator++() noexcept; T* operator--() volatile noexcept; constexpr T* operator--() noexcept; T* operator+=(ptrdiff_t) volatile noexcept; constexpr T* operator+=(ptrdiff_t) noexcept; T* operator-=(ptrdiff_t) volatile noexcept; constexpr T* operator-=(ptrdiff_t) noexcept; void wait(T*, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(T*, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; }; }
There is a partial specialization of the atomic class template for pointers.
Specializations of this partial specialization are standard-layout structs.
They each have a trivial destructor.
Descriptions are provided below only for members that differ from the primary template.
The following operations perform pointer arithmetic.
The correspondence among key, operator, and computation is specified in Table 151.
Table 151 — Atomic pointer computations [tab:atomic.types.pointer.comp]
key
Op
Computation
key
Op
Computation
add
+
addition
sub
-
subtraction
max
maximum
min
minimum
T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Mandates: T is a complete object type.
[Note 1: 
Pointer arithmetic on void* or function pointers is ill-formed.
— end note]
Effects: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed to by this and the given operand.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.multithread]).
Returns: Atomically, the value pointed to by this immediately before the effects.
Remarks: The result may be an undefined address, but the operations otherwise have no undefined behavior.
For fetch_max and fetch_min, the maximum and minimum computation is performed as if by max and min algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.
[Note 2: 
If the pointers point to different complete objects (or subobjects thereof), the < operator does not establish a strict weak ordering (Table 29, [expr.rel]).
— end note]
T* operator op=(ptrdiff_t operand) volatile noexcept; constexpr T* operator op=(ptrdiff_t operand) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_key(operand) op operand;

32.5.8.6 Member operators common to integers and pointers to objects [atomics.types.memop]

value_type operator++(int) volatile noexcept; constexpr value_type operator++(int) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_add(1);
value_type operator--(int) volatile noexcept; constexpr value_type operator--(int) noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_sub(1);
value_type operator++() volatile noexcept; constexpr value_type operator++() noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_add(1) + 1;
value_type operator--() volatile noexcept; constexpr value_type operator--() noexcept;
Constraints: For the volatile overload of this function, is_always_lock_free is true.
Effects: Equivalent to: return fetch_sub(1) - 1;

32.5.8.7 Partial specializations for smart pointers [util.smartptr.atomic]

32.5.8.7.1 General [util.smartptr.atomic.general]

The library provides partial specializations of the atomic template for shared-ownership smart pointers ([util.sharedptr]).
[Note 1: 
The partial specializations are declared in header <memory>.
— end note]
The behavior of all operations is as specified in [atomics.types.generic], unless specified otherwise.
The template parameter T of these partial specializations may be an incomplete type.
All changes to an atomic smart pointer in [util.smartptr.atomic], and all associated use_count increments, are guaranteed to be performed atomically.
Associated 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.
[Note 2: 
If the atomic operation uses locks, locks acquired by the implementation will be held when any use_count adjustments are performed, and will not be held when any destruction or deallocation resulting from this is performed.
— end note]
[Example 1: template<typename T> class atomic_list { struct node { T t; shared_ptr<node> next; }; atomic<shared_ptr<node>> head; public: shared_ptr<node> find(T t) const { auto p = head.load(); while (p && p->t != t) p = p->next; return p; } void push_front(T t) { auto p = make_shared<node>(); p->t = t; p->next = head; while (!head.compare_exchange_weak(p->next, p)) {} } }; — end example]

32.5.8.7.2 Partial specialization for shared_ptr [util.smartptr.atomic.shared]

namespace std { template<class T> struct atomic<shared_ptr<T>> { using value_type = shared_ptr<T>; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(nullptr_t) noexcept : atomic() { } atomic(shared_ptr<T> desired) noexcept; atomic(const atomic&) = delete; void operator=(const atomic&) = delete; shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; operator shared_ptr<T>() const noexcept; void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; void operator=(shared_ptr<T> desired) noexcept; void operator=(nullptr_t) noexcept; shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept; void notify_one() noexcept; void notify_all() noexcept; private: shared_ptr<T> p; // exposition only }; }
constexpr atomic() noexcept;
Effects: Initializes p{}.
atomic(shared_ptr<T> desired) noexcept;
Effects: Initializes the object with the value desired.
Initialization is not an atomic operation ([intro.multithread]).
[Note 1: 
It is possible to have an access to an atomic object A race with its construction, for example, by communicating the address of the just-constructed object A to another thread via memory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread.
This results in undefined behavior.
— end note]
void store(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​release, or memory_order​::​seq_cst.
Effects: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired).
Memory is affected according to the value of order.
void operator=(shared_ptr<T> desired) noexcept;
Effects: Equivalent to store(desired).
void operator=(nullptr_t) noexcept;
Effects: Equivalent to store(nullptr).
shared_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns p.
operator shared_ptr<T>() const noexcept;
Effects: Equivalent to: return load();
shared_ptr<T> exchange(shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Atomically replaces p with desired as if by p.swap(desired).
Memory is affected according to the value of order.
This is an atomic read-modify-write operation ([intro.races]).
Returns: Atomically returns the value of p immediately before the effects.
bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order success, memory_order failure) noexcept;
Preconditions: failure is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​acquire, or memory_order​::​seq_cst.
Effects: If p is equivalent to expected, assigns desired to p and has synchronization semantics corresponding to the value of success, otherwise assigns p to expected and has synchronization semantics corresponding to the value of failure.
Returns: true if p was equivalent to expected, false otherwise.
Remarks: Two 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.
If the operation returns true, expected is not accessed after the atomic update and the operation is an atomic read-modify-write operation ([intro.multithread]) on the memory pointed to by this.
Otherwise, the operation is an atomic load operation on that memory, and expected is updated with the existing value read from the atomic object in the attempted atomic update.
The use_count update corresponding to the write to expected is part of the atomic operation.
The write to expected itself is not required to be part of the atomic operation.
bool compare_exchange_weak(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Equivalent to: return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
bool compare_exchange_strong(shared_ptr<T>& expected, shared_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Equivalent to: return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
void wait(shared_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Repeatedly performs the following steps, in order:
  • Evaluates load(order) and compares it to old.
  • If the two are not equivalent, returns.
  • Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.
Remarks: Two 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 ([atomics.wait]).
void notify_one() noexcept;
Effects: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.
Remarks: This function is an atomic notifying operation ([atomics.wait]).
void notify_all() noexcept;
Effects: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([atomics.wait]) by this call.
Remarks: This function is an atomic notifying operation ([atomics.wait]).

32.5.8.7.3 Partial specialization for weak_ptr [util.smartptr.atomic.weak]

namespace std { template<class T> struct atomic<weak_ptr<T>> { using value_type = weak_ptr<T>; static constexpr bool is_always_lock_free = implementation-defined; bool is_lock_free() const noexcept; constexpr atomic() noexcept; atomic(weak_ptr<T> desired) noexcept; atomic(const atomic&) = delete; void operator=(const atomic&) = delete; weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept; operator weak_ptr<T>() const noexcept; void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; void operator=(weak_ptr<T> desired) noexcept; weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept; void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept; void notify_one() noexcept; void notify_all() noexcept; private: weak_ptr<T> p; // exposition only }; }
constexpr atomic() noexcept;
Effects: Initializes p{}.
atomic(weak_ptr<T> desired) noexcept;
Effects: Initializes the object with the value desired.
Initialization is not an atomic operation ([intro.multithread]).
[Note 1: 
It is possible to have an access to an atomic object A race with its construction, for example, by communicating the address of the just-constructed object A to another thread via memory_order​::​relaxed operations on a suitable atomic pointer variable, and then immediately accessing A in the receiving thread.
This results in undefined behavior.
— end note]
void store(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​release, or memory_order​::​seq_cst.
Effects: Atomically replaces the value pointed to by this with the value of desired as if by p.swap(desired).
Memory is affected according to the value of order.
void operator=(weak_ptr<T> desired) noexcept;
Effects: Equivalent to store(desired).
weak_ptr<T> load(memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns p.
operator weak_ptr<T>() const noexcept;
Effects: Equivalent to: return load();
weak_ptr<T> exchange(weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Atomically replaces p with desired as if by p.swap(desired).
Memory is affected according to the value of order.
This is an atomic read-modify-write operation ([intro.races]).
Returns: Atomically returns the value of p immediately before the effects.
bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept; bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order success, memory_order failure) noexcept;
Preconditions: failure is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​acquire, or memory_order​::​seq_cst.
Effects: If p is equivalent to expected, assigns desired to p and has synchronization semantics corresponding to the value of success, otherwise assigns p to expected and has synchronization semantics corresponding to the value of failure.
Returns: true if p was equivalent to expected, false otherwise.
Remarks: Two 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.
If the operation returns true, expected is not accessed after the atomic update and the operation is an atomic read-modify-write operation ([intro.multithread]) on the memory pointed to by this.
Otherwise, the operation is an atomic load operation on that memory, and expected is updated with the existing value read from the atomic object in the attempted atomic update.
The use_count update corresponding to the write to expected is part of the atomic operation.
The write to expected itself is not required to be part of the atomic operation.
bool compare_exchange_weak(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Equivalent to: return compare_exchange_weak(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
bool compare_exchange_strong(weak_ptr<T>& expected, weak_ptr<T> desired, memory_order order = memory_order::seq_cst) noexcept;
Effects: Equivalent to: return compare_exchange_strong(expected, desired, order, fail_order); where fail_order is the same as order except that a value of memory_order​::​acq_rel shall be replaced by the value memory_order​::​acquire and a value of memory_order​::​release shall be replaced by the value memory_order​::​relaxed.
void wait(weak_ptr<T> old, memory_order order = memory_order::seq_cst) const noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Repeatedly performs the following steps, in order:
  • Evaluates load(order) and compares it to old.
  • If the two are not equivalent, returns.
  • Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.
Remarks: Two 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 ([atomics.wait]).
void notify_one() noexcept;
Effects: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.
Remarks: This function is an atomic notifying operation ([atomics.wait]).
void notify_all() noexcept;
Effects: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([atomics.wait]) by this call.
Remarks: This function is an atomic notifying operation ([atomics.wait]).

32.5.9 Non-member functions [atomics.nonmembers]

A non-member function template whose name matches the pattern atomic_f or the pattern atomic_f_explicit invokes the member function 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 atomic<T>​::​value_type* is dereferenced when passed to the member function call.
If no such member function exists, the program is ill-formed.
[Note 1: 
The non-member functions enable programmers to write code that can be compiled as either C or C++, for example in a shared header file.
— end note]

32.5.10 Flag type and operations [atomics.flag]

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; constexpr bool test(memory_order = memory_order::seq_cst) const noexcept; bool test_and_set(memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool test_and_set(memory_order = memory_order::seq_cst) noexcept; void clear(memory_order = memory_order::seq_cst) volatile noexcept; constexpr void clear(memory_order = memory_order::seq_cst) noexcept; void wait(bool, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(bool, memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; }; }
The atomic_flag type provides the classic test-and-set functionality.
It has two states, set and clear.
Operations on an object of type atomic_flag shall be lock-free.
The operations should also be address-free.
The atomic_flag type is a standard-layout struct.
It has a trivial destructor.
constexpr atomic_flag::atomic_flag() noexcept;
Effects: Initializes *this to the clear state.
bool atomic_flag_test(const volatile atomic_flag* object) noexcept; constexpr bool atomic_flag_test(const atomic_flag* object) noexcept; bool atomic_flag_test_explicit(const volatile atomic_flag* object, memory_order order) noexcept; constexpr bool atomic_flag_test_explicit(const atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test(memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr bool atomic_flag::test(memory_order order = memory_order::seq_cst) const noexcept;
For atomic_flag_test, let order be memory_order​::​seq_cst.
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Memory is affected according to the value of order.
Returns: Atomically returns the value pointed to by object or this.
bool atomic_flag_test_and_set(volatile atomic_flag* object) noexcept; constexpr bool atomic_flag_test_and_set(atomic_flag* object) noexcept; bool atomic_flag_test_and_set_explicit(volatile atomic_flag* object, memory_order order) noexcept; constexpr bool atomic_flag_test_and_set_explicit(atomic_flag* object, memory_order order) noexcept; bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) volatile noexcept; constexpr bool atomic_flag::test_and_set(memory_order order = memory_order::seq_cst) noexcept;
Effects: Atomically sets the value pointed to by object or by this to true.
Memory is affected according to the value of order.
These operations are atomic read-modify-write operations ([intro.multithread]).
Returns: Atomically, the value of the object immediately before the effects.
void atomic_flag_clear(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_clear(atomic_flag* object) noexcept; void atomic_flag_clear_explicit(volatile atomic_flag* object, memory_order order) noexcept; constexpr void atomic_flag_clear_explicit(atomic_flag* object, memory_order order) noexcept; void atomic_flag::clear(memory_order order = memory_order::seq_cst) volatile noexcept; constexpr void atomic_flag::clear(memory_order order = memory_order::seq_cst) noexcept;
Preconditions: order is memory_order​::​relaxed, memory_order​::​release, or memory_order​::​seq_cst.
Effects: Atomically sets the value pointed to by object or by this to false.
Memory is affected according to the value of order.
void atomic_flag_wait(const volatile atomic_flag* object, bool old) noexcept; constexpr void atomic_flag_wait(const atomic_flag* object, bool old) noexcept; void atomic_flag_wait_explicit(const volatile atomic_flag* object, bool old, memory_order order) noexcept; constexpr void atomic_flag_wait_explicit(const atomic_flag* object, bool old, memory_order order) noexcept; void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const volatile noexcept; constexpr void atomic_flag::wait(bool old, memory_order order = memory_order::seq_cst) const noexcept;
For atomic_flag_wait, let order be memory_order​::​seq_cst.
Let flag be object for the non-member functions and this for the member functions.
Preconditions: order is memory_order​::​relaxed, memory_order​::​consume, memory_order​::​ac-
quire
, or memory_order​::​seq_cst.
Effects: Repeatedly performs the following steps, in order:
  • Evaluates flag->test(order) != old.
  • If the result of that evaluation is true, returns.
  • Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.
Remarks: This function is an atomic waiting operation ([atomics.wait]).
void atomic_flag_notify_one(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_notify_one(atomic_flag* object) noexcept; void atomic_flag::notify_one() volatile noexcept; constexpr void atomic_flag::notify_one() noexcept;
Effects: Unblocks the execution of at least one atomic waiting operation that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.
Remarks: This function is an atomic notifying operation ([atomics.wait]).
void atomic_flag_notify_all(volatile atomic_flag* object) noexcept; constexpr void atomic_flag_notify_all(atomic_flag* object) noexcept; void atomic_flag::notify_all() volatile noexcept; constexpr void atomic_flag::notify_all() noexcept;
Effects: Unblocks the execution of all atomic waiting operations that are eligible to be unblocked ([atomics.wait]) by this call.
Remarks: This function is an atomic notifying operation ([atomics.wait]).
#define ATOMIC_FLAG_INIT see below
Remarks: The macro ATOMIC_FLAG_INIT is defined in such a way that it can be used to initialize an object of type atomic_flag to the clear state.
The macro can be used in the form: atomic_flag guard = ATOMIC_FLAG_INIT;
It is unspecified whether the macro can be used in other initialization contexts.
For a complete static-duration object, that initialization shall be static.

32.5.11 Fences [atomics.fences]

This subclause introduces synchronization primitives called fences.
Fences can have acquire semantics, release semantics, or both.
A fence with acquire semantics is called an acquire fence.
A fence with release semantics is called a release fence.
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.
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.
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.
extern "C" constexpr void atomic_thread_fence(memory_order order) noexcept;
Effects: Depending on the value of order, this operation:
  • has no effects, if order == memory_order​::​relaxed;
  • is an acquire fence, if order == memory_order​::​acquire or order == memory_order​::​consume;
  • is a release fence, if order == memory_order​::​release;
  • is both an acquire fence and a release fence, if order == memory_order​::​acq_rel;
  • is a sequentially consistent acquire and release fence, if order == memory_order​::​seq_cst.
extern "C" constexpr void atomic_signal_fence(memory_order order) noexcept;
Effects: Equivalent to 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.
[Note 1: 
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 atomic_thread_fence, but the hardware fence instructions that atomic_thread_fence would have inserted are not emitted.
— end note]

32.5.12 C compatibility [stdatomic.h.syn]

The header <stdatomic.h> provides the following definitions:
template<class T> using std-atomic = std::atomic<T>; // exposition only #define _Atomic(T) std-atomic<T> #define ATOMIC_BOOL_LOCK_FREE see below #define ATOMIC_CHAR_LOCK_FREE see below #define ATOMIC_CHAR16_T_LOCK_FREE see below #define ATOMIC_CHAR32_T_LOCK_FREE see below #define ATOMIC_WCHAR_T_LOCK_FREE see below #define ATOMIC_SHORT_LOCK_FREE see below #define ATOMIC_INT_LOCK_FREE see below #define ATOMIC_LONG_LOCK_FREE see below #define ATOMIC_LLONG_LOCK_FREE see below #define ATOMIC_POINTER_LOCK_FREE see below using std::memory_order; // see below using std::memory_order_relaxed; // see below using std::memory_order_consume; // see below using std::memory_order_acquire; // see below using std::memory_order_release; // see below using std::memory_order_acq_rel; // see below using std::memory_order_seq_cst; // see below using std::atomic_flag; // see below using std::atomic_bool; // see below using std::atomic_char; // see below using std::atomic_schar; // see below using std::atomic_uchar; // see below using std::atomic_short; // see below using std::atomic_ushort; // see below using std::atomic_int; // see below using std::atomic_uint; // see below using std::atomic_long; // see below using std::atomic_ulong; // see below using std::atomic_llong; // see below using std::atomic_ullong; // see below using std::atomic_char8_t; // see below using std::atomic_char16_t; // see below using std::atomic_char32_t; // see below using std::atomic_wchar_t; // see below using std::atomic_int8_t; // see below using std::atomic_uint8_t; // see below using std::atomic_int16_t; // see below using std::atomic_uint16_t; // see below using std::atomic_int32_t; // see below using std::atomic_uint32_t; // see below using std::atomic_int64_t; // see below using std::atomic_uint64_t; // see below using std::atomic_int_least8_t; // see below using std::atomic_uint_least8_t; // see below using std::atomic_int_least16_t; // see below using std::atomic_uint_least16_t; // see below using std::atomic_int_least32_t; // see below using std::atomic_uint_least32_t; // see below using std::atomic_int_least64_t; // see below using std::atomic_uint_least64_t; // see below using std::atomic_int_fast8_t; // see below using std::atomic_uint_fast8_t; // see below using std::atomic_int_fast16_t; // see below using std::atomic_uint_fast16_t; // see below using std::atomic_int_fast32_t; // see below using std::atomic_uint_fast32_t; // see below using std::atomic_int_fast64_t; // see below using std::atomic_uint_fast64_t; // see below using std::atomic_intptr_t; // see below using std::atomic_uintptr_t; // see below using std::atomic_size_t; // see below using std::atomic_ptrdiff_t; // see below using std::atomic_intmax_t; // see below using std::atomic_uintmax_t; // see below using std::atomic_is_lock_free; // see below using std::atomic_load; // see below using std::atomic_load_explicit; // see below using std::atomic_store; // see below using std::atomic_store_explicit; // see below using std::atomic_exchange; // see below using std::atomic_exchange_explicit; // see below using std::atomic_compare_exchange_strong; // see below using std::atomic_compare_exchange_strong_explicit; // see below using std::atomic_compare_exchange_weak; // see below using std::atomic_compare_exchange_weak_explicit; // see below using std::atomic_fetch_add; // see below using std::atomic_fetch_add_explicit; // see below using std::atomic_fetch_sub; // see below using std::atomic_fetch_sub_explicit; // see below using std::atomic_fetch_and; // see below using std::atomic_fetch_and_explicit; // see below using std::atomic_fetch_or; // see below using std::atomic_fetch_or_explicit; // see below using std::atomic_fetch_xor; // see below using std::atomic_fetch_xor_explicit; // see below using std::atomic_flag_test_and_set; // see below using std::atomic_flag_test_and_set_explicit; // see below using std::atomic_flag_clear; // see below using std::atomic_flag_clear_explicit; // see below #define ATOMIC_FLAG_INIT see below using std::atomic_thread_fence; // see below using std::atomic_signal_fence; // see below
Each using-declaration for some name A in the synopsis above makes available the same entity as std​::​A declared in <atomic>.
Each macro listed above other than _Atomic(T) is defined as in <atomic>.
It is unspecified whether <stdatomic.h> makes available any declarations in namespace std.
Each of the using-declarations for intN_t, uintN_t, intptr_t, and uintptr_t listed above is defined if and only if the implementation defines the corresponding typedef-name in [atomics.syn].
Neither the _Atomic macro, nor any of the non-macro global namespace declarations, are provided by any C++ standard library header other than <stdatomic.h>.
Recommended practice: Implementations should ensure that C and C++ representations of atomic objects are compatible, so that the same object can be accessed as both an _Atomic(T) from C code and an atomic<T> from C++ code.
The representations should be the same, and the mechanisms used to ensure atomicity and memory ordering should be compatible.

32.6 Mutual exclusion [thread.mutex]

32.6.1 General [thread.mutex.general]

Subclause [thread.mutex] provides mechanisms for mutual exclusion: mutexes, locks, and call once.
These mechanisms ease the production of race-free programs ([intro.multithread]).

32.6.2 Header <mutex> synopsis [mutex.syn]

namespace std { // [thread.mutex.class], class mutex class mutex; // [thread.mutex.recursive], class recursive_mutex class recursive_mutex; // [thread.timedmutex.class], class timed_mutex class timed_mutex; // [thread.timedmutex.recursive], class recursive_timed_mutex class recursive_timed_mutex; struct defer_lock_t { explicit defer_lock_t() = default; }; struct try_to_lock_t { explicit try_to_lock_t() = default; }; struct adopt_lock_t { explicit adopt_lock_t() = default; }; inline constexpr defer_lock_t defer_lock { }; inline constexpr try_to_lock_t try_to_lock { }; inline constexpr adopt_lock_t adopt_lock { }; // [thread.lock], locks template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock; template<class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; // [thread.lock.algorithm], generic locking algorithms template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...); struct once_flag; template<class Callable, class... Args> void call_once(once_flag& flag, Callable&& func, Args&&... args); }

32.6.3 Header <shared_mutex> synopsis [shared.mutex.syn]

namespace std { // [thread.sharedmutex.class], class shared_mutex class shared_mutex; // [thread.sharedtimedmutex.class], class shared_timed_mutex class shared_timed_mutex; // [thread.lock.shared], class template shared_lock template<class Mutex> class shared_lock; template<class Mutex> void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept; }

32.6.4 Mutex requirements [thread.mutex.requirements]

32.6.4.1 General [thread.mutex.requirements.general]

A mutex object facilitates protection against data races and allows safe synchronization of data between execution agents.
An execution agent owns a mutex from the time it successfully calls one of the lock functions until it calls unlock.
Mutexes can be either recursive or non-recursive, and can grant simultaneous ownership to one or many execution agents.
Both recursive and non-recursive mutexes are supplied.

32.6.4.2 Mutex types [thread.mutex.requirements.mutex]

32.6.4.2.1 General [thread.mutex.requirements.mutex.general]

The mutex types are the standard library types mutex, recursive_mutex, timed_mutex, recursive_timed_mutex, shared_mutex, and shared_timed_mutex.
They meet the requirements set out in [thread.mutex.requirements.mutex].
In this description, m denotes an object of a mutex type.
[Note 1: 
The mutex types meet the Cpp17Lockable requirements ([thread.req.lockable.req]).
— end note]
If initialization of an object of a mutex type fails, an exception of type system_error is thrown.
The mutex types are neither copyable nor movable.
The error conditions for error codes, if any, reported by member functions of the mutex types are as follows:
  • resource_unavailable_try_again — if any native handle type manipulated is not available.
  • operation_not_permitted — if the thread does not have the privilege to perform the operation.
  • invalid_argument — if any native handle type manipulated as part of mutex construction is incorrect.
The implementation provides lock and unlock operations, as described below.
For purposes of determining the existence of a data race, these behave as atomic operations ([intro.multithread]).
The lock and unlock operations on a single mutex appears to occur in a single total order.
[Note 2: 
This can be viewed as the modification order of the mutex.
— end note]
[Note 3: 
Construction and destruction of an object of a mutex type need not be thread-safe; other synchronization can be used to ensure that mutex objects are initialized and visible to other threads.
— end note]
The expression m.lock() is well-formed and has the following semantics:
Preconditions: If m is of type mutex, timed_mutex, shared_mutex, or shared_timed_mutex, the calling thread does not own the mutex.
Effects: Blocks the calling thread until ownership of the mutex can be obtained for the calling thread.
Synchronization: Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Postconditions: The calling thread owns the mutex.
Return type: void.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if the thread does not have the privilege to perform the operation.
  • resource_deadlock_would_occur — if the implementation detects that a deadlock would occur.
The expression m.try_lock() is well-formed and has the following semantics:
Preconditions: If m is of type mutex, timed_mutex, shared_mutex, or shared_timed_mutex, the calling thread does not own the mutex.
Effects: Attempts to obtain ownership of the mutex for the calling thread without blocking.
If ownership is not obtained, there is no effect and try_lock() immediately returns.
An implementation may fail to obtain the lock even if it is not held by any other thread.
[Note 4: 
This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange ([atomics]).
— end note]
An implementation should ensure that try_lock() does not consistently return false in the absence of contending mutex acquisitions.
Synchronization: If try_lock() returns true, prior unlock() operations on the same object synchronize with this operation.
[Note 5: 
Since lock() does not synchronize with a failed subsequent try_lock(), the visibility rules are weak enough that little would be known about the state after a failure, even in the absence of spurious failures.
— end note]
Return type: bool.
Returns: true if ownership was obtained, otherwise false.
Throws: Nothing.
The expression m.unlock() is well-formed and has the following semantics:
Preconditions: The calling thread owns the mutex.
Effects: Releases the calling thread's ownership of the mutex.
Return type: void.
Synchronization: This operation synchronizes with subsequent lock operations that obtain ownership on the same object.
Throws: Nothing.

32.6.4.2.2 Class mutex [thread.mutex.class]

namespace std { class mutex { public: constexpr mutex() noexcept; ~mutex(); mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; void lock(); bool try_lock(); void unlock(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class mutex provides a non-recursive mutex with exclusive ownership semantics.
If one thread owns a mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock()) until the owning thread has released ownership with a call to unlock().
[Note 1: 
After a thread A has called unlock(), releasing a mutex, it is possible for another thread B to lock the same mutex, observe that it is no longer in use, unlock it, and destroy it, before thread A appears to have returned from its unlock call.
Conforming implementations handle such scenarios correctly, as long as thread A does not access the mutex after the unlock call returns.
These cases typically occur when a reference-counted object contains a mutex that is used to protect the reference count.
— end note]
The class mutex meets all of the mutex requirements ([thread.mutex.requirements]).
It is a standard-layout class ([class.prop]).
[Note 2: 
A program can deadlock if the thread that owns a mutex object calls lock() on that object.
If the implementation can detect the deadlock, a resource_deadlock_would_occur error condition might be observed.
— end note]
The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutex object.

32.6.4.2.3 Class recursive_mutex [thread.mutex.recursive]

namespace std { class recursive_mutex { public: recursive_mutex(); ~recursive_mutex(); recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; void lock(); bool try_lock() noexcept; void unlock(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class recursive_mutex provides a recursive mutex with exclusive ownership semantics.
If one thread owns a recursive_mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock()) until the first thread has completely released ownership.
The class recursive_mutex meets all of the mutex requirements ([thread.mutex.requirements]).
It is a standard-layout class ([class.prop]).
A thread that owns a recursive_mutex object may acquire additional levels of ownership by calling lock() or try_lock() on that object.
It is unspecified how many levels of ownership may be acquired by a single thread.
If a thread has already acquired the maximum level of ownership for a recursive_mutex object, additional calls to try_lock() fail, and additional calls to lock() throw an exception of type system_error.
A thread shall call unlock() once for each level of ownership acquired by calls to lock() and try_lock().
Only when all levels of ownership have been released may ownership be acquired by another thread.
The behavior of a program is undefined if
  • it destroys a recursive_mutex object owned by any thread or
  • a thread terminates while owning a recursive_mutex object.

32.6.4.3 Timed mutex types [thread.timedmutex.requirements]

32.6.4.3.1 General [thread.timedmutex.requirements.general]

The timed mutex types are the standard library types timed_mutex, recursive_timed_mutex, and shared_timed_mutex.
They meet the requirements set out below.
In this description, m denotes an object of a mutex type, rel_time denotes an object of an instantiation of duration, and abs_time denotes an object of an instantiation of time_point.
[Note 1: 
The timed mutex types meet the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
— end note]
The expression m.try_lock_for(rel_time) is well-formed and has the following semantics:
Preconditions: If m is of type timed_mutex or shared_timed_mutex, the calling thread does not own the mutex.
Effects: The function attempts to obtain ownership of the mutex within the relative timeout ([thread.req.timing]) specified by rel_time.
If the time specified by rel_time is less than or equal to rel_time.zero(), the function attempts to obtain ownership without blocking (as if by calling try_lock()).
The function returns within the timeout specified by rel_time only if it has obtained ownership of the mutex object.
[Note 2: 
As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
— end note]
Synchronization: If try_lock_for() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if ownership was obtained, otherwise false.
Throws: Timeout-related exceptions ([thread.req.timing]).
The expression m.try_lock_until(abs_time) is well-formed and has the following semantics:
Preconditions: If m is of type timed_mutex or shared_timed_mutex, the calling thread does not own the mutex.
Effects: The function attempts to obtain ownership of the mutex.
If abs_time has already passed, the function attempts to obtain ownership without blocking (as if by calling try_lock()).
The function returns before the absolute timeout ([thread.req.timing]) specified by abs_time only if it has obtained ownership of the mutex object.
[Note 3: 
As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
— end note]
Synchronization: If try_lock_until() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if ownership was obtained, otherwise false.
Throws: Timeout-related exceptions ([thread.req.timing]).

32.6.4.3.2 Class timed_mutex [thread.timedmutex.class]

namespace std { class timed_mutex { public: timed_mutex(); ~timed_mutex(); timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; void lock(); // blocking bool try_lock(); template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class timed_mutex provides a non-recursive mutex with exclusive ownership semantics.
If one thread owns a timed_mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock(), try_lock_for(), and try_lock_until()) until the owning thread has released ownership with a call to unlock() or the call to try_lock_for() or try_lock_until() times out (having failed to obtain ownership).
The class timed_mutex meets all of the timed mutex requirements ([thread.timedmutex.requirements]).
It is a standard-layout class ([class.prop]).
The behavior of a program is undefined if
  • it destroys a timed_mutex object owned by any thread,
  • a thread that owns a timed_mutex object calls lock(), try_lock(), try_lock_for(), or try_lock_until() on that object, or
  • a thread terminates while owning a timed_mutex object.

32.6.4.3.3 Class recursive_timed_mutex [thread.timedmutex.recursive]

namespace std { class recursive_timed_mutex { public: recursive_timed_mutex(); ~recursive_timed_mutex(); recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; void lock(); // blocking bool try_lock() noexcept; template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class recursive_timed_mutex provides a recursive mutex with exclusive ownership semantics.
If one thread owns a recursive_timed_mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock(), try_lock_for(), and try_lock_until()) until the owning thread has completely released ownership or the call to try_lock_for() or try_lock_until() times out (having failed to obtain ownership).
The class recursive_timed_mutex meets all of the timed mutex requirements ([thread.timedmutex.requirements]).
It is a standard-layout class ([class.prop]).
A thread that owns a recursive_timed_mutex object may acquire additional levels of ownership by calling lock(), try_lock(), try_lock_for(), or try_lock_until() on that object.
It is unspecified how many levels of ownership may be acquired by a single thread.
If a thread has already acquired the maximum level of ownership for a recursive_timed_mutex object, additional calls to try_lock(), try_lock_for(), or try_lock_until() fail, and additional calls to lock() throw an exception of type system_error.
A thread shall call unlock() once for each level of ownership acquired by calls to lock(), try_lock(), try_lock_for(), and try_lock_until().
Only when all levels of ownership have been released may ownership of the object be acquired by another thread.
The behavior of a program is undefined if
  • it destroys a recursive_timed_mutex object owned by any thread, or
  • a thread terminates while owning a recursive_timed_mutex object.

32.6.4.4 Shared mutex types [thread.sharedmutex.requirements]

32.6.4.4.1 General [thread.sharedmutex.requirements.general]

The standard library types shared_mutex and shared_timed_mutex are shared mutex types.
Shared mutex types meet the requirements of mutex types ([thread.mutex.requirements.mutex]) and additionally meet the requirements set out below.
In this description, m denotes an object of a shared mutex type.
[Note 1: 
The shared mutex types meet the Cpp17SharedLockable requirements ([thread.req.lockable.shared]).
— end note]
In addition to the exclusive lock ownership mode specified in [thread.mutex.requirements.mutex], shared mutex types provide a shared lock ownership mode.
Multiple execution agents can simultaneously hold a shared lock ownership of a shared mutex type.
But no execution agent holds a shared lock while another execution agent holds an exclusive lock on the same shared mutex type, and vice-versa.
The maximum number of execution agents which can share a shared lock on a single shared mutex type is unspecified, but is at least 10000.
If more than the maximum number of execution agents attempt to obtain a shared lock, the excess execution agents block until the number of shared locks are reduced below the maximum amount by other execution agents releasing their shared lock.
The expression m.lock_shared() is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: Blocks the calling thread until shared ownership of the mutex can be obtained for the calling thread.
If an exception is thrown then a shared lock has not been acquired for the current thread.
Synchronization: Prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Postconditions: The calling thread has a shared lock on the mutex.
Return type: void.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if the thread does not have the privilege to perform the operation.
  • resource_deadlock_would_occur — if the implementation detects that a deadlock would occur.
The expression m.unlock_shared() is well-formed and has the following semantics:
Preconditions: The calling thread holds a shared lock on the mutex.
Effects: Releases a shared lock on the mutex held by the calling thread.
Return type: void.
Synchronization: This operation synchronizes with subsequent lock() operations that obtain ownership on the same object.
Throws: Nothing.
The expression m.try_lock_shared() is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: Attempts to obtain shared ownership of the mutex for the calling thread without blocking.
If shared ownership is not obtained, there is no effect and try_lock_shared() immediately returns.
An implementation may fail to obtain the lock even if it is not held by any other thread.
Synchronization: If try_lock_shared() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if the shared lock was acquired, otherwise false.
Throws: Nothing.

32.6.4.4.2 Class shared_mutex [thread.sharedmutex.class]

namespace std { class shared_mutex { public: shared_mutex(); ~shared_mutex(); shared_mutex(const shared_mutex&) = delete; shared_mutex& operator=(const shared_mutex&) = delete; // exclusive ownership void lock(); // blocking bool try_lock(); void unlock(); // shared ownership void lock_shared(); // blocking bool try_lock_shared(); void unlock_shared(); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class shared_mutex provides a non-recursive mutex with shared ownership semantics.
The class shared_mutex meets all of the shared mutex requirements ([thread.sharedmutex.requirements]).
It is a standard-layout class ([class.prop]).
The behavior of a program is undefined if
  • it destroys a shared_mutex object owned by any thread,
  • a thread attempts to recursively gain any ownership of a shared_mutex, or
  • a thread terminates while possessing any ownership of a shared_mutex.
shared_mutex may be a synonym for shared_timed_mutex.

32.6.4.5 Shared timed mutex types [thread.sharedtimedmutex.requirements]

32.6.4.5.1 General [thread.sharedtimedmutex.requirements.general]

The standard library type shared_timed_mutex is a shared timed mutex type.
Shared timed mutex types meet the requirements of timed mutex types ([thread.timedmutex.requirements]), shared mutex types ([thread.sharedmutex.requirements]), and additionally meet the requirements set out below.
In this description, m denotes an object of a shared timed mutex type, rel_time denotes an object of an instantiation of duration ([time.duration]), and abs_time denotes an object of an instantiation of time_point.
[Note 1: 
The shared timed mutex types meet the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]).
— end note]
The expression m.try_lock_shared_for(rel_time) is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: Attempts to obtain shared lock ownership for the calling thread within the relative timeout ([thread.req.timing]) specified by rel_time.
If the time specified by rel_time is less than or equal to rel_time.zero(), the function attempts to obtain ownership without blocking (as if by calling try_lock_shared()).
The function returns within the timeout specified by rel_time only if it has obtained shared ownership of the mutex object.
[Note 2: 
As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
— end note]
If an exception is thrown then a shared lock has not been acquired for the current thread.
Synchronization: If try_lock_shared_for() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if the shared lock was acquired, otherwise false.
Throws: Timeout-related exceptions ([thread.req.timing]).
The expression m.try_lock_shared_until(abs_time) is well-formed and has the following semantics:
Preconditions: The calling thread has no ownership of the mutex.
Effects: The function attempts to obtain shared ownership of the mutex.
If abs_time has already passed, the function attempts to obtain shared ownership without blocking (as if by calling try_lock_shared()).
The function returns before the absolute timeout ([thread.req.timing]) specified by abs_time only if it has obtained shared ownership of the mutex object.
[Note 3: 
As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
— end note]
If an exception is thrown then a shared lock has not been acquired for the current thread.
Synchronization: If try_lock_shared_until() returns true, prior unlock() operations on the same object synchronize with ([intro.multithread]) this operation.
Return type: bool.
Returns: true if the shared lock was acquired, otherwise false.
Throws: Timeout-related exceptions ([thread.req.timing]).

32.6.4.5.2 Class shared_timed_mutex [thread.sharedtimedmutex.class]

namespace std { class shared_timed_mutex { public: shared_timed_mutex(); ~shared_timed_mutex(); shared_timed_mutex(const shared_timed_mutex&) = delete; shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; // exclusive ownership void lock(); // blocking bool try_lock(); template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); // shared ownership void lock_shared(); // blocking bool try_lock_shared(); template<class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock_shared(); }; }
The class shared_timed_mutex provides a non-recursive mutex with shared ownership semantics.
The class shared_timed_mutex meets all of the shared timed mutex requirements ([thread.sharedtimedmutex.requirements]).
It is a standard-layout class ([class.prop]).
The behavior of a program is undefined if
  • it destroys a shared_timed_mutex object owned by any thread,
  • a thread attempts to recursively gain any ownership of a shared_timed_mutex, or
  • a thread terminates while possessing any ownership of a shared_timed_mutex.

32.6.5 Locks [thread.lock]

32.6.5.1 General [thread.lock.general]

A lock is an object that holds a reference to a lockable object and may unlock the lockable object during the lock's destruction (such as when leaving block scope).
An execution agent may use a lock to aid in managing ownership of a lockable object in an exception safe manner.
A lock is said to own a lockable object if it is currently managing the ownership of that lockable object for an execution agent.
A lock does not manage the lifetime of the lockable object it references.
[Note 1: 
Locks are intended to ease the burden of unlocking the lockable object under both normal and exceptional circumstances.
— end note]
Some lock constructors take tag types which describe what should be done with the lockable object during the lock's construction.
namespace std { struct defer_lock_t { }; // do not acquire ownership of the mutex struct try_to_lock_t { }; // try to acquire ownership of the mutex // without blocking struct adopt_lock_t { }; // assume the calling thread has already // obtained mutex ownership and manage it inline constexpr defer_lock_t defer_lock { }; inline constexpr try_to_lock_t try_to_lock { }; inline constexpr adopt_lock_t adopt_lock { }; }

32.6.5.2 Class template lock_guard [thread.lock.guard]

namespace std { template<class Mutex> class lock_guard { public: using mutex_type = Mutex; explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard(); lock_guard(const lock_guard&) = delete; lock_guard& operator=(const lock_guard&) = delete; private: mutex_type& pm; // exposition only }; }
An object of type lock_guard controls the ownership of a lockable object within a scope.
A lock_guard object maintains ownership of a lockable object throughout the lock_guard object's lifetime.
The behavior of a program is undefined if the lockable object referenced by pm does not exist for the entire lifetime of the lock_guard object.
The supplied Mutex type shall meet the Cpp17BasicLockable requirements ([thread.req.lockable.basic]).
explicit lock_guard(mutex_type& m);
Effects: Initializes pm with m.
Calls m.lock().
lock_guard(mutex_type& m, adopt_lock_t);
Preconditions: The calling thread holds a non-shared lock on m.
Effects: Initializes pm with m.
Throws: Nothing.
~lock_guard();
Effects: Equivalent to: pm.unlock()

32.6.5.3 Class template scoped_lock [thread.lock.scoped]

namespace std { template<class... MutexTypes> class scoped_lock { public: using mutex_type = see below; // Only if sizeof...(MutexTypes) == 1 is true explicit scoped_lock(MutexTypes&... m); explicit scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock(); scoped_lock(const scoped_lock&) = delete; scoped_lock& operator=(const scoped_lock&) = delete; private: tuple<MutexTypes&...> pm; // exposition only }; }
An object of type scoped_lock controls the ownership of lockable objects within a scope.
A scoped_lock object maintains ownership of lockable objects throughout the scoped_lock object's lifetime.
The behavior of a program is undefined if the lockable objects referenced by pm do not exist for the entire lifetime of the scoped_lock object.
explicit scoped_lock(MutexTypes&... m);
Effects: Initializes pm with tie(m...).
Then if sizeof...(MutexTypes) is 0, no effects.
Otherwise if sizeof...(MutexTypes) is 1, then m.lock().
Otherwise, lock(m...).
explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
Preconditions: The calling thread holds a non-shared lock on each element of m.
Effects: Initializes pm with tie(m...).
Throws: Nothing.
~scoped_lock();
Effects: For all i in [0, sizeof...(MutexTypes)), get<i>(pm).unlock().

32.6.5.4 Class template unique_lock [thread.lock.unique]

32.6.5.4.1 General [thread.lock.unique.general]

namespace std { template<class Mutex> class unique_lock { public: using mutex_type = Mutex; // [thread.lock.unique.cons], construct/copy/destroy unique_lock() noexcept; explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); ~unique_lock(); unique_lock(const unique_lock&) = delete; unique_lock& operator=(const unique_lock&) = delete; unique_lock(unique_lock&& u) noexcept; unique_lock& operator=(unique_lock&& u); // [thread.lock.unique.locking], locking void lock(); bool try_lock(); template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); // [thread.lock.unique.mod], modifiers void swap(unique_lock& u) noexcept; mutex_type* release() noexcept; // [thread.lock.unique.obs], observers bool owns_lock() const noexcept; explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: mutex_type* pm; // exposition only bool owns; // exposition only }; }
An object of type unique_lock controls the ownership of a lockable object within a scope.
Ownership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another unique_lock object.
Objects of type unique_lock are not copyable but are movable.
The behavior of a program is undefined if the contained pointer pm is not null and the lockable object pointed to by pm does not exist for the entire remaining lifetime ([basic.life]) of the unique_lock object.
The supplied Mutex type shall meet the Cpp17BasicLockable requirements ([thread.req.lockable.basic]).
[Note 1: 
unique_lock<Mutex> meets the Cpp17BasicLockable requirements.
If Mutex meets the Cpp17Lockable requirements ([thread.req.lockable.req]), unique_lock<Mutex> also meets the Cpp17Lockable requirements; if Mutex meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]), unique_lock<Mutex> also meets the Cpp17TimedLockable requirements.
— end note]

32.6.5.4.2 Constructors, destructor, and assignment [thread.lock.unique.cons]

unique_lock() noexcept;
Postconditions: pm == nullptr and owns == false.
explicit unique_lock(mutex_type& m);
Effects: Calls m.lock().
Postconditions: pm == addressof(m) and owns == true.
unique_lock(mutex_type& m, defer_lock_t) noexcept;
Postconditions: pm == addressof(m) and owns == false.
unique_lock(mutex_type& m, try_to_lock_t);
Preconditions: The supplied Mutex type meets the Cpp17Lockable requirements ([thread.req.lockable.req]).
Effects: Calls m.try_lock().
Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock().
unique_lock(mutex_type& m, adopt_lock_t);
Preconditions: The calling thread holds a non-shared lock on m.
Postconditions: pm == addressof(m) and owns == true.
Throws: Nothing.
template<class Clock, class Duration> unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
Effects: Calls m.try_lock_until(abs_time).
Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock_until(abs_time).
template<class Rep, class Period> unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
Effects: Calls m.try_lock_for(rel_time).
Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock_for(rel_time).
unique_lock(unique_lock&& u) noexcept;
Postconditions: pm == u_p.pm and owns == u_p.owns (where u_p is the state of u just prior to this construction), u.pm == 0 and u.owns == false.
unique_lock& operator=(unique_lock&& u);
Effects: If owns calls pm->unlock().
Postconditions: pm == u_p.pm and owns == u_p.owns (where u_p is the state of u just prior to this construction), u.pm == 0 and u.owns == false.
[Note 1: 
With a recursive mutex it is possible for both *this and u to own the same mutex before the assignment.
In this case, *this will own the mutex after the assignment and u will not.
— end note]
Throws: Nothing.
~unique_lock();
Effects: If owns calls pm->unlock().

32.6.5.4.3 Locking [thread.lock.unique.locking]

void lock();
Effects: As if by pm->lock().
Postconditions: owns == true.
Throws: Any exception thrown by pm->lock().
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
bool try_lock();
Preconditions: The supplied Mutex meets the Cpp17Lockable requirements ([thread.req.lockable.req]).
Effects: As if by pm->try_lock().
Postconditions: owns == res, where res is the value returned by pm->try_lock().
Returns: The value returned by pm->try_lock().
Throws: Any exception thrown by pm->try_lock().
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
Effects: As if by pm->try_lock_until(abs_time).
Postconditions: owns == res, where res is the value returned by pm->try_lock_until(abs_time).
Returns: The value returned by pm->try_lock_until(abs_time).
Throws: Any exception thrown by pm->try_lock_until(abstime).
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
Effects: As if by pm->try_lock_for(rel_time).
Postconditions: owns == res, where res is the value returned by pm->try_lock_for(rel_time).
Returns: The value returned by pm->try_lock_for(rel_time).
Throws: Any exception thrown by pm->try_lock_for(rel_time).
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
void unlock();
Effects: As if by pm->unlock().
Postconditions: owns == false.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if on entry owns is false.

32.6.5.4.4 Modifiers [thread.lock.unique.mod]

void swap(unique_lock& u) noexcept;
Effects: Swaps the data members of *this and u.
mutex_type* release() noexcept;
Postconditions: pm == 0 and owns == false.
Returns: The previous value of pm.
template<class Mutex> void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
Effects: As if by x.swap(y).

32.6.5.4.5 Observers [thread.lock.unique.obs]

bool owns_lock() const noexcept;
Returns: owns.
explicit operator bool() const noexcept;
Returns: owns.
mutex_type *mutex() const noexcept;
Returns: pm.

32.6.5.5 Class template shared_lock [thread.lock.shared]

32.6.5.5.1 General [thread.lock.shared.general]

namespace std { template<class Mutex> class shared_lock { public: using mutex_type = Mutex; // [thread.lock.shared.cons], construct/copy/destroy shared_lock() noexcept; explicit shared_lock(mutex_type& m); // blocking shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration> shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); template<class Rep, class Period> shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); ~shared_lock(); shared_lock(const shared_lock&) = delete; shared_lock& operator=(const shared_lock&) = delete; shared_lock(shared_lock&& u) noexcept; shared_lock& operator=(shared_lock&& u) noexcept; // [thread.lock.shared.locking], locking void lock(); // blocking bool try_lock(); template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); void unlock(); // [thread.lock.shared.mod], modifiers void swap(shared_lock& u) noexcept; mutex_type* release() noexcept; // [thread.lock.shared.obs], observers bool owns_lock() const noexcept; explicit operator bool() const noexcept; mutex_type* mutex() const noexcept; private: mutex_type* pm; // exposition only bool owns; // exposition only }; }
An object of type shared_lock controls the shared ownership of a lockable object within a scope.
Shared ownership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another shared_lock object.
Objects of type shared_lock are not copyable but are movable.
The behavior of a program is undefined if the contained pointer pm is not null and the lockable object pointed to by pm does not exist for the entire remaining lifetime ([basic.life]) of the shared_lock object.
The supplied Mutex type shall meet the Cpp17SharedLockable requirements ([thread.req.lockable.shared]).
[Note 1: 
shared_lock<Mutex> meets the Cpp17Lockable requirements ([thread.req.lockable.req]).
If Mutex meets the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]), shared_lock<Mutex> also meets the Cpp17TimedLockable requirements ([thread.req.lockable.timed]).
— end note]

32.6.5.5.2 Constructors, destructor, and assignment [thread.lock.shared.cons]

shared_lock() noexcept;
Postconditions: pm == nullptr and owns == false.
explicit shared_lock(mutex_type& m);
Effects: Calls m.lock_shared().
Postconditions: pm == addressof(m) and owns == true.
shared_lock(mutex_type& m, defer_lock_t) noexcept;
Postconditions: pm == addressof(m) and owns == false.
shared_lock(mutex_type& m, try_to_lock_t);
Effects: Calls m.try_lock_shared().
Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared().
shared_lock(mutex_type& m, adopt_lock_t);
Preconditions: The calling thread holds a shared lock on m.
Postconditions: pm == addressof(m) and owns == true.
template<class Clock, class Duration> shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]).
Effects: Calls m.try_lock_shared_until(abs_time).
Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_until(abs_time).
template<class Rep, class Period> shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]).
Effects: Calls m.try_lock_shared_for(rel_time).
Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_for(rel_time).
~shared_lock();
Effects: If owns calls pm->unlock_shared().
shared_lock(shared_lock&& sl) noexcept;
Postconditions: pm == sl_p.pm and owns == sl_p.owns (where sl_p is the state of sl just prior to this construction), sl.pm == nullptr and sl.owns == false.
shared_lock& operator=(shared_lock&& sl) noexcept;
Effects: If owns calls pm->unlock_shared().
Postconditions: pm == sl_p.pm and owns == sl_p.owns (where sl_p is the state of sl just prior to this assignment), sl.pm == nullptr and sl.owns == false.

32.6.5.5.3 Locking [thread.lock.shared.locking]

void lock();
Effects: As if by pm->lock_shared().
Postconditions: owns == true.
Throws: Any exception thrown by pm->lock_shared().
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
bool try_lock();
Effects: As if by pm->try_lock_shared().
Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared().
Returns: The value returned by the call to pm->try_lock_shared().
Throws: Any exception thrown by pm->try_lock_shared().
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
template<class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]).
Effects: As if by pm->try_lock_shared_until(abs_time).
Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared_until(abs_time).
Returns: The value returned by the call to pm->try_lock_shared_until(abs_time).
Throws: Any exception thrown by pm->try_lock_shared_until(abs_time).
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
template<class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements ([thread.req.lockable.shared.timed]).
Effects: As if by pm->try_lock_shared_for(rel_time).
Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared_for(rel_time).
Returns: The value returned by the call to pm->try_lock_shared_for(rel_time).
Throws: Any exception thrown by pm->try_lock_shared_for(rel_time).
system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if pm is nullptr.
  • resource_deadlock_would_occur — if on entry owns is true.
void unlock();
Effects: As if by pm->unlock_shared().
Postconditions: owns == false.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • operation_not_permitted — if on entry owns is false.

32.6.5.5.4 Modifiers [thread.lock.shared.mod]

void swap(shared_lock& sl) noexcept;
Effects: Swaps the data members of *this and sl.
mutex_type* release() noexcept;
Postconditions: pm == nullptr and owns == false.
Returns: The previous value of pm.
template<class Mutex> void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
Effects: As if by x.swap(y).

32.6.5.5.5 Observers [thread.lock.shared.obs]

bool owns_lock() const noexcept;
Returns: owns.
explicit operator bool() const noexcept;
Returns: owns.
mutex_type* mutex() const noexcept;
Returns: pm.

32.6.6 Generic locking algorithms [thread.lock.algorithm]

template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
Preconditions: Each template parameter type meets the Cpp17Lockable requirements.
[Note 1: 
The unique_lock class template meets these requirements when suitably instantiated.
— end note]
Effects: Calls try_lock() for each argument in order beginning with the first until all arguments have been processed or a call to try_lock() fails, either by returning false or by throwing an exception.
If a call to try_lock() fails, unlock() is called for all prior arguments with no further calls to try_lock().
Returns: -1 if all calls to try_lock() returned true, otherwise a zero-based index value that indicates the argument for which try_lock() returned false.
template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
Preconditions: Each template parameter type meets the Cpp17Lockable requirements.
[Note 2: 
The unique_lock class template meets these requirements when suitably instantiated.
— end note]
Effects: All arguments are locked via a sequence of calls to lock(), try_lock(), or unlock() on each argument.
The sequence of calls does not result in deadlock, but is otherwise unspecified.
[Note 3: 
A deadlock avoidance algorithm such as try-and-back-off can be used, but the specific algorithm is not specified to avoid over-constraining implementations.
— end note]
If a call to lock() or try_lock() throws an exception, unlock() is called for any argument that had been locked by a call to lock() or try_lock().

32.6.7 Call once [thread.once]

32.6.7.1 Struct once_flag [thread.once.onceflag]

namespace std { struct once_flag { constexpr once_flag() noexcept; once_flag(const once_flag&) = delete; once_flag& operator=(const once_flag&) = delete; }; }
The class once_flag is an opaque data structure that call_once uses to initialize data without causing a data race or deadlock.
constexpr once_flag() noexcept;
Synchronization: The construction of a once_flag object is not synchronized.
Postconditions: The object's internal state is set to indicate to an invocation of call_once with the object as its initial argument that no function has been called.

32.6.7.2 Function call_once [thread.once.callonce]

template<class Callable, class... Args> void call_once(once_flag& flag, Callable&& func, Args&&... args);
Mandates: is_invocable_v<Callable, Args...> is true.
Effects: An execution of call_once that does not call its func is a passive execution.
An execution of call_once that calls its func is an active execution.
An active execution evaluates INVOKE(​std​::​forward<Callable>(func), std​::​forward<Args>(args)...) ([func.require]).
If such a call to func throws an exception the execution is exceptional, otherwise it is returning.
An exceptional execution propagates the exception to the caller of call_once.
Among all executions of call_once for any given once_flag: at most one is a returning execution; if there is a returning execution, it is the last active execution; and there are passive executions only if there is a returning execution.
[Note 1: 
Passive executions allow other threads to reliably observe the results produced by the earlier returning execution.
— end note]
Synchronization: For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes with the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.
Throws: system_error when an exception is required ([thread.req.exception]), or any exception thrown by func.
[Example 1: // global flag, regular function void init(); std::once_flag flag; void f() { std::call_once(flag, init); } // function static flag, function object struct initializer { void operator()(); }; void g() { static std::once_flag flag2; std::call_once(flag2, initializer()); } // object flag, member function class information { std::once_flag verified; void verifier(); public: void verify() { std::call_once(verified, &information::verifier, *this); } }; — end example]

32.7 Condition variables [thread.condition]

32.7.1 General [thread.condition.general]

Condition variables provide synchronization primitives used to block a thread until notified by some other thread that some condition is met or until a system time is reached.
Class condition_variable provides a condition variable that can only wait on an object of type unique_lock<mutex>, allowing the implementation to be more efficient.
Class condition_variable_any provides a general condition variable that can wait on objects of user-supplied lock types.
Condition variables permit concurrent invocation of the wait, wait_for, wait_until, notify_one and notify_all member functions.
The executions of notify_one and notify_all are atomic.
The executions of wait, wait_for, and wait_until are performed in three atomic parts:
1.the release of the mutex and entry into the waiting state;
2.the unblocking of the wait; and
3.the reacquisition of the lock.
The implementation behaves as if all executions of notify_one, notify_all, and each part of the wait, wait_for, and wait_until executions are executed in a single unspecified total order consistent with the “happens before” order.
Condition variable construction and destruction need not be synchronized.

32.7.2 Header <condition_variable> synopsis [condition.variable.syn]

namespace std { // [thread.condition.condvar], class condition_variable class condition_variable; // [thread.condition.condvarany], class condition_variable_any class condition_variable_any; // [thread.condition.nonmember], non-member functions void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); enum class cv_status { no_timeout, timeout }; }

32.7.3 Non-member functions [thread.condition.nonmember]

void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
Preconditions: lk is locked by the calling thread and either
  • no other thread is waiting on cond, or
  • lk.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects: Transfers ownership of the lock associated with lk into internal storage and schedules cond to be notified when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed.
This notification is equivalent to: lk.unlock(); cond.notify_all();
Synchronization: The implied lk.unlock() call is sequenced after the destruction of all objects with thread storage duration associated with the current thread.
[Note 1: 
The supplied lock is held until the thread exits, which might cause deadlock due to lock ordering issues.
— end note]
[Note 2: 
It is the user's responsibility to ensure that waiting threads do not incorrectly assume that the thread has finished if they experience spurious wakeups.
This typically requires that the condition being waited for is satisfied while holding the lock on lk, and that this lock is not released and reacquired prior to calling notify_all_at_thread_exit.
— end note]

32.7.4 Class condition_variable [thread.condition.condvar]

namespace std { class condition_variable { public: condition_variable(); ~condition_variable(); condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete; void notify_one() noexcept; void notify_all() noexcept; void wait(unique_lock<mutex>& lock); template<class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred); template<class Clock, class Duration> cv_status wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time); template<class Clock, class Duration, class Predicate> bool wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time); template<class Rep, class Period, class Predicate> bool wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred); using native_handle_type = implementation-defined; // see [thread.req.native] native_handle_type native_handle(); // see [thread.req.native] }; }
The class condition_variable is a standard-layout class ([class.prop]).
condition_variable();
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • resource_unavailable_try_again — if some non-memory resource limitation prevents initialization.
~condition_variable();
Preconditions: There is no thread blocked on *this.
[Note 1: 
That is, all threads have been notified; they can subsequently block on the lock specified in the wait.
This relaxes the usual rules, which would have required all wait calls to happen before destruction.
Only the notification to unblock the wait needs to happen before destruction.
Undefined behavior ensues if a thread waits on *this once the destructor has been started, especially when the waiting threads are calling the wait functions in a loop or using the overloads of wait, wait_for, or wait_until that take a predicate.
— end note]
void notify_one() noexcept;
Effects: If any threads are blocked waiting for *this, unblocks one of those threads.
void notify_all() noexcept;
Effects: Unblocks all threads that are blocked waiting for *this.
void wait(unique_lock<mutex>& lock);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock), then returns.
  • The function will unblock when signaled by a call to notify_one() or a call to notify_all(), or spuriously.
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
Throws: Nothing.
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 2: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects: Equivalent to: while (!pred()) wait(lock);
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
Throws: Any exception thrown by pred.
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 3: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Clock, class Duration> cv_status wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock), then returns.
  • The function will unblock when signaled by a call to notify_one(), a call to notify_all(), expiration of the absolute timeout ([thread.req.timing]) specified by abs_time, or spuriously.
  • If the function exits via an exception, lock.lock() is called prior to exiting the function.
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
Returns: cv_status​::​timeout if the absolute timeout ([thread.req.timing]) specified by abs_time expired, otherwise cv_status​::​no_timeout.
Throws: Timeout-related exceptions ([thread.req.timing]).
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 4: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects: Equivalent to: return wait_until(lock, chrono::steady_clock::now() + rel_time);
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
Returns: cv_status​::​timeout if the relative timeout ([thread.req.timing]) specified by rel_time expired, otherwise cv_status​::​no_timeout.
Throws: Timeout-related exceptions ([thread.req.timing]).
Remarks: If the function fails to meet the postcondition, terminate is invoked ([except.terminate]).
[Note 5: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Clock, class Duration, class Predicate> bool wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects: Equivalent to: while (!pred()) if (wait_until(lock, abs_time) == cv_status::timeout) return pred(); return true;
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
[Note 6: 
The returned value indicates whether the predicate evaluated to true regardless of whether the timeout was triggered.
— end note]
Throws: Timeout-related exceptions ([thread.req.timing]) or any exception thrown by pred.
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 7: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Rep, class Period, class Predicate> bool wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
Preconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread, and either
  • no other thread is waiting on this condition_variable object or
  • lock.mutex() returns the same value for each of the lock arguments supplied by all concurrently waiting (via wait, wait_for, or wait_until) threads.
Effects: Equivalent to: return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));
[Note 8: 
There is no blocking if pred() is initially true, even if the timeout has already expired.
— end note]
Postconditions: lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
[Note 9: 
The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered.
— end note]
Throws: Timeout-related exceptions ([thread.req.timing]) or any exception thrown by pred.
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 10: 
This can happen if the re-locking of the mutex throws an exception.
— end note]

32.7.5 Class condition_variable_any [thread.condition.condvarany]

32.7.5.1 General [thread.condition.condvarany.general]

In [thread.condition.condvarany], template arguments for template parameters named Lock shall meet the Cpp17BasicLockable requirements ([thread.req.lockable.basic]).
[Note 1: 
All of the standard mutex types meet this requirement.
If a type other than one of the standard mutex types or a unique_lock wrapper for a standard mutex type is used with condition_variable_any, any necessary synchronization is assumed to be in place with respect to the predicate associated with the condition_variable_any instance.
— end note]
namespace std { class condition_variable_any { public: condition_variable_any(); ~condition_variable_any(); condition_variable_any(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete; void notify_one() noexcept; void notify_all() noexcept; // [thread.condvarany.wait], noninterruptible waits template<class Lock> void wait(Lock& lock); template<class Lock, class Predicate> void wait(Lock& lock, Predicate pred); template<class Lock, class Clock, class Duration> cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time); template<class Lock, class Clock, class Duration, class Predicate> bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template<class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time); template<class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred); // [thread.condvarany.intwait], interruptible waits template<class Lock, class Predicate> bool wait(Lock& lock, stop_token stoken, Predicate pred); template<class Lock, class Clock, class Duration, class Predicate> bool wait_until(Lock& lock, stop_token stoken, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template<class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, stop_token stoken, const chrono::duration<Rep, Period>& rel_time, Predicate pred); }; }
condition_variable_any();
Throws: bad_alloc or system_error when an exception is required ([thread.req.exception]).
Error conditions:
  • resource_unavailable_try_again — if some non-memory resource limitation prevents initialization.
  • operation_not_permitted — if the thread does not have the privilege to perform the operation.
~condition_variable_any();
Preconditions: There is no thread blocked on *this.
[Note 2: 
That is, all threads have been notified; they can subsequently block on the lock specified in the wait.
This relaxes the usual rules, which would have required all wait calls to happen before destruction.
Only the notification to unblock the wait needs to happen before destruction.
Undefined behavior ensues if a thread waits on *this once the destructor has been started, especially when the waiting threads are calling the wait functions in a loop or using the overloads of wait, wait_for, or wait_until that take a predicate.
— end note]
void notify_one() noexcept;
Effects: If any threads are blocked waiting for *this, unblocks one of those threads.
void notify_all() noexcept;
Effects: Unblocks all threads that are blocked waiting for *this.

32.7.5.2 Noninterruptible waits [thread.condvarany.wait]

template<class Lock> void wait(Lock& lock);
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when signaled by a call to notify_one(), a call to notify_all(), or spuriously.
Postconditions: lock is locked by the calling thread.
Throws: Nothing.
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 1: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Lock, class Predicate> void wait(Lock& lock, Predicate pred);
Effects: Equivalent to: while (!pred()) wait(lock);
template<class Lock, class Clock, class Duration> cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time);
Effects:
  • Atomically calls lock.unlock() and blocks on *this.
  • When unblocked, calls lock.lock() (possibly blocking on the lock) and returns.
  • The function will unblock when signaled by a call to notify_one(), a call to notify_all(), expiration of the absolute timeout ([thread.req.timing]) specified by abs_time, or spuriously.
  • If the function exits via an exception, lock.lock() is called prior to exiting the function.
Postconditions: lock is locked by the calling thread.
Returns: cv_status​::​timeout if the absolute timeout ([thread.req.timing]) specified by abs_time expired, otherwise cv_status​::​no_timeout.
Throws: Timeout-related exceptions ([thread.req.timing]).
Remarks: If the function fails to meet the postcondition, terminate() is invoked ([except.terminate]).
[Note 2: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time);
Effects: Equivalent to: return wait_until(lock, chrono::steady_clock::now() + rel_time);
Postconditions: lock is locked by the calling thread.
Returns: cv_status​::​timeout if the relative timeout ([thread.req.timing]) specified by rel_time expired, otherwise cv_status​::​no_timeout.
Throws: Timeout-related exceptions ([thread.req.timing]).
Remarks: If the function fails to meet the postcondition, terminate is invoked ([except.terminate]).
[Note 3: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Lock, class Clock, class Duration, class Predicate> bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
Effects: Equivalent to: while (!pred()) if (wait_until(lock, abs_time) == cv_status::timeout) return pred(); return true;
[Note 4: 
There is no blocking if pred() is initially true, or if the timeout has already expired.
— end note]
[Note 5: 
The returned value indicates whether the predicate evaluates to true regardless of whether the timeout was triggered.
— end note]
template<class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
Effects: Equivalent to: return wait_until(lock, chrono::steady_clock::now() + rel_time, std::move(pred));

32.7.5.3 Interruptible waits [thread.condvarany.intwait]

The following wait functions will be notified when there is a stop request on the passed stop_token.
In that case the functions return immediately, returning false if the predicate evaluates to false.
template<class Lock, class Predicate> bool wait(Lock& lock, stop_token stoken, Predicate pred);
Effects: Registers for the duration of this call *this to get notified on a stop request on stoken during this call and then equivalent to: while (!stoken.stop_requested()) { if (pred()) return true; wait(lock); } return pred();
[Note 1: 
The returned value indicates whether the predicate evaluated to true regardless of whether there was a stop request.
— end note]
Postconditions: lock is locked by the calling thread.
Throws: Any exception thrown by pred.
Remarks: If the function fails to meet the postcondition, terminate is called ([except.terminate]).
[Note 2: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Lock, class Clock, class Duration, class Predicate> bool wait_until(Lock& lock, stop_token stoken, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
Effects: Registers for the duration of this call *this to get notified on a stop request on stoken during this call and then equivalent to: while (!stoken.stop_requested()) { if (pred()) return true; if (wait_until(lock, abs_time) == cv_status::timeout) return pred(); } return pred();
[Note 3: 
There is no blocking if pred() is initially true, stoken.stop_requested() was already true or the timeout has already expired.
— end note]
[Note 4: 
The returned value indicates whether the predicate evaluated to true regardless of whether the timeout was triggered or a stop request was made.
— end note]
Postconditions: lock is locked by the calling thread.
Throws: Timeout-related exceptions ([thread.req.timing]), or any exception thrown by pred.
Remarks: If the function fails to meet the postcondition, terminate is called ([except.terminate]).
[Note 5: 
This can happen if the re-locking of the mutex throws an exception.
— end note]
template<class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, stop_token stoken, const chrono::duration<Rep, Period>& rel_time, Predicate pred);
Effects: Equivalent to: return wait_until(lock, std::move(stoken), chrono::steady_clock::now() + rel_time, std::move(pred));

32.8 Semaphore [thread.sema]

32.8.1 General [thread.sema.general]

Semaphores are lightweight synchronization primitives used to constrain concurrent access to a shared resource.
They are widely used to implement other synchronization primitives and, whenever both are applicable, can be more efficient than condition variables.
A counting semaphore is a semaphore object that models a non-negative resource count.
A binary semaphore is a semaphore object that has only two states.
A binary semaphore should be more efficient than the default implementation of a counting semaphore with a unit resource count.

32.8.2 Header <semaphore> synopsis [semaphore.syn]

namespace std { // [thread.sema.cnt], class template counting_semaphore template<ptrdiff_t least_max_value = implementation-defined> class counting_semaphore; using binary_semaphore = counting_semaphore<1>; }

32.8.3 Class template counting_semaphore [thread.sema.cnt]

namespace std { template<ptrdiff_t least_max_value = implementation-defined> class counting_semaphore { public: static constexpr ptrdiff_t max() noexcept; constexpr explicit counting_semaphore(ptrdiff_t desired); ~counting_semaphore(); counting_semaphore(const counting_semaphore&) = delete; counting_semaphore& operator=(const counting_semaphore&) = delete; void release(ptrdiff_t update = 1); void acquire(); bool try_acquire() noexcept; template<class Rep, class Period> bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time); private: ptrdiff_t counter; // exposition only }; }
Class template counting_semaphore maintains an internal counter that is initialized when the semaphore is created.
The counter is decremented when a thread acquires the semaphore, and is incremented when a thread releases the semaphore.
If a thread tries to acquire the semaphore when the counter is zero, the thread will block until another thread increments the counter by releasing the semaphore.
least_max_value shall be non-negative; otherwise the program is ill-formed.
Concurrent invocations of the member functions of counting_semaphore, other than its destructor, do not introduce data races.
static constexpr ptrdiff_t max() noexcept;
Returns: The maximum value of counter.
This value is greater than or equal to least_max_value.
constexpr explicit counting_semaphore(ptrdiff_t desired);
Preconditions: desired >= 0 is true, and desired <= max() is true.
Effects: Initializes counter with desired.
Throws: Nothing.
void release(ptrdiff_t update = 1);
Preconditions: update >= 0 is true, and update <= max() - counter is true.
Effects: Atomically execute counter += update.
Then, unblocks any threads that are waiting for counter to be greater than zero.
Synchronization: Strongly happens before invocations of try_acquire that observe the result of the effects.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
bool try_acquire() noexcept;
Effects: Attempts to atomically decrement counter if it is positive, without blocking.
If counter is not decremented, there is no effect and try_acquire immediately returns.
An implementation may fail to decrement counter even if it is positive.
[Note 1: 
This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange ([atomics]).
— end note]
An implementation should ensure that try_acquire does not consistently return false in the absence of contending semaphore operations.
Returns: true if counter was decremented, otherwise false.
void acquire();
Effects: Repeatedly performs the following steps, in order:
  • Evaluates try_acquire().
    If the result is true, returns.
  • Blocks on *this until counter is greater than zero.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
template<class Rep, class Period> bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration> bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time);
Effects: Repeatedly performs the following steps, in order:
  • Evaluates try_acquire().
    If the result is true, returns true.
  • Blocks on *this until counter is greater than zero or until the timeout expires.
    If it is unblocked by the timeout expiring, returns false.
The timeout expires ([thread.req.timing]) when the current time is after abs_time (for try_acquire_until) or when at least rel_time has passed from the start of the function (for try_acquire_for).
Throws: Timeout-related exceptions ([thread.req.timing]), or system_error when a non-timeout-related exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).

32.9 Coordination types [thread.coord]

32.9.1 General [thread.coord.general]

Subclause [thread.coord] describes various concepts related to thread coordination, and defines the coordination types latch and barrier.
These types facilitate concurrent computation performed by a number of threads.

32.9.2 Latches [thread.latch]

32.9.2.1 General [thread.latch.general]

A latch is a thread coordination mechanism that allows any number of threads to block until an expected number of threads arrive at the latch (via the count_down function).
The expected count is set when the latch is created.
An individual latch is a single-use object; once the expected count has been reached, the latch cannot be reused.

32.9.2.2 Header <latch> synopsis [latch.syn]

namespace std { class latch; }

32.9.2.3 Class latch [thread.latch.class]

namespace std { class latch { public: static constexpr ptrdiff_t max() noexcept; constexpr explicit latch(ptrdiff_t expected); ~latch(); latch(const latch&) = delete; latch& operator=(const latch&) = delete; void count_down(ptrdiff_t update = 1); bool try_wait() const noexcept; void wait() const; void arrive_and_wait(ptrdiff_t update = 1); private: ptrdiff_t counter; // exposition only }; }
A latch maintains an internal counter that is initialized when the latch is created.
Threads can block on the latch object, waiting for counter to be decremented to zero.
Concurrent invocations of the member functions of latch, other than its destructor, do not introduce data races.
static constexpr ptrdiff_t max() noexcept;
Returns: The maximum value of counter that the implementation supports.
constexpr explicit latch(ptrdiff_t expected);
Preconditions: expected >= 0 is true and expected <= max() is true.
Effects: Initializes counter with expected.
Throws: Nothing.
void count_down(ptrdiff_t update = 1);
Preconditions: update >= 0 is true, and update <= counter is true.
Effects: Atomically decrements counter by update.
If counter is equal to zero, unblocks all threads blocked on *this.
Synchronization: Strongly happens before the returns from all calls that are unblocked.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
bool try_wait() const noexcept;
Returns: With very low probability false.
Otherwise counter == 0.
void wait() const;
Effects: If counter equals zero, returns immediately.
Otherwise, blocks on *this until a call to count_down that decrements counter to zero.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
void arrive_and_wait(ptrdiff_t update = 1);
Effects: Equivalent to: count_down(update); wait();

32.9.3 Barriers [thread.barrier]

32.9.3.1 General [thread.barrier.general]

A barrier is a thread coordination mechanism whose lifetime consists of a sequence of barrier phases, where each phase allows at most an expected number of threads to block until the expected number of threads arrive at the barrier.
[Note 1: 
A barrier is useful for managing repeated tasks that are handled by multiple threads.
— end note]

32.9.3.2 Header <barrier> synopsis [barrier.syn]

namespace std { template<class CompletionFunction = see below> class barrier; }

32.9.3.3 Class template barrier [thread.barrier.class]

namespace std { template<class CompletionFunction = see below> class barrier { public: using arrival_token = see below; static constexpr ptrdiff_t max() noexcept; constexpr explicit barrier(ptrdiff_t expected, CompletionFunction f = CompletionFunction()); ~barrier(); barrier(const barrier&) = delete; barrier& operator=(const barrier&) = delete; arrival_token arrive(ptrdiff_t update = 1); void wait(arrival_token&& arrival) const; void arrive_and_wait(); void arrive_and_drop(); private: CompletionFunction completion; // exposition only }; }
Each barrier phase consists of the following steps:
  • The expected count is decremented by each call to arrive or arrive_and_drop.
  • Exactly once after the expected count reaches zero, a thread executes the completion step during its call to arrive, arrive_and_drop, or wait, except that it is implementation-defined whether the step executes if no thread calls wait.
  • When the completion step finishes, the expected count is reset to what was specified by the expected argument to the constructor, possibly adjusted by calls to arrive_and_drop, and the next phase starts.
Each phase defines a phase synchronization point.
Threads that arrive at the barrier during the phase can block on the phase synchronization point by calling wait, and will remain blocked until the phase completion step is run.
The phase completion step that is executed at the end of each phase has the following effects:
  • Invokes the completion function, equivalent to completion().
  • Unblocks all threads that are blocked on the phase synchronization point.
The end of the completion step strongly happens before the returns from all calls that were unblocked by the completion step.
For specializations that do not have the default value of the CompletionFunction template parameter, the behavior is undefined if any of the barrier object's member functions other than wait are called while the completion step is in progress.
Concurrent invocations of the member functions of barrier, other than its destructor, do not introduce data races.
The member functions arrive and arrive_and_drop execute atomically.
CompletionFunction shall meet the Cpp17MoveConstructible (Table 31) and Cpp17Destructible (Table 35) requirements.
is_nothrow_invocable_v<CompletionFunction&> shall be true.
The default value of the CompletionFunction template parameter is an unspecified type, such that, in addition to satisfying the requirements of CompletionFunction, it meets the Cpp17DefaultConstructible requirements (Table 30) and completion() has no effects.
barrier​::​arrival_token is an unspecified type, such that it meets the Cpp17MoveConstructible (Table 31), Cpp17MoveAssignable (Table 33), and Cpp17Destructible (Table 35) requirements.
static constexpr ptrdiff_t max() noexcept;
Returns: The maximum expected count that the implementation supports.
constexpr explicit barrier(ptrdiff_t expected, CompletionFunction f = CompletionFunction());
Preconditions: expected >= 0 is true and expected <= max() is true.
Effects: Sets both the initial expected count for each barrier phase and the current expected count for the first phase to expected.
Initializes completion with std​::​move(f).
Starts the first phase.
[Note 1: 
If expected is 0 this object can only be destroyed.
— end note]
Throws: Any exception thrown by CompletionFunction's move constructor.
arrival_token arrive(ptrdiff_t update = 1);
Preconditions: update > 0 is true, and update is less than or equal to the expected count for the current barrier phase.
Effects: Constructs an object of type arrival_token that is associated with the phase synchronization point for the current phase.
Then, decrements the expected count by update.
Synchronization: The call to arrive strongly happens before the start of the phase completion step for the current phase.
Returns: The constructed arrival_token object.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
[Note 2: 
This call can cause the completion step for the current phase to start.
— end note]
void wait(arrival_token&& arrival) const;
Preconditions: arrival is associated with the phase synchronization point for the current phase or the immediately preceding phase of the same barrier object.
Effects: Blocks at the synchronization point associated with std​::​move(arrival) until the phase completion step of the synchronization point's phase is run.
[Note 3: 
If arrival is associated with the synchronization point for a previous phase, the call returns immediately.
— end note]
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
void arrive_and_wait();
Effects: Equivalent to: wait(arrive()).
void arrive_and_drop();
Preconditions: The expected count for the current barrier phase is greater than zero.
Effects: Decrements the initial expected count for all subsequent phases by one.
Then decrements the expected count for the current phase by one.
Synchronization: The call to arrive_and_drop strongly happens before the start of the phase completion step for the current phase.
Throws: system_error when an exception is required ([thread.req.exception]).
Error conditions: Any of the error conditions allowed for mutex types ([thread.mutex.requirements.mutex]).
[Note 4: 
This call can cause the completion step for the current phase to start.
— end note]

32.10 Futures [futures]

32.10.1 Overview [futures.overview]

[futures] describes components that a C++ program can use to retrieve in one thread the result (value or exception) from a function that has run in the same thread or another thread.
[Note 1: 
These components are not restricted to multi-threaded programs but can be useful in single-threaded programs as well.
— end note]

32.10.2 Header <future> synopsis [future.syn]

namespace std { enum class future_errc { broken_promise = implementation-defined, future_already_retrieved = implementation-defined, promise_already_satisfied = implementation-defined, no_state = implementation-defined }; enum class launch : unspecified { async = unspecified, deferred = unspecified, implementation-defined }; enum class future_status { ready, timeout, deferred }; // [futures.errors], error handling template<> struct is_error_code_enum<future_errc> : public true_type { }; error_code make_error_code(future_errc e) noexcept; error_condition make_error_condition(future_errc e) noexcept; const error_category& future_category() noexcept; // [futures.future.error], class future_error class future_error; // [futures.promise], class template promise template<class R> class promise; template<class R> class promise<R&>; template<> class promise<void>; template<class R> void swap(promise<R>& x, promise<R>& y) noexcept; template<class R, class Alloc> struct uses_allocator<promise<R>, Alloc>; // [futures.unique.future], class template future template<class R> class future; template<class R> class future<R&>; template<> class future<void>; // [futures.shared.future], class template shared_future template<class R> class shared_future; template<class R> class shared_future<R&>; template<> class shared_future<void>; // [futures.task], class template packaged_task template<class> class packaged_task; // not defined template<class R, class... ArgTypes> class packaged_task<R(ArgTypes...)>; template<class R, class... ArgTypes> void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&) noexcept; // [futures.async], function template async template<class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(F&& f, Args&&... args); template<class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(launch policy, F&& f, Args&&... args); }
The enum type launch is a bitmask type ([bitmask.types]) with elements launch​::​async and launch​::​deferred.
[Note 1: 
Implementations can provide bitmasks to specify restrictions on task interaction by functions launched by async() applicable to a corresponding subset of available launch policies.
Implementations can extend the behavior of the first overload of async() by adding their extensions to the launch policy under the “as if” rule.
— end note]
The enum values of future_errc are distinct and not zero.

32.10.3 Error handling [futures.errors]

const error_category& future_category() noexcept;
Returns: A reference to an object of a type derived from class error_category.
The object's default_error_condition and equivalent virtual functions shall behave as specified for the class error_category.
The object's name virtual function returns a pointer to the string "future".
error_code make_error_code(future_errc e) noexcept;
Returns: error_code(static_cast<int>(e), future_category()).
error_condition make_error_condition(future_errc e) noexcept;
Returns: error_condition(static_cast<int>(e), future_category()).

32.10.4 Class future_error [futures.future.error]

namespace std { class future_error : public logic_error { public: explicit future_error(future_errc e); const error_code& code() const noexcept; const char* what() const noexcept; private: error_code ec_; // exposition only }; }
explicit future_error(future_errc e);
Effects: Initializes ec_ with make_error_code(e).
const error_code& code() const noexcept;
Returns: ec_.
const char* what() const noexcept;
Returns: An ntbs incorporating code().message().

32.10.5 Shared state [futures.state]

Many of the classes introduced in subclause [futures] use some state to communicate results.
This shared state consists of some state information and some (possibly not yet evaluated) result, which can be a (possibly void) value or an exception.
[Note 1: 
Futures, promises, and tasks defined in this Clause reference such shared state.
— end note]
[Note 2: 
The result can be any kind of object including a function to compute that result, as used by async when policy is launch​::​deferred.
— end note]
An asynchronous return object is an object that reads results from a shared state.
A waiting function of an asynchronous return object is one that potentially blocks to wait for the shared state to be made ready.
If a waiting function can return before the state is made ready because of a timeout ([thread.req.lockable]), then it is a timed waiting function, otherwise it is a non-timed waiting function.
An asynchronous provider is an object that provides a result to a shared state.
The result of a shared state is set by respective functions on the asynchronous provider.
[Example 1: 
Promises and tasks are examples of asynchronous providers.
— end example]
The means of setting the result of a shared state is specified in the description of those classes and functions that create such a state object.
When an asynchronous return object or an asynchronous provider is said to release its shared state, it means:
  • if the return object or provider holds the last reference to its shared state, the shared state is destroyed; and
  • the return object or provider gives up its reference to its shared state; and
  • these actions will not block for the shared state to become ready, except that it may block if all of the following are true: the shared state was created by a call to std​::​async, the shared state is not yet ready, and this was the last reference to the shared state.
When an asynchronous provider is said to make its shared state ready, it means:
  • first, the provider marks its shared state as ready; and
  • second, the provider unblocks any execution agents waiting for its shared state to become ready.
When an asynchronous provider is said to abandon its shared state, it means:
  • first, if that state is not ready, the provider
    • stores an exception object of type future_error with an error condition of broken_promise within its shared state; and then
    • makes its shared state ready;
  • second, the provider releases its shared state.
A shared state is ready only if it holds a value or an exception ready for retrieval.
Waiting for a shared state to become ready may invoke code to compute the result on the waiting thread if so specified in the description of the class or function that creates the state object.
Calls to functions that successfully set the stored result of a shared state synchronize with calls to functions successfully detecting the ready state resulting from that setting.
The storage of the result (whether normal or exceptional) into the shared state synchronizes with the successful return from a call to a waiting function on the shared state.
Some functions (e.g., promise​::​set_value_at_thread_exit) delay making the shared state ready until the calling thread exits.
The destruction of each of that thread's objects with thread storage duration is sequenced before making that shared state ready.
Access to the result of the same shared state may conflict.
[Note 3: 
This explicitly specifies that the result of the shared state is visible in the objects that reference this state in the sense of data race avoidance ([res.on.data.races]).
For example, concurrent accesses through references returned by shared_future​::​get() ([futures.shared.future]) must either use read-only operations or provide additional synchronization.
— end note]

32.10.6 Class template promise [futures.promise]

namespace std { template<class R> class promise { public: promise(); template<class Allocator> promise(allocator_arg_t, const Allocator& a); promise(promise&& rhs) noexcept; promise(const promise&) = delete; ~promise(); // assignment promise& operator=(promise&& rhs) noexcept; promise& operator=(const promise&) = delete; void swap(promise& other) noexcept; // retrieving the result future<R> get_future(); // setting the result void set_value(see below); void set_exception(exception_ptr p); // setting the result with deferred notification void set_value_at_thread_exit(see below); void set_exception_at_thread_exit(exception_ptr p); }; template<class R, class Alloc> struct uses_allocator<promise<R>, Alloc>; }
For the primary template, R shall be an object type that meets the Cpp17Destructible requirements.
The implementation provides the template promise and two specializations, promise<R&> and promise<void>.
These differ only in the argument type of the member functions set_value and set_value_at_thread_exit, as set out in their descriptions, below.
The set_value, set_exception, set_value_at_thread_exit, and set_exception_at_thread_exit member functions behave as though they acquire a single mutex associated with the promise object while updating the promise object.
template<class R, class Alloc> struct uses_allocator<promise<R>, Alloc> : true_type { };
Preconditions: Alloc meets the Cpp17Allocator requirements ([allocator.requirements.general]).
promise(); template<class Allocator> promise(allocator_arg_t, const Allocator& a);
Effects: Creates a shared state.
The second constructor uses the allocator a to allocate memory for the shared state.
promise(promise&& rhs) noexcept;
Effects: Transfers ownership of the shared state of rhs (if any) to the newly-constructed object.
Postconditions: rhs has no shared state.
~promise();
Effects: Abandons any shared state ([futures.state]).
promise& operator=(promise&& rhs) noexcept;
Effects: Abandons any shared state ([futures.state]) and then as if promise(std​::​move(rhs)).swap(*this).
Returns: *this.
void swap(promise& other) noexcept;
Effects: Exchanges the shared state of *this and other.
Postconditions: *this has the shared state (if any) that other had prior to the call to swap.
other has the shared state (if any) that *this had prior to the call to swap.
future<R> get_future();
Synchronization: Calls to this function do not introduce data races ([intro.multithread]) with calls to set_value, set_exception, set_value_at_thread_exit, or set_exception_at_thread_exit.
[Note 1: 
Such calls need not synchronize with each other.
— end note]
Returns: A future<R> object with the same shared state as *this.
Throws: future_error if *this has no shared state or if get_future has already been called on a promise with the same shared state as *this.
Error conditions:
  • future_already_retrieved if get_future has already been called on a promise with the same shared state as *this.
  • no_state if *this has no shared state.
void promise::set_value(const R& r); void promise::set_value(R&& r); void promise<R&>::set_value(R& r); void promise<void>::set_value();
Effects: Atomically stores the value r in the shared state and makes that state ready ([futures.state]).
Throws:
  • future_error if its shared state already has a stored value or exception, or
  • for the first version, any exception thrown by the constructor selected to copy an object of R, or
  • for the second version, any exception thrown by the constructor selected to move an object of R.
Error conditions:
  • promise_already_satisfied if its shared state already has a stored value or exception.
  • no_state if *this has no shared state.
void set_exception(exception_ptr p);
Preconditions: p is not null.
Effects: Atomically stores the exception pointer p in the shared state and makes that state ready ([futures.state]).
Throws: future_error if its shared state already has a stored value or exception.
Error conditions:
  • promise_already_satisfied if its shared state already has a stored value or exception.
  • no_state if *this has no shared state.
void promise::set_value_at_thread_exit(const R& r); void promise::set_value_at_thread_exit(R&& r); void promise<R&>::set_value_at_thread_exit(R& r); void promise<void>::set_value_at_thread_exit();
Effects: Stores the value r in the shared state without making that state ready immediately.
Schedules that state to be made ready when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed.
Throws:
  • future_error if its shared state already has a stored value or exception, or
  • for the first version, any exception thrown by the constructor selected to copy an object of R, or
  • for the second version, any exception thrown by the constructor selected to move an object of R.
Error conditions:
  • promise_already_satisfied if its shared state already has a stored value or exception.
  • no_state if *this has no shared state.
void set_exception_at_thread_exit(exception_ptr p);
Preconditions: p is not null.
Effects: Stores the exception pointer p in the shared state without making that state ready immediately.
Schedules that state to be made ready when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed.
Throws: future_error if an error condition occurs.
Error conditions:
  • promise_already_satisfied if its shared state already has a stored value or exception.
  • no_state if *this has no shared state.
template<class R> void swap(promise<R>& x, promise<R>& y) noexcept;
Effects: As if by x.swap(y).

32.10.7 Class template future [futures.unique.future]

The class template future defines a type for asynchronous return objects which do not share their shared state with other asynchronous return objects.
A default-constructed future object has no shared state.
A future object with shared state can be created by functions on asynchronous providers or by the move constructor and shares its shared state with the original asynchronous provider.
The result (value or exception) of a future object can be set by calling a respective function on an object that shares the same shared state.
[Note 1: 
Member functions of future do not synchronize with themselves or with member functions of shared_future.
— end note]
The effect of calling any member function other than the destructor, the move assignment operator, share, or valid on a future object for which valid() == false is undefined.
[Note 2: 
It is valid to move from a future object for which valid() == false.
— end note]
Recommended practice: Implementations should detect this case and throw an object of type future_error with an error condition of future_errc​::​no_state.
namespace std { template<class R> class future { public: future() noexcept; future(future&&) noexcept; future(const future&) = delete; ~future(); future& operator=(const future&) = delete; future& operator=(future&&) noexcept; shared_future<R> share() noexcept; // retrieving the value see below get(); // functions to check state bool valid() const noexcept; void wait() const; template<class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template<class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; }; }
For the primary template, R shall be an object type that meets the Cpp17Destructible requirements.
The implementation provides the template future and two specializations, future<R&> and future<void>.
These differ only in the return type and return value of the member function get, as set out in its description, below.
future() noexcept;
Effects: The object does not refer to a shared state.
Postconditions: valid() == false.
future(future&& rhs) noexcept;
Effects: Move constructs a future object that refers to the shared state that was originally referred to by rhs (if any).
Postconditions:
  • valid() returns the same value as rhs.valid() prior to the constructor invocation.
  • rhs.valid() == false.
~future();
Effects:
future& operator=(future&& rhs) noexcept;
Effects: If addressof(rhs) == this is true, there are no effects.
Otherwise:
Postconditions:
  • valid() returns the same value as rhs.valid() prior to the assignment.
  • If addressof(rhs) == this is false, rhs.valid() == false.
shared_future<R> share() noexcept;
Postconditions: valid() == false.
Returns: shared_future<R>(std​::​move(*this)).
R future::get(); R& future<R&>::get(); void future<void>::get();
[Note 3: 
As described above, the template and its two required specializations differ only in the return type and return value of the member function get.
— end note]
Effects:
  • wait()s until the shared state is ready, then retrieves the value stored in the shared state;
  • releases any shared state ([futures.state]).
Postconditions: valid() == false.
Returns:
  • future​::​get() returns the value v stored in the object's shared state as std​::​move(v).
  • future<R&>​::​get() returns the reference stored as value in the object's shared state.
  • future<void>​::​get() returns nothing.
Throws: The stored exception, if an exception was stored in the shared state.
bool valid() const noexcept;
Returns: true only if *this refers to a shared state.
void wait() const;
Effects: Blocks until the shared state is ready.
template<class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the relative timeout ([thread.req.timing]) specified by rel_time has expired.
Returns:
  • future_status​::​deferred if the shared state contains a deferred function.
  • future_status​::​ready if the shared state is ready.
  • future_status​::​timeout if the function is returning because the relative timeout ([thread.req.timing]) specified by rel_time has expired.
Throws: timeout-related exceptions ([thread.req.timing]).
template<class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the absolute timeout ([thread.req.timing]) specified by abs_time has expired.
Returns:
  • future_status​::​deferred if the shared state contains a deferred function.
  • future_status​::​ready if the shared state is ready.
  • future_status​::​timeout if the function is returning because the absolute timeout ([thread.req.timing]) specified by abs_time has expired.
Throws: timeout-related exceptions ([thread.req.timing]).

32.10.8 Class template shared_future [futures.shared.future]

The class template shared_future defines a type for asynchronous return objects which may share their shared state with other asynchronous return objects.
A default-constructed shared_future object has no shared state.
A shared_future object with shared state can be created by conversion from a future object and shares its shared state with the original asynchronous provider of the shared state.
The result (value or exception) of a shared_future object can be set by calling a respective function on an object that shares the same shared state.
[Note 1: 
Member functions of shared_future do not synchronize with themselves, but they synchronize with the shared state.
— end note]
The effect of calling any member function other than the destructor, the move assignment operator, the copy assignment operator, or valid() on a shared_future object for which valid() == false is undefined.
[Note 2: 
It is valid to copy or move from a shared_future object for which valid() is false.
— end note]
Recommended practice: Implementations should detect this case and throw an object of type future_error with an error condition of future_errc​::​no_state.
namespace std { template<class R> class shared_future { public: shared_future() noexcept; shared_future(const shared_future& rhs) noexcept; shared_future(future<R>&&) noexcept; shared_future(shared_future&& rhs) noexcept; ~shared_future(); shared_future& operator=(const shared_future& rhs) noexcept; shared_future& operator=(shared_future&& rhs) noexcept; // retrieving the value see below get() const; // functions to check state bool valid() const noexcept; void wait() const; template<class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template<class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; }; }
For the primary template, R shall be an object type that meets the Cpp17Destructible requirements.
The implementation provides the template shared_future and two specializations, shared_future<R&> and shared_future<void>.
These differ only in the return type and return value of the member function get, as set out in its description, below.
shared_future() noexcept;
Effects: The object does not refer to a shared state.
Postconditions: valid() == false.
shared_future(const shared_future& rhs) noexcept;
Effects: The object refers to the same shared state as rhs (if any).
Postconditions: valid() returns the same value as rhs.valid().
shared_future(future<R>&& rhs) noexcept; shared_future(shared_future&& rhs) noexcept;
Effects: Move constructs a shared_future object that refers to the shared state that was originally referred to by rhs (if any).
Postconditions:
  • valid() returns the same value as rhs.valid() returned prior to the constructor invocation.
  • rhs.valid() == false.
~shared_future();
Effects:
shared_future& operator=(shared_future&& rhs) noexcept;
Effects: If addressof(rhs) == this is true, there are no effects.
Otherwise:
Postconditions:
  • valid() returns the same value as rhs.valid() returned prior to the assignment.
  • If addressof(rhs) == this is false, rhs.valid() == false.
shared_future& operator=(const shared_future& rhs) noexcept;
Effects: If addressof(rhs) == this is true, there are no effects.
Otherwise:
  • Releases any shared state ([futures.state]);
  • assigns the contents of rhs to *this.
    [Note 3: 
    As a result, *this refers to the same shared state as rhs (if any).
    — end note]
Postconditions: valid() == rhs.valid().
const R& shared_future::get() const; R& shared_future<R&>::get() const; void shared_future<void>::get() const;
[Note 4: 
As described above, the template and its two required specializations differ only in the return type and return value of the member function get.
— end note]
[Note 5: 
Access to a value object stored in the shared state is unsynchronized, so operations on R might introduce a data race ([intro.multithread]).
— end note]
Effects: wait()s until the shared state is ready, then retrieves the value stored in the shared state.
Returns:
  • shared_future​::​get() returns a const reference to the value stored in the object's shared state.
    [Note 6: 
    Access through that reference after the shared state has been destroyed produces undefined behavior; this can be avoided by not storing the reference in any storage with a greater lifetime than the shared_future object that returned the reference.
    — end note]
  • shared_future<R&>​::​get() returns the reference stored as value in the object's shared state.
  • shared_future<void>​::​get() returns nothing.
Throws: The stored exception, if an exception was stored in the shared state.
bool valid() const noexcept;
Returns: true only if *this refers to a shared state.
void wait() const;
Effects: Blocks until the shared state is ready.
template<class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the relative timeout ([thread.req.timing]) specified by rel_time has expired.
Returns:
  • future_status​::​deferred if the shared state contains a deferred function.
  • future_status​::​ready if the shared state is ready.
  • future_status​::​timeout if the function is returning because the relative timeout ([thread.req.timing]) specified by rel_time has expired.
Throws: timeout-related exceptions ([thread.req.timing]).
template<class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the absolute timeout ([thread.req.timing]) specified by abs_time has expired.
Returns:
  • future_status​::​deferred if the shared state contains a deferred function.
  • future_status​::​ready if the shared state is ready.
  • future_status​::​timeout if the function is returning because the absolute timeout ([thread.req.timing]) specified by abs_time has expired.
Throws: timeout-related exceptions ([thread.req.timing]).

32.10.9 Function template async [futures.async]

The function template async provides a mechanism to launch a function potentially in a new thread and provides the result of the function in a future object with which it shares a shared state.
template<class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(F&& f, Args&&... args); template<class F, class... Args> future<invoke_result_t<decay_t<F>, decay_t<Args>...>> async(launch policy, F&& f, Args&&... args);
Mandates: The following are all true:
  • is_constructible_v<decay_t<F>, F>,
  • (is_constructible_v<decay_t<Args>, Args> && ...), and
  • is_invocable_v<decay_t<F>, decay_t<Args>...>.
Effects: The first function behaves the same as a call to the second function with a policy argument of launch​::​async | launch​::​deferred and the same arguments for F and Args.
The second function creates a shared state that is associated with the returned future object.
The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies):
  • If launch​::​async is set in policy, calls invoke(auto(std​::​forward<F>(f)), auto(std​::​forward<Args>(args))...) ([func.invoke], [thread.thread.constr]) as if in a new thread of execution represented by a thread object with the values produced by auto being materialized ([conv.rval]) in the thread that called async.
    Any return value is stored as the result in the shared state.
    Any exception propagated from the execution of invoke(auto(std​::​forward<F>(f)), auto(std​::​forward<Args>(args))...) is stored as the exceptional result in the shared state.
    The thread object is stored in the shared state and affects the behavior of any asynchronous return objects that reference that state.
  • If launch​::​deferred is set in policy, stores auto(std​::​forward<F>(f)) and auto(std​::​forward<Args>(args))... in the shared state.
    These copies of f and args constitute a deferred function.
    Invocation of the deferred function evaluates invoke(std​::​move(g), std​::​move(xyz)) where g is the stored value of auto(std​::​forward<F>(f)) and xyz is the stored copy of auto(std​::​forward<Args>(args))....
    Any return value is stored as the result in the shared state.
    Any exception propagated from the execution of the deferred function is stored as the exceptional result in the shared state.
    The shared state is not made ready until the function has completed.
    The first call to a non-timed waiting function ([futures.state]) on an asynchronous return object referring to this shared state invokes the deferred function in the thread that called the waiting function.
    Once evaluation of invoke(std​::​move(g), std​::​move(xyz)) begins, the function is no longer considered deferred.
    Recommended practice: If this policy is specified together with other policies, such as when using a policy value of launch​::​async | launch​::​deferred, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited.
  • If no value is set in the launch policy, or a value is set that is neither specified in this document nor by the implementation, the behavior is undefined.
Synchronization: The invocation of async synchronizes with the invocation of f.
The completion of the function f is sequenced before the shared state is made ready.
[Note 1: 
These apply regardless of the provided policy argument, and even if the corresponding future object is moved to another thread.
However, it is possible for f not to be called at all, in which case its completion never happens.
— end note]
If the implementation chooses the launch​::​async policy,
  • a call to a waiting function on an asynchronous return object that shares the shared state created by this async call shall block until the associated thread has completed, as if joined, or else time out ([thread.thread.member]);
  • the associated thread completion synchronizes with the return from the first function that successfully detects the ready status of the shared state or with the return from the last function that releases the shared state, whichever happens first.
Returns: An object of type future<invoke_result_t<decay_t<F>, decay_t<Args>...>> that refers to the shared state created by this call to async.
[Note 2: 
If a future obtained from async is moved outside the local scope, the future's destructor can block for the shared state to become ready.
— end note]
Throws: system_error if policy == launch​::​async and the implementation is unable to start a new thread, or std​::​bad_alloc if memory for the internal data structures cannot be allocated.
Error conditions:
  • resource_unavailable_try_again — if policy == launch​::​async and the system is unable to start a new thread.
[Example 1: int work1(int value); int work2(int value); int work(int value) { auto handle = std::async([=]{ return work2(value); }); int tmp = work1(value); return tmp + handle.get(); // #1 }
[Note 3: 
Line #1 might not result in concurrency because the async call uses the default policy, which might use launch​::​deferred, in which case the lambda might not be invoked until the get() call; in that case, work1 and work2 are called on the same thread and there is no concurrency.
— end note]
— end example]

32.10.10 Class template packaged_task [futures.task]

32.10.10.1 General [futures.task.general]

The class template packaged_task defines a type for wrapping a function or callable object so that the return value of the function or callable object is stored in a future when it is invoked.
When the packaged_task object is invoked, its stored task is invoked and the result (whether normal or exceptional) stored in the shared state.
Any futures that share the shared state will then be able to access the stored result.
namespace std { template<class> class packaged_task; // not defined template<class R, class... ArgTypes> class packaged_task<R(ArgTypes...)> { public: // construction and destruction packaged_task() noexcept; template<class F> explicit packaged_task(F&& f); ~packaged_task(); // no copy packaged_task(const packaged_task&) = delete; packaged_task& operator=(const packaged_task&) = delete; // move support packaged_task(packaged_task&& rhs) noexcept; packaged_task& operator=(packaged_task&& rhs) noexcept; void swap(packaged_task& other) noexcept; bool valid() const noexcept; // result retrieval future<R> get_future(); // execution void operator()(ArgTypes... ); void make_ready_at_thread_exit(ArgTypes...); void reset(); }; template<class R, class... ArgTypes> packaged_task(R (*)(ArgTypes...)) -> packaged_task<R(ArgTypes...)>; template<class F> packaged_task(F) -> packaged_task<see below>; }

32.10.10.2 Member functions [futures.task.members]

packaged_task() noexcept;
Effects: The object has no shared state and no stored task.
template<class F> explicit packaged_task(F&& f);
Constraints: remove_cvref_t<F> is not the same type as packaged_task<R(ArgTypes...)>.
Mandates: is_invocable_r_v<R, decay_t<F>&, ArgTypes...> is true.
Effects: Constructs a new packaged_task object with a stored task of type decay_t<F> and a shared state.
Initializes the object's stored task with std​::​forward<F>(f).
Throws: Any exceptions thrown by the copy or move constructor of f, or bad_alloc if memory for the internal data structures cannot be allocated.
template<class F> packaged_task(F) -> packaged_task<see below>;
Constraints: &F​::​operator() is well-formed when treated as an unevaluated operand ([expr.context]) and either
  • F​::​operator() is a non-static member function and decltype(&F​::​operator()) is either of the form R(G​::​*)(A...) cv & noexcept or of the form R(*)(G, A...) noexcept for a type G, or
  • F​::​operator() is a static member function and decltype(&F​::​operator()) is of the form R(*)(A...) noexcept.
Remarks: The deduced type is packaged_task<R(A...)>.
packaged_task(packaged_task&& rhs) noexcept;
Effects: Transfers ownership of rhs's shared state to *this, leaving rhs with no shared state.
Moves the stored task from rhs to *this.
Postconditions: rhs has no shared state.
packaged_task& operator=(packaged_task&& rhs) noexcept;
Effects:
~packaged_task();
Effects: Abandons any shared state ([futures.state]).
void swap(packaged_task& other) noexcept;
Effects: Exchanges the shared states and stored tasks of *this and other.
Postconditions: *this has the same shared state and stored task (if any) as other prior to the call to swap.
other has the same shared state and stored task (if any) as *this prior to the call to swap.
bool valid() const noexcept;
Returns: true only if *this has a shared state.
future<R> get_future();
Synchronization: Calls to this function do not introduce data races ([intro.multithread]) with calls to operator() or make_ready_at_thread_exit.
[Note 1: 
Such calls need not synchronize with each other.
— end note]
Returns: A future object that shares the same shared state as *this.
Throws: A future_error object if an error occurs.
Error conditions:
  • future_already_retrieved if get_future has already been called on a packaged_task object with the same shared state as *this.
  • no_state if *this has no shared state.
void operator()(ArgTypes... args);
Effects: As if by INVOKE<R>(f, t, t, , t) ([func.require]), where f is the stored task of *this and t, t, , t are the values in args....
If the task returns normally, the return value is stored as the asynchronous result in the shared state of *this, otherwise the exception thrown by the task is stored.
The shared state of *this is made ready, and any threads blocked in a function waiting for the shared state of *this to become ready are unblocked.
Throws: A future_error exception object if there is no shared state or the stored task has already been invoked.
Error conditions:
  • promise_already_satisfied if the stored task has already been invoked.
  • no_state if *this has no shared state.
void make_ready_at_thread_exit(ArgTypes... args);
Effects: As if by INVOKE<R>(f, t, t, , t) ([func.require]), where f is the stored task and t, t, , t are the values in args....
If the task returns normally, the return value is stored as the asynchronous result in the shared state of *this, otherwise the exception thrown by the task is stored.
In either case, this is done without making that state ready ([futures.state]) immediately.
Schedules the shared state to be made ready when the current thread exits, after all objects of thread storage duration associated with the current thread have been destroyed.
Throws: future_error if an error condition occurs.
Error conditions:
  • promise_already_satisfied if the stored task has already been invoked.
  • no_state if *this has no shared state.
void reset();
Effects: As if *this = packaged_task(std​::​move(f)), where f is the task stored in *this.
[Note 2: 
This constructs a new shared state for *this.
The old state is abandoned ([futures.state]).
— end note]
Throws:
  • bad_alloc if memory for the new shared state cannot be allocated.
  • Any exception thrown by the move constructor of the task stored in the shared state.
  • future_error with an error condition of no_state if *this has no shared state.

32.10.10.3 Globals [futures.task.nonmembers]

template<class R, class... ArgTypes> void swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y) noexcept;
Effects: As if by x.swap(y).

32.11 Safe reclamation [saferecl]

32.11.1 General [saferecl.general]

Subclause [saferecl] contains safe-reclamation techniques, which are most frequently used to straightforwardly resolve access-deletion races.

32.11.2 Read-copy update (RCU) [saferecl.rcu]

32.11.2.1 General [saferecl.rcu.general]

RCU is a synchronization mechanism that can be used for linked data structures that are frequently read, but seldom updated.
RCU does not provide mutual exclusion, but instead allows the user to schedule specified actions such as deletion at some later time.
A class type T is rcu-protectable if it has exactly one base class of type rcu_obj_base<T, D> for some D, and that base is public and non-virtual, and it has no base classes of type rcu_obj_base<X, Y> for any other combination X, Y.
An object is rcu-protectable if it is of rcu-protectable type.
An invocation of unlock U on an rcu_domain dom corresponds to an invocation of lock L on dom if L is sequenced before U and either
  • no other invocation of lock on dom is sequenced after L and before U, or
  • every invocation of unlock U2 on dom such that L is sequenced before U2 and U2 is sequenced before U corresponds to an invocation of lock L2 on dom such that L is sequenced before L2 and L2 is sequenced before U2.
[Note 1: 
This pairs nested locks and unlocks on a given domain in each thread.
— end note]
A region of RCU protection on a domain dom starts with a lock L on dom and ends with its corresponding unlock U.
Given a region of RCU protection R on a domain dom and given an evaluation E that scheduled another evaluation F in dom, if E does not strongly happen before the start of R, the end of R strongly happens before evaluating F.
The evaluation of a scheduled evaluation is potentially concurrent with any other scheduled evaluation.
Each scheduled evaluation is evaluated at most once.

32.11.2.2 Header <rcu> synopsis [rcu.syn]

namespace std { // [saferecl.rcu.base], class template rcu_obj_base template<class T, class D = default_delete<T>> class rcu_obj_base; // [saferecl.rcu.domain], class rcu_domain class rcu_domain; // [saferecl.rcu.domain.func], non-member functions rcu_domain& rcu_default_domain() noexcept; void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept; void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept; template<class T, class D = default_delete<T>> void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain()); }

32.11.2.3 Class template rcu_obj_base [saferecl.rcu.base]

Objects of type T to be protected by RCU inherit from a specialization rcu_obj_base<T, D> for some D.
namespace std { template<class T, class D = default_delete<T>> class rcu_obj_base { public: void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept; protected: rcu_obj_base() = default; rcu_obj_base(const rcu_obj_base&) = default; rcu_obj_base(rcu_obj_base&&) = default; rcu_obj_base& operator=(const rcu_obj_base&) = default; rcu_obj_base& operator=(rcu_obj_base&&) = default; ~rcu_obj_base() = default; private: D deleter; // exposition only }; }
The behavior of a program that adds specializations for rcu_obj_base is undefined.
T may be an incomplete type.
It shall be complete before any member of the resulting specialization of rcu_obj_base is referenced.
D shall be a function object type ([function.objects]) for which, given a value d of type D and a value ptr of type T*, the expression d(ptr) is valid.
D shall meet the requirements for Cpp17DefaultConstructible and Cpp17MoveAssignable.
If D is trivially copyable, all specializations of rcu_obj_base<T, D> are trivially copyable.
void retire(D d = D(), rcu_domain& dom = rcu_default_domain()) noexcept;
Mandates: T is an rcu-protectable type.
Preconditions: *this is a base class subobject of an object x of type T.
The member function rcu_obj_base<T, D>​::​retire was not invoked on x before.
The assignment to deleter does not exit via an exception.
Effects: Evaluates deleter = std​::​move(d) and schedules the evaluation of the expression deleter(
addressof(x))
in the domain dom; the behavior is undefined if that evaluation exits via an exception.
May invoke scheduled evaluations in dom.
[Note 1: 
If such evaluations acquire resources held across any invocation of retire on dom, deadlock can occur.
— end note]

32.11.2.4 Class rcu_domain [saferecl.rcu.domain]

32.11.2.4.1 General [saferecl.rcu.domain.general]

namespace std { class rcu_domain { public: rcu_domain(const rcu_domain&) = delete; rcu_domain& operator=(const rcu_domain&) = delete; void lock() noexcept; bool try_lock() noexcept; void unlock() noexcept; }; }
This class meets the requirements of Cpp17Lockable ([thread.req.lockable.req]) and provides regions of RCU protection.
[Example 1: std::scoped_lock<rcu_domain> rlock(rcu_default_domain()); — end example]
The functions lock and unlock establish (possibly nested) regions of RCU protection.

32.11.2.4.2 Member functions [saferecl.rcu.domain.members]

void lock() noexcept;
Effects: Opens a region of RCU protection.
Remarks: Calls to lock do not introduce a data race ([intro.races]) involving *this.
bool try_lock() noexcept;
Effects: Equivalent to lock().
Returns: true.
void unlock() noexcept;
Preconditions: A call to lock that opened an unclosed region of RCU protection is sequenced before the call to unlock.
Effects: Closes the unclosed region of RCU protection that was most recently opened.
May invoke scheduled evaluations in *this.
[Note 1: 
If such evaluations acquire resources held across any invocation of unlock on *this, deadlock can occur.
— end note]
Remarks: Calls to unlock do not introduce a data race involving *this.
[Note 2: 
Evaluation of scheduled evaluations can still cause a data race.
— end note]

32.11.2.4.3 Non-member functions [saferecl.rcu.domain.func]

rcu_domain& rcu_default_domain() noexcept;
Returns: A reference to a static-duration object of type rcu_domain.
A reference to the same object is returned every time this function is called.
void rcu_synchronize(rcu_domain& dom = rcu_default_domain()) noexcept;
Effects: If the call to rcu_synchronize does not strongly happen before the lock opening an RCU protection region R on dom, blocks until the unlock closing R happens.
Synchronization: The unlock closing R strongly happens before the return from rcu_synchronize.
void rcu_barrier(rcu_domain& dom = rcu_default_domain()) noexcept;
Effects: May evaluate any scheduled evaluations in dom.
For any evaluation that happens before the call to rcu_barrier and that schedules an evaluation E in dom, blocks until E has been evaluated.
Synchronization: The evaluation of any such E strongly happens before the return from rcu_barrier.
[Note 1: 
A call to rcu_barrier does not imply a call to rcu_synchronize and vice versa.
— end note]
template<class T, class D = default_delete<T>> void rcu_retire(T* p, D d = D(), rcu_domain& dom = rcu_default_domain());
Mandates: is_move_constructible_v<D> is true and the expression d(p) is well-formed.
Preconditions: D meets the Cpp17MoveConstructible and Cpp17Destructible requirements.
Effects: May allocate memory.
It is unspecified whether the memory allocation is performed by invoking operator new.
Initializes an object d1 of type D from std​::​move(d).
Schedules the evaluation of d1(p) in the domain dom; the behavior is undefined if that evaluation exits via an exception.
May invoke scheduled evaluations in dom.
[Note 2: 
If rcu_retire exits via an exception, no evaluation is scheduled.
— end note]
Throws: bad_alloc or any exception thrown by the initialization of d1.
[Note 3: 
If scheduled evaluations acquire resources held across any invocation of rcu_retire on dom, deadlock can occur.
— end note]

32.11.3 Hazard pointers [saferecl.hp]

32.11.3.1 General [saferecl.hp.general]

A hazard pointer is a single-writer multi-reader pointer that can be owned by at most one thread at any time.
Only the owner of the hazard pointer can set its value, while any number of threads may read its value.
The owner thread sets the value of a hazard pointer to point to an object in order to indicate to concurrent threads—which may delete such an object—that the object is not yet safe to delete.
A class type T is hazard-protectable if it has exactly one base class of type hazard_pointer_obj_base<T, D> for some D, that base is public and non-virtual, and it has no base classes of type hazard_pointer_obj_base<T2, D2> for any other combination T2, D2.
An object is hazard-protectable if it is of hazard-protectable type.
The time span between creation and destruction of a hazard pointer h is partitioned into a series of protection epochs; in each protection epoch, h either is associated with a hazard-protectable object, or is unassociated.
Upon creation, a hazard pointer is unassociated.
Changing the association (possibly to the same object) initiates a new protection epoch and ends the preceding one.
An object x of hazard-protectable type T is retired with a deleter of type D when the member function hazard_pointer_obj_base<T, D>​::​retire is invoked on x.
Any given object x shall be retired at most once.
A retired object x is reclaimed by invoking its deleter with a pointer to x; the behavior is undefined if that invocation exits via an exception.
A hazard-protectable object x is possibly-reclaimable with respect to an evaluation A if
  • x is not reclaimed; and
  • x is retired in an evaluation R and A does not happen before R; and
  • for all hazard pointers h and for every protection epoch E of h during which h is associated with x:
    • if the beginning of E happens before R, the end of E strongly happens before A; and
    • if E began by an evaluation of try_protect with argument src, label its atomic load operation L.
      If there exists an atomic modification B on src such that L observes a modification that is modification-ordered before B, and B happens before x is retired, the end of E strongly happens before A.
      [Note 1: 
      In typical use, a store to src sequenced before retiring x will be such an atomic operation B.
      — end note]
    [Note 2: 
    The latter two conditions convey the informal notion that a protection epoch that began before retiring x, as implied either by the happens-before relation or the coherence order of some source, delays the reclamation of x.
    — end note]
The number of possibly-reclaimable objects has an unspecified bound.
[Note 3: 
The bound can be a function of the number of hazard pointers, the number of threads that retire objects, and the number of threads that use hazard pointers.
— end note]
[Example 1: 
The following example shows how hazard pointers allow updates to be carried out in the presence of concurrent readers.
The object of type hazard_pointer in print_name protects the object *ptr from being reclaimed by ptr->retire until the end of the protection epoch.
struct Name : public hazard_pointer_obj_base<Name> { /* details */ }; atomic<Name*> name; // called often and in parallel! void print_name() { hazard_pointer h = make_hazard_pointer(); Name* ptr = h.protect(name); // Protection epoch starts // ... safe to access *ptr } // Protection epoch ends. // called rarely, but possibly concurrently with print_name void update_name(Name* new_name) { Name* ptr = name.exchange(new_name); ptr->retire(); } — end example]

32.11.3.2 Header <hazard_pointer> synopsis [hazard.pointer.syn]

namespace std { // [saferecl.hp.base], class template hazard_pointer_obj_base template<class T, class D = default_delete<T>> class hazard_pointer_obj_base; // [saferecl.hp.holder], class hazard_pointer class hazard_pointer; // [saferecl.hp.holder.nonmem], non-member functions hazard_pointer make_hazard_pointer(); void swap(hazard_pointer&, hazard_pointer&) noexcept; }

32.11.3.3 Class template hazard_pointer_obj_base [saferecl.hp.base]

namespace std { template<class T, class D = default_delete<T>> class hazard_pointer_obj_base { public: void retire(D d = D()) noexcept; protected: hazard_pointer_obj_base() = default; hazard_pointer_obj_base(const hazard_pointer_obj_base&) = default; hazard_pointer_obj_base(hazard_pointer_obj_base&&) = default; hazard_pointer_obj_base& operator=(const hazard_pointer_obj_base&) = default; hazard_pointer_obj_base& operator=(hazard_pointer_obj_base&&) = default; ~hazard_pointer_obj_base() = default; private: D deleter; // exposition only }; }
D shall be a function object type ([func.require]) for which, given a value d of type D and a value ptr of type T*, the expression d(ptr) is valid.
The behavior of a program that adds specializations for hazard_pointer_obj_base is undefined.
D shall meet the requirements for Cpp17DefaultConstructible and Cpp17MoveAssignable.
T may be an incomplete type.
It shall be complete before any member of the resulting specialization of hazard_pointer_obj_base is referenced.
void retire(D d = D()) noexcept;
Mandates: T is a hazard-protectable type.
Preconditions: *this is a base class subobject of an object x of type T.
x is not retired.
Move-assigning d to deleter does not exit via an exception.
Effects: Move-assigns d to deleter, thereby setting it as the deleter of x, then retires x.
May reclaim possibly-reclaimable objects.

32.11.3.4 Class hazard_pointer [saferecl.hp.holder]

32.11.3.4.1 General [saferecl.hp.holder.general]

namespace std { class hazard_pointer { public: hazard_pointer() noexcept; hazard_pointer(hazard_pointer&&) noexcept; hazard_pointer& operator=(hazard_pointer&&) noexcept; ~hazard_pointer(); bool empty() const noexcept; template<class T> T* protect(const atomic<T*>& src) noexcept; template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept; template<class T> void reset_protection(const T* ptr) noexcept; void reset_protection(nullptr_t = nullptr) noexcept; void swap(hazard_pointer&) noexcept; }; }
An object of type hazard_pointer is either empty or owns a hazard pointer.
Each hazard pointer is owned by exactly one object of type hazard_pointer.
[Note 1: 
An empty hazard_pointer object is different from a hazard_pointer object that owns an unassociated hazard pointer.
An empty hazard_pointer object does not own any hazard pointers.
— end note]

32.11.3.4.2 Constructors, destructor, and assignment [saferecl.hp.holder.ctor]

hazard_pointer() noexcept;
Postconditions: *this is empty.
hazard_pointer(hazard_pointer&& other) noexcept;
Postconditions: If other is empty, *this is empty.
Otherwise, *this owns the hazard pointer originally owned by other; other is empty.
~hazard_pointer();
Effects: If *this is not empty, destroys the hazard pointer owned by *this, thereby ending its current protection epoch.
hazard_pointer& operator=(hazard_pointer&& other) noexcept;
Effects: If this == &other is true, no effect.
Otherwise, if *this is not empty, destroys the hazard pointer owned by *this, thereby ending its current protection epoch.
Postconditions: If other was empty, *this is empty.
Otherwise, *this owns the hazard pointer originally owned by other.
If this != &other is true, other is empty.
Returns: *this.

32.11.3.4.3 Member functions [saferecl.hp.holder.mem]

bool empty() const noexcept;
Returns: true if and only if *this is empty.
template<class T> T* protect(const atomic<T*>& src) noexcept;
Effects: Equivalent to: T* ptr = src.load(memory_order::relaxed); while (!try_protect(ptr, src)) {} return ptr;
template<class T> bool try_protect(T*& ptr, const atomic<T*>& src) noexcept;
Mandates: T is a hazard-protectable type.
Preconditions: *this is not empty.
Effects: Performs the following steps in order:
  • Initializes a variable old of type T* with the value of ptr.
  • Evaluates reset_protection(old).
  • Assigns the value of src.load(memory_order​::​acquire) to ptr.
  • If old == ptr is false, evaluates reset_protection().
Returns: old == ptr.
template<class T> void reset_protection(const T* ptr) noexcept;
Mandates: T is a hazard-protectable type.
Preconditions: *this is not empty.
Effects: If ptr is a null pointer value, invokes reset_protection().
Otherwise, associates the hazard pointer owned by *this with *ptr, thereby ending the current protection epoch.
Complexity: Constant.
void reset_protection(nullptr_t = nullptr) noexcept;
Preconditions: *this is not empty.
Postconditions: The hazard pointer owned by *this is unassociated.
Complexity: Constant.
void swap(hazard_pointer& other) noexcept;
Effects: Swaps the hazard pointer ownership of this object with that of other.
[Note 1: 
The owned hazard pointers, if any, remain unchanged during the swap and continue to be associated with the respective objects that they were protecting before the swap, if any.
No protection epochs are ended or initiated.
— end note]
Complexity: Constant.

32.11.3.4.4 Non-member functions [saferecl.hp.holder.nonmem]

hazard_pointer make_hazard_pointer();
Effects: Constructs a hazard pointer.
Returns: A hazard_pointer object that owns the newly-constructed hazard pointer.
Throws: May throw bad_alloc if memory for the hazard pointer could not be allocated.
void swap(hazard_pointer& a, hazard_pointer& b) noexcept;
Effects: Equivalent to a.swap(b).

33 Execution control library [exec]

33.1 General [exec.general]

This Clause describes components supporting execution of function objects ([function.objects]).
The following subclauses describe the requirements, concepts, and components for execution control primitives as summarized in Table 152.
Table 152 — Execution control library summary [tab:exec.summary]
Subclause
Header
Schedulers
<execution>
Receivers
Operation states
Senders
Table 153 shows the types of customization point objects ([customization.point.object]) used in the execution control library.
Table 153 — Types of customization point objects in the execution control library [tab:exec.pos]
Customization point
Purpose
Examples
object type
core
provide core execution functionality, and connection between core components
e.g., connect, start
completion functions
called by senders to announce the completion of the work (success, error, or cancellation)
senders
allow the specialization of the provided sender algorithms
queries
allow querying different properties of objects
This clause makes use of the following exposition-only entities.
For a subexpression expr, let MANDATE-NOTHROW(expr) be expression-equivalent to expr.
Mandates: noexcept(expr) is true.
namespace std { template<class T> concept movable-value = // exposition only move_constructible<decay_t<T>> && constructible_from<decay_t<T>, T> && (!is_array_v<remove_reference_t<T>>); }
For function types F1 and F2 denoting R1(Args1...) and R2(Args2...), respectively, MATCHING-SIG(F1, F2) is true if and only if same_as<R1(Args1&&...), R2(Args2&&...)> is true.
For a subexpression err, let Err be decltype((err)) and let AS-EXCEPT-PTR(err) be:
  • err if decay_t<Err> denotes the type exception_ptr.
    Preconditions: !err is false.
  • Otherwise, make_exception_ptr(system_error(err)) if decay_t<Err> denotes the type error_code.
  • Otherwise, make_exception_ptr(err).

33.2 Queries and queryables [exec.queryable]

33.2.1 General [exec.queryable.general]

A queryable object is a read-only collection of key/value pair where each key is a customization point object known as a query object.
A query is an invocation of a query object with a queryable object as its first argument and a (possibly empty) set of additional arguments.
A query imposes syntactic and semantic requirements on its invocations.
Let q be a query object, let args be a (possibly empty) pack of subexpressions, let env be a subexpression that refers to a queryable object o of type O, and let cenv be a subexpression referring to o such that decltype((cenv)) is const O&.
The expression q(env, args...) is equal to ([concepts.equality]) the expression q(cenv, args...).
The type of a query expression cannot be void.
The expression q(env, args...) is equality-preserving ([concepts.equality]) and does not modify the query object or the arguments.
If the expression env.query(q, args...) is well-formed, then it is expression-equivalent to q(env, args...).
Unless otherwise specified, the result of a query is valid as long as the queryable object is valid.

33.2.2 queryable concept [exec.queryable.concept]

namespace std { template<class T> concept queryable = destructible<T>; // exposition only }
The exposition-only queryable concept specifies the constraints on the types of queryable objects.
Let env be an object of type Env.
The type Env models queryable if for each callable object q and a pack of subexpressions args, if requires { q(env, args...) } is true then q(env, args...) meets any semantic requirements imposed by q.

33.3 Asynchronous operations [exec.async.ops]

An execution resource is a program entity that manages a (possibly dynamic) set of execution agents ([thread.req.lockable.general]), which it uses to execute parallel work on behalf of callers.
[Example 1: 
The currently active thread, a system-provided thread pool, and uses of an API associated with an external hardware accelerator are all examples of execution resources.
— end example]
Execution resources execute asynchronous operations.
An execution resource is either valid or invalid.
An asynchronous operation is a distinct unit of program execution that
  • is explicitly created;
  • can be explicitly started once at most;
  • once started, eventually completes exactly once with a (possibly empty) set of result datums and in exactly one of three dispositions: success, failure, or cancellation;
    An asynchronous operation's async result is its disposition and its (possibly empty) set of result datums.
  • can complete on a different execution resource than the execution resource on which it started; and
  • can create and start other asynchronous operations called child operations.
    A child operation is an asynchronous operation that is created by the parent operation and, if started, completes before the parent operation completes.
    A parent operation is the asynchronous operation that created a particular child operation.
[Note 1: 
An asynchronous operation can execute synchronously; that is, it can complete during the execution of its start operation on the thread of execution that started it.
— end note]
An asynchronous operation has associated state known as its operation state.
An asynchronous operation has an associated environment.
An environment is a queryable object ([exec.queryable]) representing the execution-time properties of the operation's caller.
The caller of an asynchronous operation is its parent operation or the function that created it.
An asynchronous operation has an associated receiver.
A receiver is an aggregation of three handlers for the three asynchronous completion dispositions:
  • a value completion handler for a value completion,
  • an error completion handler for an error completion, and
  • a stopped completion handler for a stopped completion.
A receiver has an associated environment.
An asynchronous operation's operation state owns the operation's receiver.
The environment of an asynchronous operation is equal to its receiver's environment.
For each completion disposition, there is a completion function.
A completion function is a customization point object ([customization.point.object]) that accepts an asynchronous operation's receiver as the first argument and the result datums of the asynchronous operation as additional arguments.
The value completion function invokes the receiver's value completion handler with the value result datums; likewise for the error completion function and the stopped completion function.
A completion function has an associated type known as its completion tag that is the unqualified type of the completion function.
A valid invocation of a completion function is called a completion operation.
The lifetime of an asynchronous operation, also known as the operation's async lifetime, begins when its start operation begins executing and ends when its completion operation begins executing.
If the lifetime of an asynchronous operation's associated operation state ends before the lifetime of the asynchronous operation, the behavior is undefined.
After an asynchronous operation executes a completion operation, its associated operation state is invalid.
Accessing any part of an invalid operation state is undefined behavior.
An asynchronous operation shall not execute a completion operation before its start operation has begun executing.
After its start operation has begun executing, exactly one completion operation shall execute.
The lifetime of an asynchronous operation's operation state can end during the execution of the completion operation.
A sender is a factory for one or more asynchronous operations.
Connecting a sender and a receiver creates an asynchronous operation.
The asynchronous operation's associated receiver is equal to the receiver used to create it, and its associated environment is equal to the environment associated with the receiver used to create it.
The lifetime of an asynchronous operation's associated operation state does not depend on the lifetimes of either the sender or the receiver from which it was created.
A sender is started when it is connected to a receiver and the resulting asynchronous operation is started.
A sender's async result is the async result of the asynchronous operation created by connecting it to a receiver.
A sender sends its results by way of the asynchronous operation(s) it produces, and a receiver receives those results.
A sender is either valid or invalid; it becomes invalid when its parent sender (see below) becomes invalid.
A scheduler is an abstraction of an execution resource with a uniform, generic interface for scheduling work onto that resource.
It is a factory for senders whose asynchronous operations execute value completion operations on an execution agent belonging to the scheduler's associated execution resource.
A schedule-expression obtains such a sender from a scheduler.
A schedule sender is the result of a schedule expression.
On success, an asynchronous operation produced by a schedule sender executes a value completion operation with an empty set of result datums.
Multiple schedulers can refer to the same execution resource.
A scheduler can be valid or invalid.
A scheduler becomes invalid when the execution resource to which it refers becomes invalid, as do any schedule senders obtained from the scheduler, and any operation states obtained from those senders.
An asynchronous operation has one or more associated completion schedulers for each of its possible dispositions.
A completion scheduler is a scheduler whose associated execution resource is used to execute a completion operation for an asynchronous operation.
A value completion scheduler is a scheduler on which an asynchronous operation's value completion operation can execute.
Likewise for error completion schedulers and stopped completion schedulers.
A sender has an associated queryable object ([exec.queryable]) known as its attributes that describes various characteristics of the sender and of the asynchronous operation(s) it produces.
For each disposition, there is a query object for reading the associated completion scheduler from a sender's attributes; i.e., a value completion scheduler query object for reading a sender's value completion scheduler, etc.
If a completion scheduler query is well-formed, the returned completion scheduler is unique for that disposition for any asynchronous operation the sender creates.
A schedule sender is required to have a value completion scheduler attribute whose value is equal to the scheduler that produced the schedule sender.
A completion signature is a function type that describes a completion operation.
An asynchronous operation has a finite set of possible completion signatures corresponding to the completion operations that the asynchronous operation potentially evaluates ([basic.def.odr]).
For a completion function set, receiver rcvr, and pack of arguments args, let c be the completion operation set(rcvr, args...), and let F be the function type decltype(auto(set))(decltype((args))...).
A completion signature Sig is associated with c if and only if MATCHING-SIG(Sig, F) is true ([exec.general])).
Together, a sender type and an environment type Env determine the set of completion signatures of an asynchronous operation that results from connecting the sender with a receiver that has an environment of type Env.
The type of the receiver does not affect an asynchronous operation's completion signatures, only the type of the receiver's environment.
A sender algorithm is a function that takes and/or returns a sender.
There are three categories of sender algorithms:
  • A sender factory is a function that takes non-senders as arguments and that returns a sender.
  • A sender adaptor is a function that constructs and returns a parent sender from a set of one or more child senders and a (possibly empty) set of additional arguments.
    An asynchronous operation created by a parent sender is a parent operation to the child operations created by the child senders.
  • A sender consumer is a function that takes one or more senders and a (possibly empty) set of additional arguments, and whose return type is not the type of a sender.

33.4 Header <execution> synopsis [execution.syn]

namespace std { // [execpol.type], execution policy type trait template<class T> struct is_execution_policy; template<class T> constexpr bool is_execution_policy_v = is_execution_policy<T>::value; } namespace std::execution { // [execpol.seq], sequenced execution policy class sequenced_policy; // [execpol.par], parallel execution policy class parallel_policy; // [execpol.parunseq], parallel and unsequenced execution policy class parallel_unsequenced_policy; // [execpol.unseq], unsequenced execution policy class unsequenced_policy; // [execpol.objects], execution policy objects inline constexpr sequenced_policy seq{ unspecified }; inline constexpr parallel_policy par{ unspecified }; inline constexpr parallel_unsequenced_policy par_unseq{ unspecified }; inline constexpr unsequenced_policy unseq{ unspecified }; } namespace std { // [exec.general], helper concepts template<class T> concept movable-value = see below; // exposition only template<class From, class To> concept decays-to = same_as<decay_t<From>, To>; // exposition only template<class T> concept class-type = decays-to<T, T> && is_class_v<T>; // exposition only // [exec.queryable], queryable objects template<class T> concept queryable = see below; // exposition only // [exec.queries], queries struct forwarding_query_t { unspecified }; struct get_allocator_t { unspecified }; struct get_stop_token_t { unspecified }; inline constexpr forwarding_query_t forwarding_query{}; inline constexpr get_allocator_t get_allocator{}; inline constexpr get_stop_token_t get_stop_token{}; template<class T> using stop_token_of_t = remove_cvref_t<decltype(get_stop_token(declval<T>()))>; template<class T> concept forwarding-query = forwarding_query(T{}); // exposition only } namespace std::execution { // [exec.queries], queries struct get_domain_t { unspecified }; struct get_scheduler_t { unspecified }; struct get_delegation_scheduler_t { unspecified }; struct get_forward_progress_guarantee_t { unspecified }; template<class CPO> struct get_completion_scheduler_t { unspecified }; inline constexpr get_domain_t get_domain{}; inline constexpr get_scheduler_t get_scheduler{}; inline constexpr get_delegation_scheduler_t get_delegation_scheduler{}; enum class forward_progress_guarantee; inline constexpr get_forward_progress_guarantee_t get_forward_progress_guarantee{}; template<class CPO> constexpr get_completion_scheduler_t<CPO> get_completion_scheduler{}; struct get_env_t { unspecified }; inline constexpr get_env_t get_env{}; template<class T> using env_of_t = decltype(get_env(declval<T>())); // [exec.prop], class template prop template<class QueryTag, class ValueType> struct prop; // [exec.env], class template env template<queryable... Envs> struct env; // [exec.domain.default], execution domains struct default_domain; // [exec.sched], schedulers struct scheduler_t {}; template<class Sch> concept scheduler = see below; // [exec.recv], receivers struct receiver_t {}; template<class Rcvr> concept receiver = see below; template<class Rcvr, class Completions> concept receiver_of = see below; struct set_value_t { unspecified }; struct set_error_t { unspecified }; struct set_stopped_t { unspecified }; inline constexpr set_value_t set_value{}; inline constexpr set_error_t set_error{}; inline constexpr set_stopped_t set_stopped{}; // [exec.opstate], operation states struct operation_state_t {}; template<class O> concept operation_state = see below; struct start_t; inline constexpr start_t start{}; // [exec.snd], senders struct sender_t {}; template<class Sndr> concept sender = see below; template<class Sndr, class Env = env<>> concept sender_in = see below; template<class Sndr, class Rcvr> concept sender_to = see below; template<class... Ts> struct type-list; // exposition only // [exec.getcomplsigs], completion signatures struct get_completion_signatures_t; inline constexpr get_completion_signatures_t get_completion_signatures {}; template<class Sndr, class Env = env<>> requires sender_in<Sndr, Env> using completion_signatures_of_t = call-result-t<get_completion_signatures_t, Sndr, Env>; template<class... Ts> using decayed-tuple = tuple<decay_t<Ts>...>; // exposition only template<class... Ts> using variant-or-empty = see below; // exposition only template<class Sndr, class Env = env<>, template<class...> class Tuple = decayed-tuple, template<class...> class Variant = variant-or-empty> requires sender_in<Sndr, Env> using value_types_of_t = see below; template<class Sndr, class Env = env<>, template<class...> class Variant = variant-or-empty> requires sender_in<Sndr, Env> using error_types_of_t = see below; template<class Sndr, class Env = env<>> requires sender_in<Sndr, Env> constexpr bool sends_stopped = see below; template<class Sndr, class Env> using single-sender-value-type = see below; // exposition only template<class Sndr, class Env> concept single-sender = see below; // exposition only template<sender Sndr> using tag_of_t = see below; // [exec.snd.transform], sender transformations template<class Domain, sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) constexpr sender decltype(auto) transform_sender( Domain dom, Sndr&& sndr, const Env&... env) noexcept(see below); // [exec.snd.transform.env], environment transformations template<class Domain, sender Sndr, queryable Env> constexpr queryable decltype(auto) transform_env( Domain dom, Sndr&& sndr, Env&& env) noexcept; // [exec.snd.apply], sender algorithm application template<class Domain, class Tag, sender Sndr, class... Args> constexpr decltype(auto) apply_sender( Domain dom, Tag, Sndr&& sndr, Args&&... args) noexcept(see below); // [exec.connect], the connect sender algorithm struct connect_t; inline constexpr connect_t connect{}; template<class Sndr, class Rcvr> using connect_result_t = decltype(connect(declval<Sndr>(), declval<Rcvr>())); // [exec.factories], sender factories struct just_t { unspecified }; struct just_error_t { unspecified }; struct just_stopped_t { unspecified }; struct schedule_t { unspecified }; inline constexpr just_t just{}; inline constexpr just_error_t just_error{}; inline constexpr just_stopped_t just_stopped{}; inline constexpr schedule_t schedule{}; inline constexpr unspecified read_env{}; template<scheduler Sndr> using schedule_result_t = decltype(schedule(declval<Sndr>())); // [exec.adapt], sender adaptors template<class-type D> struct sender_adaptor_closure { }; struct starts_on_t { unspecified }; struct continues_on_t { unspecified }; struct on_t { unspecified }; struct schedule_from_t { unspecified }; struct then_t { unspecified }; struct upon_error_t { unspecified }; struct upon_stopped_t { unspecified }; struct let_value_t { unspecified }; struct let_error_t { unspecified }; struct let_stopped_t { unspecified }; struct bulk_t { unspecified }; struct split_t { unspecified }; struct when_all_t { unspecified }; struct when_all_with_variant_t { unspecified }; struct into_variant_t { unspecified }; struct stopped_as_optional_t { unspecified }; struct stopped_as_error_t { unspecified }; inline constexpr starts_on_t starts_on{}; inline constexpr continues_on_t continues_on{}; inline constexpr on_t on{}; inline constexpr schedule_from_t schedule_from{}; inline constexpr then_t then{}; inline constexpr upon_error_t upon_error{}; inline constexpr upon_stopped_t upon_stopped{}; inline constexpr let_value_t let_value{}; inline constexpr let_error_t let_error{}; inline constexpr let_stopped_t let_stopped{}; inline constexpr bulk_t bulk{}; inline constexpr split_t split{}; inline constexpr when_all_t when_all{}; inline constexpr when_all_with_variant_t when_all_with_variant{}; inline constexpr into_variant_t into_variant{}; inline constexpr stopped_as_optional_t stopped_as_optional{}; inline constexpr stopped_as_error_t stopped_as_error{}; // [exec.util], sender and receiver utilities // [exec.util.cmplsig] template<class Fn> concept completion-signature = see below; // exposition only template<completion-signature... Fns> struct completion_signatures {}; template<class Sigs> concept valid-completion-signatures = see below; // exposition only // [exec.util.cmplsig.trans] template< valid-completion-signatures InputSignatures, valid-completion-signatures AdditionalSignatures = completion_signatures<>, template<class...> class SetValue = see below, template<class> class SetError = see below, valid-completion-signatures SetStopped = completion_signatures<set_stopped_t()>> using transform_completion_signatures = completion_signatures<see below>; template< sender Sndr, class Env = env<>, valid-completion-signatures AdditionalSignatures = completion_signatures<>, template<class...> class SetValue = see below, template<class> class SetError = see below, valid-completion-signatures SetStopped = completion_signatures<set_stopped_t()>> requires sender_in<Sndr, Env> using transform_completion_signatures_of = transform_completion_signatures< completion_signatures_of_t<Sndr, Env>, AdditionalSignatures, SetValue, SetError, SetStopped>; // [exec.run.loop], run_loop class run_loop; } namespace std::this_thread { // [exec.consumers], consumers struct sync_wait_t { unspecified }; struct sync_wait_with_variant_t { unspecified }; inline constexpr sync_wait_t sync_wait{}; inline constexpr sync_wait_with_variant_t sync_wait_with_variant{}; } namespace std::execution { // [exec.as.awaitable] struct as_awaitable_t { unspecified }; inline constexpr as_awaitable_t as_awaitable{}; // [exec.with.awaitable.senders] template<class-type Promise> struct with_awaitable_senders; }
The exposition-only type variant-or-empty<Ts...> is defined as follows:
  • If sizeof...(Ts) is greater than zero, variant-or-empty<Ts...> denotes variant<Us...> where Us... is the pack decay_t<Ts>... with duplicate types removed.
  • Otherwise, variant-or-empty<Ts...> denotes the exposition-only class type: namespace std::execution { struct empty-variant { // exposition only empty-variant() = delete; }; }
For types Sndr and Env, single-sender-value-type<Sndr, Env> is an alias for:
  • value_types_of_t<Sndr, Env, decay_t, type_identity_t> if that type is well-formed,
  • Otherwise, void if value_types_of_t<Sndr, Env, tuple, variant> is variant<tuple<>> or variant<>,
  • Otherwise, value_types_of_t<Sndr, Env, decayed-tuple, type_identity_t> if that type is well-formed,
  • Otherwise, single-sender-value-type<Sndr, Env> is ill-formed.
The exposition-only concept single-sender is defined as follows: namespace std::execution { template<class Sndr, class Env> concept single-sender = sender_in<Sndr, Env> && requires { typename single-sender-value-type<Sndr, Env>; }; }

33.5 Queries [exec.queries]

33.5.1 forwarding_query [exec.fwd.env]

forwarding_query asks a query object whether it should be forwarded through queryable adaptors.
The name forwarding_query denotes a query object.
For some query object q of type Q, forwarding_query(q) is expression-equivalent to:
  • MANDATE-NOTHROW(q.query(forwarding_query)) if that expression is well-formed.
    Mandates: The expression above has type bool and is a core constant expression if q is a core constant expression.
  • Otherwise, true if derived_from<Q, forwarding_query_t> is true.
  • Otherwise, false.

33.5.2 get_allocator [exec.get.allocator]

get_allocator asks a queryable object for its associated allocator.
The name get_allocator denotes a query object.
For a subexpression env, get_allocator(env) is expression-equivalent to MANDATE-NOTHROW(as_const(env).query(get_allocator)).
Mandates: If the expression above is well-formed, its type satisfies simple-allocator ([allocator.requirements.general]).
forwarding_query(get_allocator) is a core constant expression and has value true.

33.5.3 get_stop_token [exec.get.stop.token]

get_stop_token asks a queryable object for an associated stop token.
The name get_stop_token denotes a query object.
For a subexpression env, get_stop_token(env) is expression-equivalent to:
  • MANDATE-NOTHROW(as_const(env).query(get_stop_token)) if that expression is well-formed.
    Mandates: The type of the expression above satisfies stoppable_token.
  • Otherwise, never_stop_token{}.
forwarding_query(get_stop_token) is a core constant expression and has value true.

33.5.4 execution​::​get_env [exec.get.env]

execution​::​get_env is a customization point object.
For a subexpression o, execution​::​get_env(o) is expression-equivalent to:
The value of get_env(o) shall be valid while o is valid.
[Note 1: 
When passed a sender object, get_env returns the sender's associated attributes.
When passed a receiver, get_env returns the receiver's associated execution environment.
— end note]

33.5.5 execution​::​get_domain [exec.get.domain]

get_domain asks a queryable object for its associated execution domain tag.
The name get_domain denotes a query object.
For a subexpression env, get_domain(env) is expression-equivalent to MANDATE-NOTHROW(as_const(env).query(get_domain)).
forwarding_query(execution​::​get_domain) is a core constant expression and has value true.

33.5.6 execution​::​get_scheduler [exec.get.scheduler]

get_scheduler asks a queryable object for its associated scheduler.
The name get_scheduler denotes a query object.
For a subexpression env, get_scheduler(env) is expression-equivalent to MANDATE-NOTHROW(as_const(env).query(get_scheduler)).
Mandates: If the expression above is well-formed, its type satisfies scheduler.
forwarding_query(execution​::​get_scheduler) is a core constant expression and has value true.

33.5.7 execution​::​get_delegation_scheduler [exec.get.delegation.scheduler]

get_delegation_scheduler asks a queryable object for a scheduler that can be used to delegate work to for the purpose of forward progress delegation ([intro.progress]).
The name get_delegation_scheduler denotes a query object.
For a subexpression env, get_delegation_scheduler(env) is expression-equivalent to MANDATE-NOTHROW(as_const(env).query(get_delegation_scheduler)).
Mandates: If the expression above is well-formed, its type satisfies scheduler.
forwarding_query(execution​::​get_delegation_scheduler) is a core constant expression and has value true.

33.5.8 execution​::​get_forward_progress_guarantee [exec.get.fwd.progress]

namespace std::execution { enum class forward_progress_guarantee { concurrent, parallel, weakly_parallel }; }
get_forward_progress_guarantee asks a scheduler about the forward progress guarantee of execution agents created by that scheduler's associated execution resource ([intro.progress]).
The name get_forward_progress_guarantee denotes a query object.
For a subexpression sch, let Sch be decltype((sch)).
If Sch does not satisfy scheduler, get_forward_progress_guarantee is ill-formed.
Otherwise, get_forward_progress_guarantee(sch) is expression-equivalent to:
  • MANDATE-NOTHROW(as_const(sch).query(get_forward_progress_guarantee)), if that expression is well-formed.
    Mandates: The type of the expression above is forward_progress_guarantee.
  • Otherwise, forward_progress_guarantee​::​weakly_parallel.
If get_forward_progress_guarantee(sch) for some scheduler sch returns forward_progress_guarantee​::​concurrent, all execution agents created by that scheduler's associated execution resource shall provide the concurrent forward progress guarantee.
If it returns forward_progress_guarantee​::​parallel, all such execution agents shall provide at least the parallel forward progress guarantee.

33.5.9 execution​::​get_completion_scheduler [exec.get.compl.sched]

get_completion_scheduler<completion-tag> obtains the completion scheduler associated with a completion tag from a sender's attributes.
The name get_completion_scheduler denotes a query object template.
For a subexpression q, the expression get_completion_scheduler<completion-tag>(q) is ill-formed if completion-tag is not one of set_value_t, set_error_t, or set_stopped_t.
Otherwise, get_completion_scheduler<completion-tag>(q) is expression-equivalent to MANDATE-NOTHROW(as_const(q).query(get_completion_scheduler<completion-tag>)) Mandates: If the expression above is well-formed, its type satisfies scheduler.
Let completion-fn be a completion function ([exec.async.ops]); let completion-tag be the associated completion tag of completion-fn; let args be a pack of subexpressions; and let sndr be a subexpression such that sender<decltype((sndr))> is true and get_completion_scheduler<completion-tag>(get_env(sndr)) is well-formed and denotes a scheduler sch.
If an asynchronous operation created by connecting sndr with a receiver rcvr causes the evaluation of completion-fn(rcvr, args...), the behavior is undefined unless the evaluation happens on an execution agent that belongs to sch's associated execution resource.
The expression forwarding_query(get_completion_scheduler<completion-tag>) is a core constant expression and has value true.

33.6 Schedulers [exec.sched]

The scheduler concept defines the requirements of a scheduler type ([exec.async.ops]).
schedule is a customization point object that accepts a scheduler.
A valid invocation of schedule is a schedule-expression.
namespace std::execution { template<class Sch> concept scheduler = derived_from<typename remove_cvref_t<Sch>::scheduler_concept, scheduler_t> && queryable<Sch> && requires(Sch&& sch) { { schedule(std::forward<Sch>(sch)) } -> sender; { auto(get_completion_scheduler<set_value_t>( get_env(schedule(std::forward<Sch>(sch))))) } -> same_as<remove_cvref_t<Sch>>; } && equality_comparable<remove_cvref_t<Sch>> && copyable<remove_cvref_t<Sch>>; }
Let Sch be the type of a scheduler and let Env be the type of an execution environment for which sender_in<schedule_result_t<Sch>, Env> is satisfied.
Then sender-in-of<schedule_result_t<Sch>, Env> shall be modeled.
No operation required by copyable<remove_cvref_t<Sch>> and equality_comparable<remove_cvref_t<Sch>> shall exit via an exception.
None of these operations, nor a scheduler type's schedule function, shall introduce data races as a result of potentially concurrent ([intro.races]) invocations of those operations from different threads.
For any two values sch1 and sch2 of some scheduler type Sch, sch1 == sch2 shall return true only if both sch1 and sch2 share the same associated execution resource.
For a given scheduler expression sch, the expression get_completion_scheduler<set_value_t>(get_env(schedule(sch))) shall compare equal to sch.
For a given scheduler expression sch, if the expression get_domain(sch) is well-formed, then the expression get_domain(get_env(schedule(sch))) is also well-formed and has the same type.
A scheduler type's destructor shall not block pending completion of any receivers connected to the sender objects returned from schedule.
[Note 1: 
The ability to wait for completion of submitted function objects can be provided by the associated execution resource of the scheduler.
— end note]

33.7 Receivers [exec.recv]

33.7.1 Receiver concepts [exec.recv.concepts]

A receiver represents the continuation of an asynchronous operation.
The receiver concept defines the requirements for a receiver type ([exec.async.ops]).
The receiver_of concept defines the requirements for a receiver type that is usable as the first argument of a set of completion operations corresponding to a set of completion signatures.
The get_env customization point object is used to access a receiver's associated environment.
namespace std::execution { template<class Rcvr> concept receiver = derived_from<typename remove_cvref_t<Rcvr>::receiver_concept, receiver_t> && requires(const remove_cvref_t<Rcvr>& rcvr) { { get_env(rcvr) } -> queryable; } && move_constructible<remove_cvref_t<Rcvr>> && // rvalues are movable, and constructible_from<remove_cvref_t<Rcvr>, Rcvr>; // lvalues are copyable template<class Signature, class Rcvr> concept valid-completion-for = requires (Signature* sig) { []<class Tag, class... Args>(Tag(*)(Args...)) requires callable<Tag, remove_cvref_t<Rcvr>, Args...> {}(sig); }; template<class Rcvr, class Completions> concept has-completions = requires (Completions* completions) { []<valid-completion-for<Rcvr>...Sigs>(completion_signatures<Sigs...>*) {}(completions); }; template<class Rcvr, class Completions> concept receiver_of = receiver<Rcvr> && has-completions<Rcvr, Completions>; }
Class types that are marked final do not model the receiver concept.
Let rcvr be a receiver and let op_state be an operation state associated with an asynchronous operation created by connecting rcvr with a sender.
Let token be a stop token equal to get_stop_token(get_env(rcvr)).
token shall remain valid for the duration of the asynchronous operation's lifetime ([exec.async.ops]).
[Note 1: 
This means that, unless it knows about further guarantees provided by the type of rcvr, the implementation of op_state cannot use token after it executes a completion operation.
This also implies that any stop callbacks registered on token must be destroyed before the invocation of the completion operation.
— end note]

33.7.2 execution​::​set_value [exec.set.value]

set_value is a value completion function ([exec.async.ops]).
Its associated completion tag is set_value_t.
The expression set_value(rcvr, vs...) for a subexpression rcvr and pack of subexpressions vs is ill-formed if rcvr is an lvalue or an rvalue of const type.
Otherwise, it is expression-equivalent to MANDATE-NOTHROW(rcvr.set_value(vs...)).

33.7.3 execution​::​set_error [exec.set.error]

set_error is an error completion function ([exec.async.ops]).
Its associated completion tag is set_error_t.
The expression set_error(rcvr, err) for some subexpressions rcvr and err is ill-formed if rcvr is an lvalue or an rvalue of const type.
Otherwise, it is expression-equivalent to MANDATE-NOTHROW(rcvr.set_error(err)).

33.7.4 execution​::​set_stopped [exec.set.stopped]

set_stopped is a stopped completion function ([exec.async.ops]).
Its associated completion tag is set_stopped_t.
The expression set_stopped(rcvr) for a subexpression rcvr is ill-formed if rcvr is an lvalue or an rvalue of const type.
Otherwise, it is expression-equivalent to MANDATE-NOTHROW(rcvr.set_stopped()).

33.8 Operation states [exec.opstate]

33.8.1 General [exec.opstate.general]

The operation_state concept defines the requirements of an operation state type ([exec.async.ops]).
namespace std::execution { template<class O> concept operation_state = derived_from<typename O::operation_state_concept, operation_state_t> && is_object_v<O> && requires (O& o) { { start(o) } noexcept; }; }
If an operation_state object is destroyed during the lifetime of its asynchronous operation ([exec.async.ops]), the behavior is undefined.
[Note 1: 
The operation_state concept does not impose requirements on any operations other than destruction and start, including copy and move operations.
Invoking any such operation on an object whose type models operation_state can lead to undefined behavior.
— end note]
The program is ill-formed if it performs a copy or move construction or assignment operation on an operation state object created by connecting a library-provided sender.

33.8.2 execution​::​start [exec.opstate.start]

The name start denotes a customization point object that starts ([exec.async.ops]) the asynchronous operation associated with the operation state object.
For a subexpression op, the expression start(op) is ill-formed if op is an rvalue.
Otherwise, it is expression-equivalent to MANDATE-NOTHROW(op.start()).
If op.start() does not start ([exec.async.ops]) the asynchronous operation associated with the operation state op, the behavior of calling start(op) is undefined.

33.9 Senders [exec.snd]

33.9.1 General [exec.snd.general]

Subclauses [exec.factories] and [exec.adapt] define customizable algorithms that return senders.
Each algorithm has a default implementation.
Let sndr be the result of an invocation of such an algorithm or an object equal to the result ([concepts.equality]), and let Sndr be decltype((sndr)).
Let rcvr be a receiver of type Rcvr with associated environment env of type Env such that sender_to<Sndr, Rcvr> is true.
For the default implementation of the algorithm that produced sndr, connecting sndr to rcvr and starting the resulting operation state ([exec.async.ops]) necessarily results in the potential evaluation ([basic.def.odr]) of a set of completion operations whose first argument is a subexpression equal to rcvr.
Let Sigs be a pack of completion signatures corresponding to this set of completion operations.
Then the type of the expression get_completion_signatures(sndr, env) is a specialization of the class template completion_signatures ([exec.util.cmplsig]), the set of whose template arguments is Sigs.
If a user-provided implementation of the algorithm that produced sndr is selected instead of the default, any completion signature that is in the set of types denoted by completion_signatures_of_t<Sndr, Env> and that is not part of Sigs shall correspond to error or stopped completion operations, unless otherwise specified.

33.9.2 Exposition-only entities [exec.snd.expos]

Subclause [exec.snd] makes use of the following exposition-only entities.
For a queryable object env, FWD-ENV(env) is an expression whose type satisfies queryable such that for a query object q and a pack of subexpressions as, the expression FWD-ENV(env).query(q, as...) is ill-formed if forwarding_query(q) is false; otherwise, it is expression-equivalent to env.query(q, as...).
For a query object q and a subexpression v, MAKE-ENV(q, v) is an expression env whose type satisfies queryable such that the result of env.query(q) has a value equal to v ([concepts.equality]).
Unless otherwise stated, the object to which env.query(q) refers remains valid while env remains valid.
For two queryable objects env1 and env2, a query object q, and a pack of subexpressions as, JOIN-ENV(env1, env2) is an expression env3 whose type satisfies queryable such that env3.query(q, as...) is expression-equivalent to:
  • env1.query(q, as...) if that expression is well-formed,
  • otherwise, env2.query(q, as...) if that expression is well-formed,
  • otherwise, env3.query(q, as...) is ill-formed.
The results of FWD-ENV, MAKE-ENV, and JOIN-ENV can be context-dependent; i.e., they can evaluate to expressions with different types and value categories in different contexts for the same arguments.
For a scheduler sch, SCHED-ATTRS(sch) is an expression o1 whose type satisfies queryable such that o1.query(get_completion_scheduler<Tag>) is an expression with the same type and value as sch where Tag is one of set_value_t or set_stopped_t, and such that o1.query(get_domain) is expression-equivalent to sch.query(get_domain).
SCHED-ENV(sch) is an expression o2 whose type satisfies queryable such that o2.query(get_scheduler) is a prvalue with the same type and value as sch, and such that o2.query(get_domain) is expression-equivalent to sch.query(get_domain).
For two subexpressions rcvr and expr, SET-VALUE(rcvr, expr) is expression-equivalent to (expr, set_value(std​::​move(rcvr))) if the type of expr is void; otherwise, set_value(std​::​move(rcvr), expr).
TRY-EVAL(rcvr, expr) is equivalent to: try { expr; } catch(...) { set_error(std::move(rcvr), current_exception()); } if expr is potentially-throwing; otherwise, expr.
TRY-SET-VALUE(rcvr, expr) is TRY-EVAL(rcvr, SET-VALUE(rcvr, expr)) except that rcvr is evaluated only once.
template<class Default = default_domain, class Sndr> constexpr auto completion-domain(const Sndr& sndr) noexcept;
COMPL-DOMAIN(T) is the type of the expression get_domain(get_completion_scheduler<T>(get_env(sndr))).
Effects: If all of the types COMPL-DOMAIN(set_value_t), COMPL-DOMAIN(set_error_t), and
COMPL-DOMAIN(set_stopped_t) are ill-formed, completion-domain<Default>(sndr) is a default-constructed prvalue of type Default.
Otherwise, if they all share a common type ([meta.trans.other]) (ignoring those types that are ill-formed), then completion-domain<Default>(sndr) is a default-constructed prvalue of that type.
Otherwise, completion-domain<Default>(sndr) is ill-formed.
template<class Tag, class Env, class Default> constexpr decltype(auto) query-with-default( Tag, const Env& env, Default&& value) noexcept(see below);
Let e be the expression Tag()(env) if that expression is well-formed; otherwise, it is static_cast<Default>(std​::​forward<Default>(value)).
Returns: e.
Remarks: The expression in the noexcept clause is noexcept(e).
template<class Sndr> constexpr auto get-domain-early(const Sndr& sndr) noexcept;
Effects: Equivalent to: return Domain(); where Domain is the decayed type of the first of the following expressions that is well-formed:
template<class Sndr, class Env> constexpr auto get-domain-late(const Sndr& sndr, const Env& env) noexcept;
Effects: Equivalent to:
  • If sender-for<Sndr, continues_on_t> is true, then return Domain(); where Domain is the type of the following expression: [] { auto [_, sch, _] = sndr; return query-or-default(get_domain, sch, default_domain()); }();
    [Note 1: 
    The continues_on algorithm works in tandem with schedule_from ([exec.schedule.from]) to give scheduler authors a way to customize both how to transition onto (continues_on) and off of (schedule_from) a given execution context.
    Thus, continues_on ignores the domain of the predecessor and uses the domain of the destination scheduler to select a customization, a property that is unique to continues_on.
    That is why it is given special treatment here.
    — end note]
  • Otherwise, return Domain(); where Domain is the first of the following expressions that is well-formed and whose type is not void:
template<callable Fun> requires is_nothrow_move_constructible_v<Fun> struct emplace-from { Fun fun; // exposition only using type = call-result-t<Fun>; constexpr operator type() && noexcept(nothrow-callable<Fun>) { return std::move(fun)(); } constexpr type operator()() && noexcept(nothrow-callable<Fun>) { return std::move(fun)(); } };
[Note 2: 
emplace-from is used to emplace non-movable types into tuple, optional, variant, and similar types.
— end note]
struct on-stop-request { inplace_stop_source& stop-src; // exposition only void operator()() noexcept { stop-src.request_stop(); } };
template<class T, class T, ..., class T> struct product-type { // exposition only T t; // exposition only T t; // exposition only ... T t; // exposition only template<size_t I, class Self> constexpr decltype(auto) get(this Self&& self) noexcept; // exposition only template<class Self, class Fn> constexpr decltype(auto) apply(this Self&& self, Fn&& fn) // exposition only noexcept(see below); };
[Note 3: 
product-type is presented here in pseudo-code form for the sake of exposition.
It can be approximated in standard C++ with a tuple-like implementation that takes care to keep the type an aggregate that can be used as the initializer of a structured binding declaration.
— end note]
[Note 4: 
An expression of type product-type is usable as the initializer of a structured binding declaration ([dcl.struct.bind]).
— end note]
template<size_t I, class Self> constexpr decltype(auto) get(this Self&& self) noexcept;
Effects: Equivalent to: auto& [...ts] = self; return std::forward_like<Self>(ts...[I]);
template<class Self, class Fn> constexpr decltype(auto) apply(this Self&& self, Fn&& fn) noexcept(see below);
Constraints: The expression in the return statement below is well-formed.
Effects: Equivalent to: auto& [...ts] = self; return std::forward<Fn>(fn)(std::forward_like<Self>(ts)...);
Remarks: The expression in the noexcept clause is true if the return statement above is not potentially throwing; otherwise, false.
template<class Tag, class Data = see below, class... Child> constexpr auto make-sender(Tag tag, Data&& data, Child&&... child);
Mandates: The following expressions are true:
Returns: A prvalue of type basic-sender<Tag, decay_t<Data>, decay_t<Child>...> that has been direct-list-initialized with the forwarded arguments, where basic-sender is the following exposition-only class template except as noted below.
namespace std::execution { template<class Tag> concept completion-tag = // exposition only same_as<Tag, set_value_t> || same_as<Tag, set_error_t> || same_as<Tag, set_stopped_t>; template<template<class...> class T, class... Args> concept valid-specialization = // exposition only requires { typename T<Args...>; }; struct default-impls { // exposition only static constexpr auto get-attrs = see below; // exposition only static constexpr auto get-env = see below; // exposition only static constexpr auto get-state = see below; // exposition only static constexpr auto start = see below; // exposition only static constexpr auto complete = see below; // exposition only }; template<class Tag> struct impls-for : default-impls {}; // exposition only template<class Sndr, class Rcvr> // exposition only using state-type = decay_t<call-result-t< decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&>>; template<class Index, class Sndr, class Rcvr> // exposition only using env-type = call-result-t< decltype(impls-for<tag_of_t<Sndr>>::get-env), Index, state-type<Sndr, Rcvr>&, const Rcvr&>; template<class Sndr, size_t I = 0> using child-type = decltype(declval<Sndr>().template get<I+2>()); // exposition only template<class Sndr> using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only template<class Sndr, class Rcvr> struct basic-state { // exposition only basic-state(Sndr&& sndr, Rcvr&& rcvr) noexcept(see below) : rcvr(std::move(rcvr)) , state(impls-for<tag_of_t<Sndr>>::get-state(std::forward<Sndr>(sndr), rcvr)) { } Rcvr rcvr; // exposition only state-type<Sndr, Rcvr> state; // exposition only }; template<class Sndr, class Rcvr, class Index> requires valid-specialization<env-type, Index, Sndr, Rcvr> struct basic-receiver { // exposition only using receiver_concept = receiver_t; using tag-t = tag_of_t<Sndr>; // exposition only using state-t = state-type<Sndr, Rcvr>; // exposition only static constexpr const auto& complete = impls-for<tag-t>::complete; // exposition only template<class... Args> requires callable<decltype(complete), Index, state-t&, Rcvr&, set_value_t, Args...> void set_value(Args&&... args) && noexcept { complete(Index(), op->state, op->rcvr, set_value_t(), std::forward<Args>(args)...); } template<class Error> requires callable<decltype(complete), Index, state-t&, Rcvr&, set_error_t, Error> void set_error(Error&& err) && noexcept { complete(Index(), op->state, op->rcvr, set_error_t(), std::forward<Error>(err)); } void set_stopped() && noexcept requires callable<decltype(complete), Index, state-t&, Rcvr&, set_stopped_t> { complete(Index(), op->state, op->rcvr, set_stopped_t()); } auto get_env() const noexcept -> env-type<Index, Sndr, Rcvr> { return impls-for<tag-t>::get-env(Index(), op->state, op->rcvr); } basic-state<Sndr, Rcvr>* op; // exposition only }; constexpr auto connect-all = see below; // exposition only template<class Sndr, class Rcvr> using connect-all-result = call-result-t< // exposition only decltype(connect-all), basic-state<Sndr, Rcvr>*, Sndr, indices-for<Sndr>>; template<class Sndr, class Rcvr> requires valid-specialization<state-type, Sndr, Rcvr> && valid-specialization<connect-all-result, Sndr, Rcvr> struct basic-operation : basic-state<Sndr, Rcvr> { // exposition only using operation_state_concept = operation_state_t; using tag-t = tag_of_t<Sndr>; // exposition only connect-all-result<Sndr, Rcvr> inner-ops; // exposition only basic-operation(Sndr&& sndr, Rcvr&& rcvr) noexcept(see below) // exposition only : basic-state<Sndr, Rcvr>(std::forward<Sndr>(sndr), std::move(rcvr)), inner-ops(connect-all(this, std::forward<Sndr>(sndr), indices-for<Sndr>())) {} void start() & noexcept { auto& [...ops] = inner-ops; impls-for<tag-t>::start(this->state, this->rcvr, ops...); } }; template<class Sndr, class Env> using completion-signatures-for = see below; // exposition only template<class Tag, class Data, class... Child> struct basic-sender : product-type<Tag, Data, Child...> { // exposition only using sender_concept = sender_t; using indices-for = index_sequence_for<Child...>; // exposition only decltype(auto) get_env() const noexcept { auto& [_, data, ...child] = *this; return impls-for<Tag>::get-attrs(data, child...); } template<decays-to<basic-sender> Self, receiver Rcvr> auto connect(this Self&& self, Rcvr rcvr) noexcept(see below) -> basic-operation<Self, Rcvr> { return {std::forward<Self>(self), std::move(rcvr)}; } template<decays-to<basic-sender> Self, class Env> auto get_completion_signatures(this Self&& self, Env&& env) noexcept -> completion-signatures-for<Self, Env> { return {}; } }; }
The default template argument for the Data template parameter denotes an unspecified empty trivially copyable class type that models semiregular.
It is unspecified whether a specialization of basic-sender is an aggregate.
An expression of type basic-sender is usable as the initializer of a structured binding declaration ([dcl.struct.bind]).
The expression in the noexcept clause of the constructor of basic-state is is_nothrow_move_constructible_v<Rcvr> && nothrow-callable<decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&> && (same_as<state-type<Sndr, Rcvr>, get-state-result> || is_nothrow_constructible_v<state-type<Sndr, Rcvr>, get-state-result>) where get-state-result is call-result-t<decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&>.
The object connect-all is initialized with a callable object equivalent to the following lambda:
[]<class Sndr, class Rcvr, size_t... Is>( basic-state<Sndr, Rcvr>* op, Sndr&& sndr, index_sequence<Is...>) noexcept(see below) -> decltype(auto) { auto& [_, data, ...child] = sndr; return product-type{connect( std::forward_like<Sndr>(child), basic-receiver<Sndr, Rcvr, integral_constant<size_t, Is>>{op})...}; }
Constraints: The expression in the return statement is well-formed.
Remarks: The expression in the noexcept clause is true if the return statement is not potentially throwing; otherwise, false.
The expression in the noexcept clause of the constructor of basic-operation is: is_nothrow_constructible_v<basic-state<Self, Rcvr>, Self, Rcvr> && noexcept(connect-all(this, std::forward<Sndr>(sndr), indices-for<Sndr>()))
The expression in the noexcept clause of the connect member function of basic-sender is: is_nothrow_constructible_v<basic-operation<Self, Rcvr>, Self, Rcvr>
The member default-impls​::​get-attrs is initialized with a callable object equivalent to the following lambda: [](const auto&, const auto&... child) noexcept -> decltype(auto) { if constexpr (sizeof...(child) == 1) return (FWD-ENV(get_env(child)), ...); else return env<>(); }
The member default-impls​::​get-env is initialized with a callable object equivalent to the following lambda: [](auto, auto&, const auto& rcvr) noexcept -> decltype(auto) { return FWD-ENV(get_env(rcvr)); }
The member default-impls​::​get-state is initialized with a callable object equivalent to the following lambda: []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> decltype(auto) { auto& [_, data, ...child] = sndr; return std::forward_like<Sndr>(data); }
The member default-impls​::​start is initialized with a callable object equivalent to the following lambda: [](auto&, auto&, auto&... ops) noexcept -> void { (execution::start(ops), ...); }
The member default-impls​::​complete is initialized with a callable object equivalent to the following lambda: []<class Index, class Rcvr, class Tag, class... Args>( Index, auto& state, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void requires callable<Tag, Rcvr, Args...> { static_assert(Index::value == 0); Tag()(std::move(rcvr), std::forward<Args>(args)...); }
For a subexpression sndr let Sndr be decltype((sndr)).
Let rcvr be a receiver with an associated environment of type Env such that sender_in<Sndr, Env> is true.
completion-signatures-for<Sndr, Env> denotes a specialization of completion_signatures, the set of whose template arguments correspond to the set of completion operations that are potentially evaluated as a result of starting ([exec.async.ops]) the operation state that results from connecting sndr and rcvr.
When sender_in<Sndr, Env> is false, the type denoted by completion-signatures-for<Sndr, Env>, if any, is not a specialization of completion_signatures.
Recommended practice: When sender_in<Sndr, Env> is false, implementations are encouraged to use the type denoted by completion-signatures-for<Sndr, Env> to communicate to users why.
template<sender Sndr, queryable Env> constexpr auto write-env(Sndr&& sndr, Env&& env); // exposition only
write-env is an exposition-only sender adaptor that, when connected with a receiver rcvr, connects the adapted sender with a receiver whose execution environment is the result of joining the queryable argument env to the result of get_env(rcvr).
Let write-env-t be an exposition-only empty class type.
Returns: make-sender(write-env-t(), std::forward<Env>(env), std::forward<Sndr>(sndr))
Remarks: The exposition-only class template impls-for ([exec.snd.general]) is specialized for write-env-t as follows: template<> struct impls-for<write-env-t> : default-impls { static constexpr auto get-env = [](auto, const auto& state, const auto& rcvr) noexcept { return see below; }; };
Invocation of impls-for<write-env-t>​::​get-env returns an object e such that
  • decltype(e) models queryable and
  • given a query object q, the expression e.query(q) is expression-equivalent to state.query(q) if that expression is valid, otherwise, e.query(q) is expression-equivalent to get_env(rcvr).query(q).

33.9.3 Sender concepts [exec.snd.concepts]

The sender concept defines the requirements for a sender type ([exec.async.ops]).
The sender_in concept defines the requirements for a sender type that can create asynchronous operations given an associated environment type.
The sender_to concept defines the requirements for a sender type that can connect with a specific receiver type.
The get_env customization point object is used to access a sender's associated attributes.
The connect customization point object is used to connect ([exec.async.ops]) a sender and a receiver to produce an operation state.
namespace std::execution { template<class Sigs> concept valid-completion-signatures = see below; // exposition only template<class Sndr> concept is-sender = // exposition only derived_from<typename Sndr::sender_concept, sender_t>; template<class Sndr> concept enable-sender = // exposition only is-sender<Sndr> || is-awaitable<Sndr, env-promise<env<>>>; // [exec.awaitable] template<class Sndr> concept sender = bool(enable-sender<remove_cvref_t<Sndr>>) && requires (const remove_cvref_t<Sndr>& sndr) { { get_env(sndr) } -> queryable; } && move_constructible<remove_cvref_t<Sndr>> && constructible_from<remove_cvref_t<Sndr>, Sndr>; template<class Sndr, class Env = env<>> concept sender_in = sender<Sndr> && queryable<Env> && requires (Sndr&& sndr, Env&& env) { { get_completion_signatures(std::forward<Sndr>(sndr), std::forward<Env>(env)) } -> valid-completion-signatures; }; template<class Sndr, class Rcvr> concept sender_to = sender_in<Sndr, env_of_t<Rcvr>> && receiver_of<Rcvr, completion_signatures_of_t<Sndr, env_of_t<Rcvr>>> && requires (Sndr&& sndr, Rcvr&& rcvr) { connect(std::forward<Sndr>(sndr), std::forward<Rcvr>(rcvr)); }; }
Given a subexpression sndr, let Sndr be decltype((sndr)) and let rcvr be a receiver with an associated environment whose type is Env.
A completion operation is a permissible completion for Sndr and Env if its completion signature appears in the argument list of the specialization of completion_signatures denoted by completion_signatures_of_t<Sndr, Env>.
Sndr and Env model sender_in<Sndr, Env> if all the completion operations that are potentially evaluated by connecting sndr to rcvr and starting the resulting operation state are permissible completions for Sndr and Env.
A type models the exposition-only concept valid-completion-signatures if it denotes a specialization of the completion_signatures class template.
The exposition-only concepts sender-of and sender-in-of define the requirements for a sender type that completes with a given unique set of value result types.
namespace std::execution { template<class... As> using value-signature = set_value_t(As...); // exposition only template<class Sndr, class Env, class... Values> concept sender-in-of = sender_in<Sndr, Env> && MATCHING-SIG( // see [exec.general] set_value_t(Values...), value_types_of_t<Sndr, Env, value-signature, type_identity_t>); template<class Sndr, class... Values> concept sender-of = sender-in-of<Sndr, env<>, Values...>; }
Let sndr be an expression such that decltype((sndr)) is Sndr.
The type tag_of_t<Sndr> is as follows:
  • If the declaration auto&& [tag, data, ...children] = sndr; would be well-formed, tag_of_t<Sndr> is an alias for decltype(auto(tag)).
  • Otherwise, tag_of_t<Sndr> is ill-formed.
Let sender-for be an exposition-only concept defined as follows: namespace std::execution { template<class Sndr, class Tag> concept sender-for = sender<Sndr> && same_as<tag_of_t<Sndr>, Tag>; }
For a type T, SET-VALUE-SIG(T) denotes the type set_value_t() if T is cv void; otherwise, it denotes the type set_value_t(T).
Library-provided sender types
  • always expose an overload of a member connect that accepts an rvalue sender and
  • only expose an overload of a member connect that accepts an lvalue sender if they model copy_constructible.

33.9.4 Awaitable helpers [exec.awaitable]

The sender concepts recognize awaitables as senders.
For [exec], an awaitable is an expression that would be well-formed as the operand of a co_await expression within a given context.
For a subexpression c, let GET-AWAITER(c, p) be expression-equivalent to the series of transformations and conversions applied to c as the operand of an await-expression in a coroutine, resulting in lvalue e as described by [expr.await], where p is an lvalue referring to the coroutine's promise, which has type Promise.
[Note 1: 
This includes the invocation of the promise type's await_transform member if any, the invocation of the operator co_await picked by overload resolution if any, and any necessary implicit conversions and materializations.
— end note]
Let is-awaitable be the following exposition-only concept: namespace std { template<class T> concept await-suspend-result = see below; // exposition only template<class A, class Promise> concept is-awaiter = // exposition only requires (A& a, coroutine_handle<Promise> h) { a.await_ready() ? 1 : 0; { a.await_suspend(h) } -> await-suspend-result; a.await_resume(); }; template<class C, class Promise> concept is-awaitable = // exposition only requires (C (*fc)() noexcept, Promise& p) { { GET-AWAITER(fc(), p) } -> is-awaiter<Promise>; }; }
await-suspend-result<T> is true if and only if one of the following is true:
  • T is void, or
  • T is bool, or
  • T is a specialization of coroutine_handle.
For a subexpression c such that decltype((c)) is type C, and an lvalue p of type Promise, await-result-
type
<C, Promise>
denotes the type decltype(GET-AWAITER(c, p).await_resume()).
Let with-await-transform be the exposition-only class template: namespace std::execution { template<class T, class Promise> concept has-as-awaitable = // exposition only requires (T&& t, Promise& p) { { std::forward<T>(t).as_awaitable(p) } -> is-awaitable<Promise&>; }; template<class Derived> struct with-await-transform { // exposition only template<class T> T&& await_transform(T&& value) noexcept { return std::forward<T>(value); } template<has-as-awaitable<Derived> T> decltype(auto) await_transform(T&& value) noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>()))) { return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*this)); } }; }
Let env-promise be the exposition-only class template: namespace std::execution { template<class Env> struct env-promise : with-await-transform<env-promise<Env>> { // exposition only unspecified get_return_object() noexcept; unspecified initial_suspend() noexcept; unspecified final_suspend() noexcept; void unhandled_exception() noexcept; void return_void() noexcept; coroutine_handle<> unhandled_stopped() noexcept; const Env& get_env() const noexcept; }; }
[Note 2: 
Specializations of env-promise are used only for the purpose of type computation; its members need not be defined.
— end note]

33.9.5 execution​::​default_domain [exec.domain.default]

namespace std::execution { struct default_domain { template<sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) static constexpr sender decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) noexcept(see below); template<sender Sndr, queryable Env> static constexpr queryable decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept; template<class Tag, sender Sndr, class... Args> static constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) noexcept(see below); }; }
template<sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) constexpr sender decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) noexcept(see below);
Let e be the expression tag_of_t<Sndr>().transform_sender(std::forward<Sndr>(sndr), env...) if that expression is well-formed; otherwise, std​::​forward<Sndr>(sndr).
Returns: e.
Remarks: The exception specification is equivalent to noexcept(e).
template<sender Sndr, queryable Env> constexpr queryable decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept;
Let e be the expression tag_of_t<Sndr>().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env)) if that expression is well-formed; otherwise, static_cast<Env>(std​::​forward<Env>(env)).
Mandates: noexcept(e) is true.
Returns: e.
template<class Tag, sender Sndr, class... Args> constexpr decltype(auto) apply_sender(Tag, Sndr&& sndr, Args&&... args) noexcept(see below);
Let e be the expression Tag().apply_sender(std::forward<Sndr>(sndr), std::forward<Args>(args)...)
Constraints: e is a well-formed expression.
Returns: e.
Remarks: The exception specification is equivalent to noexcept(e).

33.9.6 execution​::​transform_sender [exec.snd.transform]

namespace std::execution { template<class Domain, sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) constexpr sender decltype(auto) transform_sender(Domain dom, Sndr&& sndr, const Env&... env) noexcept(see below); }
Let transformed-sndr be the expression dom.transform_sender(std::forward<Sndr>(sndr), env...) if that expression is well-formed; otherwise, default_domain().transform_sender(std::forward<Sndr>(sndr), env...)
Let final-sndr be the expression transformed-sndr if transformed-sndr and sndr have the same type ignoring cv-qualifiers; otherwise, it is the expression transform_sender(dom, transformed-sndr, env...).
Returns: final-sndr.
Remarks: The exception specification is equivalent to noexcept(final-sndr).

33.9.7 execution​::​transform_env [exec.snd.transform.env]

namespace std::execution { template<class Domain, sender Sndr, queryable Env> constexpr queryable decltype(auto) transform_env(Domain dom, Sndr&& sndr, Env&& env) noexcept; }
Let e be the expression dom.transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env)) if that expression is well-formed; otherwise, default_domain().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))
Mandates: noexcept(e) is true.
Returns: e.

33.9.8 execution​::​apply_sender [exec.snd.apply]

namespace std::execution { template<class Domain, class Tag, sender Sndr, class... Args> constexpr decltype(auto) apply_sender(Domain dom, Tag, Sndr&& sndr, Args&&... args) noexcept(see below); }
Let e be the expression dom.apply_sender(Tag(), std::forward<Sndr>(sndr), std::forward<Args>(args)...) if that expression is well-formed; otherwise, default_domain().apply_sender(Tag(), std::forward<Sndr>(sndr), std::forward<Args>(args)...)
Constraints: The expression e is well-formed.
Returns: e.
Remarks: The exception specification is equivalent to noexcept(e).

33.9.9 execution​::​get_completion_signatures [exec.getcomplsigs]

get_completion_signatures is a customization point object.
Let sndr be an expression such that decltype((sndr)) is Sndr, and let env be an expression such that decltype((env)) is Env.
Let new_sndr be the expression transform_sender(decltype(get-domain-late(sndr, env)), sndr, env), and let NewSndr be decltype((new_sndr)).
Then get_completion_signatures(sndr, env) is expression-equivalent to (void(sndr), void(env), CS()) except that void(sndr) and void(env) are indeterminately sequenced, where CS is:
  • decltype(new_sndr.get_completion_signatures(env)) if that type is well-formed,
  • Otherwise, remove_cvref_t<NewSndr>​::​completion_signatures if that type is well-formed,
  • Otherwise, if is-awaitable<NewSndr, env-promise<Env>> is true, then: completion_signatures< SET-VALUE-SIG(await-result-type<NewSndr, env-promise<Env>>), // ([exec.snd.concepts]) set_error_t(exception_ptr), set_stopped_t()>
  • Otherwise, CS is ill-formed.
Let rcvr be an rvalue whose type Rcvr models receiver, and let Sndr be the type of a sender such that sender_in<Sndr, env_of_t<Rcvr>> is true.
Let Sigs... be the template arguments of the completion_signatures specialization named by completion_signatures_of_t<Sndr, env_of_t<Rcvr>>.
Let CSO be a completion function.
If sender Sndr or its operation state cause the expression CSO(rcvr, args...) to be potentially evaluated ([basic.def.odr]) then there shall be a signature Sig in Sigs... such that MATCHING-SIG(decayed-typeof<CSO>(decltype(args)...), Sig) is true ([exec.general]).

33.9.10 execution​::​connect [exec.connect]

connect connects ([exec.async.ops]) a sender with a receiver.
The name connect denotes a customization point object.
For subexpressions sndr and rcvr, let Sndr be decltype((sndr)) and Rcvr be decltype((rcvr)), let new_sndr be the expression transform_sender(decltype(get-domain-late(sndr, get_env(rcvr))){}, sndr, get_env(rcvr)) and let DS and DR be decay_t<decltype((new_sndr))> and decay_t<Rcvr>, respectively.
Let connect-awaitable-promise be the following exposition-only class:
namespace std::execution { struct connect-awaitable-promise : with-await-transform<connect-awaitable-promise> { connect-awaitable-promise(DS&, DR& rcvr) noexcept : rcvr(rcvr) {} suspend_always initial_suspend() noexcept { return {}; } [[noreturn]] suspend_always final_suspend() noexcept { terminate(); } [[noreturn]] void unhandled_exception() noexcept { terminate(); } [[noreturn]] void return_void() noexcept { terminate(); } coroutine_handle<> unhandled_stopped() noexcept { set_stopped(std::move(rcvr)); return noop_coroutine(); } operation-state-task get_return_object() noexcept { return operation-state-task{ coroutine_handle<connect-awaitable-promise>::from_promise(*this)}; } env_of_t<DR> get_env() const noexcept { return execution::get_env(rcvr); } private: DR& rcvr; // exposition only }; }
Let operation-state-task be the following exposition-only class: namespace std::execution { struct operation-state-task { // exposition only using operation_state_concept = operation_state_t; using promise_type = connect-awaitable-promise; explicit operation-state-task(coroutine_handle<> h) noexcept : coro(h) {} operation-state-task(operation-state-task&&) = delete; ~operation-state-task() { coro.destroy(); } void start() & noexcept { coro.resume(); } private: coroutine_handle<> coro; // exposition only }; }
Let V name the type await-result-type<DS, connect-awaitable-promise>, let Sigs name the type completion_signatures< SET-VALUE-SIG(V), // see ([exec.snd.concepts]) set_error_t(exception_ptr), set_stopped_t()> and let connect-awaitable be an exposition-only coroutine defined as follows: namespace std::execution { template<class Fun, class... Ts> auto suspend-complete(Fun fun, Ts&&... as) noexcept { // exposition only auto fn = [&, fun]() noexcept { fun(std::forward<Ts>(as)...); }; struct awaiter { decltype(fn) fn; // exposition only static constexpr bool await_ready() noexcept { return false; } void await_suspend(coroutine_handle<>) noexcept { fn(); } [[noreturn]] void await_resume() noexcept { unreachable(); } }; return awaiter{fn}; } operation-state-task connect-awaitable(DS sndr, DR rcvr) requires receiver_of<DR, Sigs> { exception_ptr ep; try { if constexpr (same_as<V, void>) { co_await std::move(sndr); co_await suspend-complete(set_value, std::move(rcvr)); } else { co_await suspend-complete(set_value, std::move(rcvr), co_await std::move(sndr)); } } catch(...) { ep = current_exception(); } co_await suspend-complete(set_error, std::move(rcvr), std::move(ep)); } }
The expression connect(sndr, rcvr) is expression-equivalent to:
  • new_sndr.connect(rcvr) if that expression is well-formed.
    Mandates: The type of the expression above satisfies operation_state.
  • Otherwise, connect-awaitable(new_sndr, rcvr).
Mandates: sender<Sndr> && receiver<Rcvr> is true.

33.9.11 Sender factories [exec.factories]

33.9.11.1 execution​::​schedule [exec.schedule]

schedule obtains a schedule sender ([exec.async.ops]) from a scheduler.
The name schedule denotes a customization point object.
For a subexpression sch, the expression schedule(sch) is expression-equivalent to sch.schedule().
Mandates: The type of sch.schedule() satisfies sender.
If the expression get_completion_scheduler<set_value_t>(get_env(sch.schedule())) == sch is ill-formed or evaluates to false, the behavior of calling schedule(sch) is undefined.

33.9.11.2 execution​::​just, execution​::​just_error, execution​::​just_stopped [exec.just]

just, just_error, and just_stopped are sender factories whose asynchronous operations complete synchronously in their start operation with a value completion operation, an error completion operation, or a stopped completion operation, respectively.
The names just, just_error, and just_stopped denote customization point objects.
Let just-cpo be one of just, just_error, or just_stopped.
For a pack of subexpressions ts, let Ts be the pack of types decltype((ts)).
The expression just-cpo(ts...) is ill-formed if
  • (movable-value<Ts> &&...) is false, or
  • just-cpo is just_error and sizeof...(ts) == 1 is false, or
  • just-cpo is just_stopped and sizeof...(ts) == 0 is false.
Otherwise, it is expression-equivalent to make-sender(just-cpo, product-type{ts...}).
For just, just_error, and just_stopped, let set-cpo be set_value, set_error, and set_stopped, respectively.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for just-cpo as follows: namespace std::execution { template<> struct impls-for<decayed-typeof<just-cpo>> : default-impls { static constexpr auto start = [](auto& state, auto& rcvr) noexcept -> void { auto& [...ts] = state; set-cpo(std::move(rcvr), std::move(ts)...); }; }; }

33.9.11.3 execution​::​read_env [exec.read.env]

read_env is a sender factory for a sender whose asynchronous operation completes synchronously in its start operation with a value completion result equal to a value read from the receiver's associated environment.
read_env is a customization point object.
For some query object q, the expression read_env(q) is expression-equivalent to make-sender(read_env, q).
The exposition-only class template impls-for ([exec.snd.general]) is specialized for read_env as follows: namespace std::execution { template<> struct impls-for<decayed-typeof<read_env>> : default-impls { static constexpr auto start = [](auto query, auto& rcvr) noexcept -> void { TRY-SET-VALUE(rcvr, query(get_env(rcvr))); }; }; }

33.9.12 Sender adaptors [exec.adapt]

33.9.12.1 General [exec.adapt.general]

Subclause [exec.adapt] specifies a set of sender adaptors.
The bitwise inclusive or operator is overloaded for the purpose of creating sender chains.
The adaptors also support function call syntax with equivalent semantics.
Unless otherwise specified:
  • A sender adaptor is prohibited from causing observable effects, apart from moving and copying its arguments, before the returned sender is connected with a receiver using connect, and start is called on the resulting operation state.
  • A parent sender ([exec.async.ops]) with a single child sender sndr has an associated attribute object equal to FWD-ENV(get_env(sndr)) ([exec.fwd.env]).
  • A parent sender with more than one child sender has an associated attributes object equal to env<>{}.
  • When a parent sender is connected to a receiver rcvr, any receiver used to connect a child sender has an associated environment equal to FWD-ENV(get_env(rcvr)).
  • These requirements apply to any function that is selected by the implementation of the sender adaptor.
If a sender returned from a sender adaptor specified in [exec.adapt] is specified to include set_error_t(Err) among its set of completion signatures where decay_t<Err> denotes the type exception_ptr, but the implementation does not potentially evaluate an error completion operation with an exception_ptr argument, the implementation is allowed to omit the exception_ptr error completion signature from the set.

33.9.12.2 Closure objects [exec.adapt.obj]

A pipeable sender adaptor closure object is a function object that accepts one or more sender arguments and returns a sender.
For a pipeable sender adaptor closure object c and an expression sndr such that decltype((sndr)) models sender, the following expressions are equivalent and yield a sender: c(sndr) sndr | c
Given an additional pipeable sender adaptor closure object d, the expression c | d produces another pipeable sender adaptor closure object e:
e is a perfect forwarding call wrapper ([func.require]) with the following properties:
  • Its target object is an object d2 of type decltype(auto(d)) direct-non-list-initialized with d.
  • It has one bound argument entity, an object c2 of type decltype(auto(c)) direct-non-list-initialized with c.
  • Its call pattern is d2(c2(arg)), where arg is the argument used in a function call expression of e.
The expression c | d is well-formed if and only if the initializations of the state entities ([func.def]) of e are all well-formed.
An object t of type T is a pipeable sender adaptor closure object if T models derived_from<sender_adaptor_closure<T>>, T has no other base classes of type sender_adaptor_closure<U> for any other type U, and T does not satisfy sender.
The template parameter D for sender_adaptor_closure can be an incomplete type.
Before any expression of type cv D appears as an operand to the | operator, D shall be complete and model derived_from<sender_adaptor_closure<D>>.
The behavior of an expression involving an object of type cv D as an operand to the | operator is undefined if overload resolution selects a program-defined operator| function.
A pipeable sender adaptor object is a customization point object that accepts a sender as its first argument and returns a sender.
If a pipeable sender adaptor object accepts only one argument, then it is a pipeable sender adaptor closure object.
If a pipeable sender adaptor object adaptor accepts more than one argument, then let sndr be an expression such that decltype((sndr)) models sender, let args... be arguments such that adaptor(sndr, args...) is a well-formed expression as specified below, and let BoundArgs be a pack that denotes decltype(auto(args))....
The expression adaptor(args...) produces a pipeable sender adaptor closure object f that is a perfect forwarding call wrapper with the following properties:
  • Its target object is a copy of adaptor.
  • Its bound argument entities bound_args consist of objects of types BoundArgs... direct-non-list-initialized with std​::​forward<decltype((args))>(args)..., respectively.
  • Its call pattern is adaptor(rcvr, bound_args...), where rcvr is the argument used in a function call expression of f.
The expression adaptor(args...) is well-formed if and only if the initializations of the bound argument entities of the result, as specified above, are all well-formed.

33.9.12.3 execution​::​starts_on [exec.starts.on]

starts_on adapts an input sender into a sender that will start on an execution agent belonging to a particular scheduler's associated execution resource.
The name starts_on denotes a customization point object.
For subexpressions sch and sndr, if decltype((
sch))
does not satisfy scheduler, or decltype((sndr)) does not satisfy sender, starts_on(sch, sndr) is ill-formed.
Otherwise, the expression starts_on(sch, sndr) is expression-equivalent to: transform_sender( query-or-default(get_domain, sch, default_domain()), make-sender(starts_on, sch, sndr)) except that sch is evaluated only once.
Let out_sndr and env be subexpressions such that OutSndr is decltype((out_sndr)).
If sender-for<OutSndr, starts_on_t> is false, then the expressions starts_on.transform_env(out_sndr, env) and starts_on.transform_sender(out_sndr, env) are ill-formed; otherwise
  • starts_on.transform_env(out_sndr, env) is equivalent to: auto&& [_, sch, _] = out_sndr; return JOIN-ENV(SCHED-ENV(sch), FWD-ENV(env));
  • starts_on.transform_sender(out_sndr, env) is equivalent to: auto&& [_, sch, sndr] = out_sndr; return let_value( schedule(sch), [sndr = std::forward_like<OutSndr>(sndr)]() mutable noexcept(is_nothrow_move_constructible_v<decay_t<OutSndr>>) { return std::move(sndr); });
Let out_sndr be a subexpression denoting a sender returned from starts_on(sch, sndr) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall start sndr on an execution agent of the associated execution resource of sch.
If scheduling onto sch fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.

33.9.12.4 execution​::​continues_on [exec.continues.on]

continues_on adapts a sender into one that completes on the specified scheduler.
The name continues_on denotes a pipeable sender adaptor object.
For subexpressions sch and sndr, if decltype((sch)) does not satisfy scheduler, or decltype((sndr)) does not satisfy sender, continues_on(sndr, sch) is ill-formed.
Otherwise, the expression continues_on(sndr, sch) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(continues_on, sch, sndr)) except that sndr is evaluated only once.
The exposition-only class template impls-for is specialized for continues_on_t as follows: namespace std::execution { template<> struct impls-for<continues_on_t> : default-impls { static constexpr auto get-attrs = [](const auto& data, const auto& child) noexcept -> decltype(auto) { return JOIN-ENV(SCHED-ATTRS(data), FWD-ENV(get_env(child))); }; }; }
Let sndr and env be subexpressions such that Sndr is decltype((sndr)).
If sender-for<Sndr, continues_on_t> is false, then the expression continues_on.transform_sender(sndr, env) is ill-formed; otherwise, it is equal to: auto [_, data, child] = sndr; return schedule_from(std::move(data), std::move(child));
[Note 1: 
This causes the continues_on(sndr, sch) sender to become schedule_from(sch, sndr) when it is connected with a receiver whose execution domain does not customize continues_on.
— end note]
Let out_sndr be a subexpression denoting a sender returned from continues_on(sndr, sch) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall start sndr on the current execution agent and execute completion operations on out_rcvr on an execution agent of the execution resource associated with sch.
If scheduling onto sch fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.

33.9.12.5 execution​::​schedule_from [exec.schedule.from]

schedule_from schedules work dependent on the completion of a sender onto a scheduler's associated execution resource.
[Note 1: 
schedule_from is not meant to be used in user code; it is used in the implementation of continues_on.
— end note]
The name schedule_from denotes a customization point object.
For some subexpressions sch and sndr, let Sch be decltype((sch)) and Sndr be decltype((sndr)).
If Sch does not satisfy scheduler, or Sndr does not satisfy sender, schedule_from(sch, sndr) is ill-formed.
Otherwise, the expression schedule_from(sch, sndr) is expression-equivalent to: transform_sender( query-or-default(get_domain, sch, default_domain()), make-sender(schedule_from, sch, sndr)) except that sch is evaluated only once.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for schedule_from_t as follows: namespace std::execution { template<> struct impls-for<schedule_from_t> : default-impls { static constexpr auto get-attrs = see below; static constexpr auto get-state = see below; static constexpr auto complete = see below; }; }
The member impls-for<schedule_from_t>​::​get-attrs is initialized with a callable object equivalent to the following lambda: [](const auto& data, const auto& child) noexcept -> decltype(auto) { return JOIN-ENV(SCHED-ATTRS(data), FWD-ENV(get_env(child))); }
The member impls-for<schedule_from_t>​::​get-state is initialized with a callable object equivalent to the following lambda: []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below) requires sender_in<child-type<Sndr>, env_of_t<Rcvr>> { auto& [_, sch, child] = sndr; using sched_t = decltype(auto(sch)); using variant_t = see below; using receiver_t = see below; using operation_t = connect_result_t<schedule_result_t<sched_t>, receiver_t>; constexpr bool nothrow = noexcept(connect(schedule(sch), receiver_t{nullptr})); struct state-type { Rcvr& rcvr; // exposition only variant_t async-result; // exposition only operation_t op-state; // exposition only explicit state-type(sched_t sch, Rcvr& rcvr) noexcept(nothrow) : rcvr(rcvr), op-state(connect(schedule(sch), receiver_t{this})) {} }; return state-type{sch, rcvr}; }
Objects of the local class state-type can be used to initialize a structured binding.
Let Sigs be a pack of the arguments to the completion_signatures specialization named by completion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>.
Let as-tuple be an alias template that transforms a completion signature Tag(Args...) into the tuple specialization decayed-tuple<Tag, Args...>.
Then variant_t denotes the type variant<monostate, as-tuple<Sigs>...>, except with duplicate types removed.
receiver_t is an alias for the following exposition-only class: namespace std::execution { struct receiver-type { using receiver_concept = receiver_t; state-type* state; // exposition only void set_value() && noexcept { visit( [this]<class Tuple>(Tuple& result) noexcept -> void { if constexpr (!same_as<monostate, Tuple>) { auto& [tag, ...args] = result; tag(std::move(state->rcvr), std::move(args)...); } }, state->async-result); } template<class Error> void set_error(Error&& err) && noexcept { execution::set_error(std::move(state->rcvr), std::forward<Error>(err)); } void set_stopped() && noexcept { execution::set_stopped(std::move(state->rcvr)); } decltype(auto) get_env() const noexcept { return FWD-ENV(execution::get_env(state->rcvr)); } }; }
The expression in the noexcept clause of the lambda is true if the construction of the returned state-type object is not potentially throwing; otherwise, false.
The member impls-for<schedule_from_t>​::​complete is initialized with a callable object equivalent to the following lambda: []<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { using result_t = decayed-tuple<Tag, Args...>; constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>; try { state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...); } catch (...) { if constexpr (!nothrow) { set_error(std::move(rcvr), current_exception()); return; } } start(state.op-state); };
Let out_sndr be a subexpression denoting a sender returned from schedule_from(sch, sndr) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall start sndr on the current execution agent and execute completion operations on out_rcvr on an execution agent of the execution resource associated with sch.
If scheduling onto sch fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.

33.9.12.6 execution​::​on [exec.on]

The on sender adaptor has two forms:
  • on(sch, sndr), which starts a sender sndr on an execution agent belonging to a scheduler sch's associated execution resource and that, upon sndr's completion, transfers execution back to the execution resource on which the on sender was started.
  • on(sndr, sch, closure), which upon completion of a sender sndr, transfers execution to an execution agent belonging to a scheduler sch's associated execution resource, then executes a sender adaptor closure closure with the async results of the sender, and that then transfers execution back to the execution resource on which sndr completed.
The name on denotes a pipeable sender adaptor object.
For subexpressions sch and sndr, on(sch, sndr) is ill-formed if any of the following is true:
  • decltype((sch)) does not satisfy scheduler, or
  • decltype((sndr)) does not satisfy sender and sndr is not a pipeable sender adaptor closure object ([exec.adapt.obj]), or
  • decltype((sndr)) satisfies sender and sndr is also a pipeable sender adaptor closure object.
Otherwise, if decltype((sndr)) satisfies sender, the expression on(sch, sndr) is expression-equivalent to: transform_sender( query-or-default(get_domain, sch, default_domain()), make-sender(on, sch, sndr)) except that sch is evaluated only once.
For subexpressions sndr, sch, and closure, if the expression on(sndr, sch, closure) is ill-formed; otherwise, it is expression-equivalent to: transform_sender( get-domain-early(sndr), make-sender(on, product-type{sch, closure}, sndr)) except that sndr is evaluated only once.
Let out_sndr and env be subexpressions, let OutSndr be decltype((out_sndr)), and let Env be decltype((env)).
If sender-for<OutSndr, on_t> is false, then the expressions on.transform_env(out_sndr, env) and on.transform_sender(out_sndr, env) are ill-formed.
Otherwise: Let not-a-scheduler be an unspecified empty class type, and let not-a-sender be the exposition-only type: struct not-a-sender { using sender_concept = sender_t; auto get_completion_signatures(auto&&) const { return see below; } }; where the member function get_completion_signatures returns an object of a type that is not a specialization of the completion_signatures class template.
The expression on.transform_env(out_sndr, env) has effects equivalent to: auto&& [_, data, _] = out_sndr; if constexpr (scheduler<decltype(data)>) { return JOIN-ENV(SCHED-ENV(std::forward_like<OutSndr>(data)), FWD-ENV(std::forward<Env>(env))); } else { return std::forward<Env>(env); }
The expression on.transform_sender(out_sndr, env) has effects equivalent to: auto&& [_, data, child] = out_sndr; if constexpr (scheduler<decltype(data)>) { auto orig_sch = query-with-default(get_scheduler, env, not-a-scheduler()); if constexpr (same_as<decltype(orig_sch), not-a-scheduler>) { return not-a-sender{}; } else { return continues_on( starts_on(std::forward_like<OutSndr>(data), std::forward_like<OutSndr>(child)), std::move(orig_sch)); } } else { auto& [sch, closure] = data; auto orig_sch = query-with-default( get_completion_scheduler<set_value_t>, get_env(child), query-with-default(get_scheduler, env, not-a-scheduler())); if constexpr (same_as<decltype(orig_sch), not-a-scheduler>) { return not-a-sender{}; } else { return write-env( continues_on( std::forward_like<OutSndr>(closure)( continues_on( write-env(std::forward_like<OutSndr>(child), SCHED-ENV(orig_sch)), sch)), orig_sch), SCHED-ENV(sch)); } }
Recommended practice: Implementations should use the return type of not-a-sender​::​get_completion_signatures to inform users that their usage of on is incorrect because there is no available scheduler onto which to restore execution.
Let out_sndr be a subexpression denoting a sender returned from on(sch, sndr) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall
  • remember the current scheduler, get_scheduler(get_env(rcvr));
  • start sndr on an execution agent belonging to sch's associated execution resource;
  • upon sndr's completion, transfer execution back to the execution resource associated with the scheduler remembered in step 1; and
  • forward sndr's async result to out_rcvr.
If any scheduling operation fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.
Let out_sndr be a subexpression denoting a sender returned from on(sndr, sch, closure) or one equal to such, and let OutSndr be the type decltype((out_sndr)).
Let out_rcvr be a subexpression denoting a receiver that has an environment of type Env such that sender_in<OutSndr, Env> is true.
Let op be an lvalue referring to the operation state that results from connecting out_sndr with out_rcvr.
Calling start(op) shall
  • remember the current scheduler, which is the first of the following expressions that is well-formed:
    • get_completion_scheduler<set_value_t>(get_env(sndr))
    • get_scheduler(get_env(rcvr));
  • start sndr on the current execution agent;
  • upon sndr's completion, transfer execution to an agent owned by sch's associated execution resource;
  • forward sndr's async result as if by connecting and starting a sender closure(S), where S is a sender that completes synchronously with sndr's async result; and
  • upon completion of the operation started in the previous step, transfer execution back to the execution resource associated with the scheduler remembered in step 1 and forward the operation's async result to out_rcvr.
If any scheduling operation fails, an error completion on out_rcvr shall be executed on an unspecified execution agent.

33.9.12.7 execution​::​then, execution​::​upon_error, execution​::​upon_stopped [exec.then]

then attaches an invocable as a continuation for an input sender's value completion operation.
upon_error and upon_stopped do the same for the error and stopped completion operations, respectively, sending the result of the invocable as a value completion.
The names then, upon_error, and upon_stopped denote pipeable sender adaptor objects.
Let the expression then-cpo be one of then, upon_error, or upon_stopped.
For subexpressions sndr and f, if decltype((sndr)) does not satisfy sender, or decltype((f)) does not satisfy movable-value, then-cpo(sndr, f) is ill-formed.
Otherwise, the expression then-cpo(sndr, f) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(then-cpo, f, sndr)) except that sndr is evaluated only once.
For then, upon_error, and upon_stopped, let set-cpo be set_value, set_error, and set_stopped, respectively.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for then-cpo as follows: namespace std::execution { template<> struct impls-for<decayed-typeof<then-cpo>> : default-impls { static constexpr auto complete = []<class Tag, class... Args> (auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void { if constexpr (same_as<Tag, decayed-typeof<set-cpo>>) { TRY-SET-VALUE(rcvr, invoke(std::move(fn), std::forward<Args>(args)...)); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); } }; }; }
The expression then-cpo(sndr, f) has undefined behavior unless it returns a senderout_sndr that
  • invokes f or a copy of such with the value, error, or stopped result datums of sndr for then, upon_error, and upon_stopped, respectively, using the result value of f as out_sndr's value completion, and
  • forwards all other completion operations unchanged.

33.9.12.8 execution​::​let_value, execution​::​let_error, execution​::​let_stopped [exec.let]

let_value, let_error, and let_stopped transform a sender's value, error, and stopped completions, respectively, into a new child asynchronous operation by passing the sender's result datums to a user-specified callable, which returns a new sender that is connected and started.
For let_value, let_error, and let_stopped, let set-cpo be set_value, set_error, and set_stopped, respectively.
Let the expression let-cpo be one of let_value, let_error, or let_stopped.
For a subexpression sndr, let let-env(sndr) be expression-equivalent to the first well-formed expression below:
  • SCHED-ENV(get_completion_scheduler<decayed-typeof<set-cpo>>(get_env(sndr)))
  • MAKE-ENV(get_domain, get_domain(get_env(sndr)))
  • (void(sndr), env<>{})
The names let_value, let_error, and let_stopped denote pipeable sender adaptor objects.
For subexpressions sndr and f, let F be the decayed type of f.
If decltype((sndr)) does not satisfy sender or if decltype((f)) does not satisfy movable-value, the expression let-cpo(sndr, f) is ill-formed.
If F does not satisfy invocable, the expression let_stopped(sndr, f) is ill-formed.
Otherwise, the expression let-cpo(sndr, f) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(let-cpo, f, sndr)) except that sndr is evaluated only once.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for let-cpo as follows: namespace std::execution { template<class State, class Rcvr, class... Args> void let-bind(State& state, Rcvr& rcvr, Args&&... args); // exposition only template<> struct impls-for<decayed-typeof<let-cpo>> : default-impls { static constexpr auto get-state = see below; static constexpr auto complete = see below; }; }
Let receiver2 denote the following exposition-only class template: namespace std::execution { template<class Rcvr, class Env> struct receiver2 { using receiver_concept = receiver_t; template<class... Args> void set_value(Args&&... args) && noexcept { execution::set_value(std::move(rcvr), std::forward<Args>(args)...); } template<class Error> void set_error(Error&& err) && noexcept { execution::set_error(std::move(rcvr), std::forward<Error>(err)); } void set_stopped() && noexcept { execution::set_stopped(std::move(rcvr)); } decltype(auto) get_env() const noexcept { return see below; } Rcvr& rcvr; // exposition only Env env; // exposition only }; }
Invocation of the function receiver2​::​get_env returns an object e such that
  • decltype(e) models queryable and
  • given a query object q, the expression e.query(q) is expression-equivalent to env.query(q) if that expression is valid, otherwise e.query(q) is expression-equivalent to get_env(rcvr).query(q).
impls-for<decayed-typeof<let-cpo>>​::​get-state is initialized with a callable object equivalent to the following: []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) requires see below { auto& [_, fn, child] = sndr; using fn_t = decay_t<decltype(fn)>; using env_t = decltype(let-env(child)); using args_variant_t = see below; using ops2_variant_t = see below; struct state-type { fn_t fn; // exposition only env_t env; // exposition only args_variant_t args; // exposition only ops2_variant_t ops2; // exposition only }; return state-type{std::forward_like<Sndr>(fn), let-env(child), {}, {}}; }
Let Sigs be a pack of the arguments to the completion_signatures specialization named by completion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>.
Let LetSigs be a pack of those types in Sigs with a return type of decayed-typeof<set-cpo>.
Let as-tuple be an alias template such that as-tuple<Tag(Args...)> denotes the type decayed-tuple<Args...>.
Then args_variant_t denotes the type variant<monostate, as-tuple<LetSigs>...> except with duplicate types removed.
Given a type Tag and a pack Args, let as-sndr2 be an alias template such that as-sndr2<Tag(Args...)> denotes the type call-result-t<Fn, decay_t<Args>&...>.
Then ops2_variant_t denotes the type variant<monostate, connect_result_t<as-sndr2<LetSigs>, receiver2<Rcvr, Env>>...> except with duplicate types removed.
The requires-clause constraining the above lambda is satisfied if and only if the types args_variant_t and ops2_variant_t are well-formed.
The exposition-only function template let-bind has effects equivalent to: using args_t = decayed-tuple<Args...>; auto mkop2 = [&] { return connect( apply(std::move(state.fn), state.args.template emplace<args_t>(std::forward<Args>(args)...)), receiver2{rcvr, std::move(state.env)}); }; start(state.ops2.template emplace<decltype(mkop2())>(emplace-from{mkop2}));
impls-for<decayed-typeof<let-cpo>>​::​complete is initialized with a callable object equivalent to the following: []<class Tag, class... Args> (auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { if constexpr (same_as<Tag, decayed-typeof<set-cpo>>) { TRY-EVAL(rcvr, let-bind(state, rcvr, std::forward<Args>(args)...)); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); } }
Let sndr and env be subexpressions, and let Sndr be decltype((sndr)).
If sender-for<Sndr, decayed-typeof<let-cpo>> is false, then the expression let-cpo.transform_env(sndr, env) is ill-formed.
Otherwise, it is equal to JOIN-ENV(let-env(sndr), FWD-ENV(env)).
Let the subexpression out_sndr denote the result of the invocation let-cpo(sndr, f) or an object equal to such, and let the subexpression rcvr denote a receiver such that the expression connect(out_sndr, rcvr) is well-formed.
The expression connect(out_sndr, rcvr) has undefined behavior unless it creates an asynchronous operation ([exec.async.ops]) that, when started:
  • invokes f when set-cpo is called with sndr's result datums,
  • makes its completion dependent on the completion of a sender returned by f, and
  • propagates the other completion operations sent by sndr.

33.9.12.9 execution​::​bulk [exec.bulk]

bulk runs a task repeatedly for every index in an index space.
The name bulk denotes a pipeable sender adaptor object.
For subexpressions sndr, shape, and f, let Shape be decltype(auto(shape)).
If bulk(sndr, shape, f) is ill-formed.
Otherwise, the expression bulk(sndr, shape, f) is expression-equivalent to:
transform_sender(get-domain-early(sndr), make-sender(bulk, product-type{shape, f}, sndr)) except that sndr is evaluated only once.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for bulk_t as follows: namespace std::execution { template<> struct impls-for<bulk_t> : default-impls { static constexpr auto complete = see below; }; }
The member impls-for<bulk_t>​::​complete is initialized with a callable object equivalent to the following lambda: []<class Index, class State, class Rcvr, class Tag, class... Args> (Index, State& state, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void requires see below { if constexpr (same_as<Tag, set_value_t>) { auto& [shape, f] = state; constexpr bool nothrow = noexcept(f(auto(shape), args...)); TRY-EVAL(rcvr, [&]() noexcept(nothrow) { for (decltype(auto(shape)) i = 0; i < shape; ++i) { f(auto(i), args...); } Tag()(std::move(rcvr), std::forward<Args>(args)...); }()); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); } }
The expression in the requires-clause of the lambda above is true if and only if Tag denotes a type other than set_value_t or if the expression f(auto(shape), args...) is well-formed.
Let the subexpression out_sndr denote the result of the invocation bulk(sndr, shape, f) or an object equal to such, and let the subexpression rcvr denote a receiver such that the expression connect(out_sndr, rcvr) is well-formed.
The expression connect(out_sndr, rcvr) has undefined behavior unless it creates an asynchronous operation ([exec.async.ops]) that, when started,
  • on a value completion operation, invokes f(i, args...) for every i of type Shape in [0, shape), where args is a pack of lvalue subexpressions referring to the value completion result datums of the input sender, and
  • propagates all completion operations sent by sndr.

33.9.12.10 execution​::​split [exec.split]

split adapts an arbitrary sender into a sender that can be connected multiple times.
Let split-env be the type of an environment such that, given an instance env, the expression get_stop_token(env) is well-formed and has type inplace_stop_token.
The name split denotes a pipeable sender adaptor object.
For a subexpression sndr, let Sndr be decltype((sndr)).
If sender_in<Sndr, split-env> is false, split(sndr) is ill-formed.
Otherwise, the expression split(sndr) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(split, {}, sndr)) except that sndr is evaluated only once.
[Note 1: 
The default implementation of transform_sender will have the effect of connecting the sender to a receiver.
It will return a sender with a different tag type.
— end note]
Let local-state denote the following exposition-only class template:
namespace std::execution { struct local-state-base { // exposition only virtual ~local-state-base() = default; virtual void notify() noexcept = 0; // exposition only }; template<class Sndr, class Rcvr> struct local-state : local-state-base { // exposition only using on-stop-callback = // exposition only stop_callback_for_t<stop_token_of_t<env_of_t<Rcvr>>, on-stop-request>; local-state(Sndr&& sndr, Rcvr& rcvr) noexcept; ~local-state(); void notify() noexcept override; private: optional<on-stop-callback> on_stop; // exposition only shared-state<Sndr>* sh_state; // exposition only Rcvr* rcvr; // exposition only }; }
local-state(Sndr&& sndr, Rcvr& rcvr) noexcept;
Effects: Equivalent to: auto& [_, data, _] = sndr; this->sh_state = data.sh_state.get(); this->sh_state->inc-ref(); this->rcvr = addressof(rcvr);
~local-state();
Effects: Equivalent to: sh_state->dec-ref();
void notify() noexcept override;
Effects: Equivalent to: on_stop.reset(); visit( [this](const auto& tupl) noexcept -> void { apply( [this](auto tag, const auto&... args) noexcept -> void { tag(std::move(*rcvr), args...); }, tupl); }, sh_state->result);
Let split-receiver denote the following exposition-only class template: namespace std::execution { template<class Sndr> struct split-receiver { // exposition only using receiver_concept = receiver_t; template<class Tag, class... Args> void complete(Tag, Args&&... args) noexcept { // exposition only using tuple_t = decayed-tuple<Tag, Args...>; try { sh_state->result.template emplace<tuple_t>(Tag(), std::forward<Args>(args)...); } catch (...) { using tuple_t = tuple<set_error_t, exception_ptr>; sh_state->result.template emplace<tuple_t>(set_error, current_exception()); } sh_state->notify(); } template<class... Args> void set_value(Args&&... args) && noexcept { complete(execution::set_value, std::forward<Args>(args)...); } template<class Error> void set_error(Error&& err) && noexcept { complete(execution::set_error, std::forward<Error>(err)); } void set_stopped() && noexcept { complete(execution::set_stopped); } struct env { // exposition only shared-state<Sndr>* sh-state; // exposition only inplace_stop_token query(get_stop_token_t) const noexcept { return sh-state->stop_src.get_token(); } }; env get_env() const noexcept { return env{sh_state}; } shared-state<Sndr>* sh_state; // exposition only }; }
Let shared-state denote the following exposition-only class template: namespace std::execution { template<class Sndr> struct shared-state { using variant-type = see below; // exposition only using state-list-type = see below; // exposition only explicit shared-state(Sndr&& sndr); void start-op() noexcept; // exposition only void notify() noexcept; // exposition only void inc-ref() noexcept; // exposition only void dec-ref() noexcept; // exposition only inplace_stop_source stop_src{}; // exposition only variant-type result{}; // exposition only state-list-type waiting_states; // exposition only atomic<bool> completed{false}; // exposition only atomic<size_t> ref_count{1}; // exposition only connect_result_t<Sndr, split-receiver<Sndr>> op_state; // exposition only }; }
Let Sigs be a pack of the arguments to the completion_signatures specialization named by completion_signatures_of_t<Sndr>.
For type Tag and pack Args, let as-tuple be an alias template such that as-tuple<Tag(Args...)> denotes the type decayed-tuple<Tag, Args...>.
Then variant-type denotes the type variant<tuple<set_stopped_t>, tuple<set_error_t, exception_ptr>, as-tuple<Sigs>...> but with duplicate types removed.
Let state-list-type be a type that stores a list of pointers to local-state-base objects and that permits atomic insertion.
explicit shared-state(Sndr&& sndr);
Effects: Initializes op_state with the result of connect(std​::​forward<Sndr>(sndr), split-receiver{this}).
Postconditions: waiting_states is empty, and completed is false.
void start-op() noexcept;
Effects: Evaluates inc-ref().
If stop_src.stop_requested() is true, evaluates notify(); otherwise, evaluates start(op_state).
void notify() noexcept;
Effects: Atomically does the following:
  • Sets completed to true, and
  • Exchanges waiting_states with an empty list, storing the old value in a local prior_states.
Then, for each pointer p in prior_states, evaluates p->notify().
Finally, evaluates dec-ref().
void inc-ref() noexcept;
Effects: Increments ref_count.
void dec-ref() noexcept;
Effects: Decrements ref_count.
If the new value of ref_count is 0, calls delete this.
Synchronization: If an evaluation of dec-ref() does not decrement the ref_count to 0 then synchronizes with the evaluation of dec-ref() that decrements ref_count to 0.
Let split-impl-tag be an empty exposition-only class type.
Given an expression sndr, the expression split.transform_sender(sndr) is equivalent to: auto&& [tag, _, child] = sndr; auto* sh_state = new shared-state{std::forward_like<decltype((sndr))>(child)}; return make-sender(split-impl-tag(), shared-wrapper{sh_state, tag}); where shared-wrapper is an exposition-only class that manages the reference count of the shared-state object pointed to by sh_state.
shared-wrapper models copyable with move operations nulling out the moved-from object, copy operations incrementing the reference count by calling sh_state->inc-ref(), and assignment operations performing a copy-and-swap operation.
The destructor has no effect if sh_state is null; otherwise, it decrements the reference count by evaluating sh_state->dec-ref().
The exposition-only class template impls-for ([exec.snd.general]) is specialized for split-impl-tag as follows: namespace std::execution { template<> struct impls-for<split-impl-tag> : default-impls { static constexpr auto get-state = see below; static constexpr auto start = see below; }; }
The member impls-for<split-impl-tag>​::​get-state is initialized with a callable object equivalent to the following lambda expression: []<class Sndr>(Sndr&& sndr, auto& rcvr) noexcept { return local-state{std::forward<Sndr>(sndr), rcvr}; }
The member impls-for<split-impl-tag>​::​start is initialized with a callable object that has a function call operator equivalent to the following: template<class Sndr, class Rcvr> void operator()(local-state<Sndr, Rcvr>& state, Rcvr& rcvr) const noexcept;
Effects: If state.sh_state->completed is true, evaluates state.notify() and returns.
Otherwise, does the following in order:
  • Evaluates state.on_stop.emplace( get_stop_token(get_env(rcvr)), on-stop-request{state.sh_state->stop_src});
  • Then atomically does the following:
    • Reads the value c of state.sh_state->completed, and
    • Inserts addressof(state) into state.sh_state->waiting_states if c is false.
  • If c is true, calls state.notify() and returns.
  • Otherwise, if addressof(state) is the first item added to state.sh_state->waiting_states, evaluates state.sh_state->start-op().

33.9.12.11 execution​::​when_all [exec.when.all]

when_all and when_all_with_variant both adapt multiple input senders into a sender that completes when all input senders have completed.
when_all only accepts senders with a single value completion signature and on success concatenates all the input senders' value result datums into its own value completion operation.
when_all_with_variant(sndrs...) is semantically equivalent to when_all(into_variant(sndrs)...), where sndrs is a pack of subexpressions whose types model sender.
The names when_all and when_all_with_variant denote customization point objects.
Let sndrs be a pack of subexpressions, let Sndrs be a pack of the types decltype((sndrs))..., and let CD be the type common_type_t<decltype(get-domain-early(sndrs))...>.
The expressions when_all(sndrs...) and when_all_with_variant(sndrs...) are ill-formed if any of the following is true:
The expression when_all(sndrs...) is expression-equivalent to: transform_sender(CD(), make-sender(when_all, {}, sndrs...))
The exposition-only class template impls-for ([exec.snd.general]) is specialized for when_all_t as follows: namespace std::execution { template<> struct impls-for<when_all_t> : default-impls { static constexpr auto get-attrs = see below; static constexpr auto get-env = see below; static constexpr auto get-state = see below; static constexpr auto start = see below; static constexpr auto complete = see below; }; }
The member impls-for<when_all_t>​::​get-attrs is initialized with a callable object equivalent to the following lambda expression: [](auto&&, auto&&... child) noexcept { if constexpr (same_as<CD, default_domain>) { return env<>(); } else { return MAKE-ENV(get_domain, CD()); } }
The member impls-for<when_all_t>​::​get-env is initialized with a callable object equivalent to the following lambda expression: []<class State, class Rcvr>(auto&&, State& state, const Receiver& rcvr) noexcept { return see below; }
Returns an object e such that
  • decltype(e) models queryable, and
  • e.query(get_stop_token) is expression-equivalent to state.stop-src.get_token(), and
  • given a query object q with type other than cv stop_token_t, e.query(q) is expression-equivalent to get_env(rcvr).query(q).
The member impls-for<when_all_t>​::​get-state is initialized with a callable object equivalent to the following lambda expression: []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(e) -> decltype(e) { return e; } where e is the expression std::forward<Sndr>(sndr).apply(make-state<Rcvr>()) and where make-state is the following exposition-only class template: template<class Sndr, class Env> concept max-1-sender-in = sender_in<Sndr, Env> && // exposition only (tuple_size_v<value_types_of_t<Sndr, Env, tuple, tuple>> <= 1); enum class disposition { started, error, stopped }; // exposition only template<class Rcvr> struct make-state { template<max-1-sender-in<env_of_t<Rcvr>>... Sndrs> auto operator()(auto, auto, Sndrs&&... sndrs) const { using values_tuple = see below; using errors_variant = see below; using stop_callback = stop_callback_for_t<stop_token_of_t<env_of_t<Rcvr>>, on-stop-request>; struct state-type { void arrive(Rcvr& rcvr) noexcept { // exposition only if (0 == --count) { complete(rcvr); } } void complete(Rcvr& rcvr) noexcept; // exposition only atomic<size_t> count{sizeof...(sndrs)}; // exposition only inplace_stop_source stop_src{}; // exposition only atomic<disposition> disp{disposition::started}; // exposition only errors_variant errors{}; // exposition only values_tuple values{}; // exposition only optional<stop_callback> on_stop{nullopt}; // exposition only }; return state-type{}; } };
Let copy-fail be exception_ptr if decay-copying any of the child senders' result datums can potentially throw; otherwise, none-such, where none-such is an unspecified empty class type.
The alias values_tuple denotes the type tuple<value_types_of_t<Sndrs, env_of_t<Rcvr>, decayed-tuple, optional>...> if that type is well-formed; otherwise, tuple<>.
The alias errors_variant denotes the type variant<none-such, copy-fail, Es...> with duplicate types removed, where Es is the pack of the decayed types of all the child senders' possible error result datums.
The member void state-type​::​complete(Rcvr& rcvr) noexcept behaves as follows:
  • If disp is equal to disposition​::​started, evaluates: auto tie = []<class... T>(tuple<T...>& t) noexcept { return tuple<T&...>(t); }; auto set = [&](auto&... t) noexcept { set_value(std::move(rcvr), std::move(t)...); }; on_stop.reset(); apply( [&](auto&... opts) noexcept { apply(set, tuple_cat(tie(*opts)...)); }, values);
  • Otherwise, if disp is equal to disposition​::​error, evaluates: on_stop.reset(); visit( [&]<class Error>(Error& error) noexcept { if constexpr (!same_as<Error, none-such>) { set_error(std::move(rcvr), std::move(error)); } }, errors);
  • Otherwise, evaluates: on_stop.reset(); set_stopped(std::move(rcvr));
The member impls-for<when_all_t>​::​start is initialized with a callable object equivalent to the following lambda expression: []<class State, class Rcvr, class... Ops>( State& state, Rcvr& rcvr, Ops&... ops) noexcept -> void { state.on_stop.emplace( get_stop_token(get_env(rcvr)), on-stop-request{state.stop_src}); if (state.stop_src.stop_requested()) { state.on_stop.reset(); set_stopped(std::move(rcvr)); } else { (start(ops), ...); } }
The member impls-for<when_all_t>​::​complete is initialized with a callable object equivalent to the following lambda expression: []<class Index, class State, class Rcvr, class Set, class... Args>( this auto& complete, Index, State& state, Rcvr& rcvr, Set, Args&&... args) noexcept -> void { if constexpr (same_as<Set, set_error_t>) { if (disposition::error != state.disp.exchange(disposition::error)) { state.stop_src.request_stop(); TRY-EMPLACE-ERROR(state.errors, std::forward<Args>(args)...); } } else if constexpr (same_as<Set, set_stopped_t>) { auto expected = disposition::started; if (state.disp.compare_exchange_strong(expected, disposition::stopped)) { state.stop_src.request_stop(); } } else if constexpr (!same_as<decltype(State::values), tuple<>>) { if (state.disp == disposition::started) { auto& opt = get<Index::value>(state.values); TRY-EMPLACE-VALUE(complete, opt, std::forward<Args>(args)...); } } state.arrive(rcvr); } where TRY-EMPLACE-ERROR(v, e), for subexpressions v and e, is equivalent to: try { v.template emplace<decltype(auto(e))>(e); } catch (...) { v.template emplace<exception_ptr>(current_exception()); } if the expression decltype(auto(e))(e) is potentially throwing; otherwise, v.template emplace<decltype(auto(e))>(e); and where TRY-EMPLACE-VALUE(c, o, as...), for subexpressions c, o, and pack of subexpressions as, is equivalent to: try { o.emplace(as...); } catch (...) { c(Index(), state, rcvr, set_error, current_exception()); return; } if the expression decayed-tuple<decltype(as)...>{as...} is potentially throwing; otherwise, o.emplace(as...).
The expression when_all_with_variant(sndrs...) is expression-equivalent to: transform_sender(CD(), make-sender(when_all_with_variant, {}, sndrs...));
Given subexpressions sndr and env, if sender-for<decltype((sndr)), when_all_with_variant_t> is false, then the expression when_all_with_variant.transform_sender(sndr, env) is ill-formed; otherwise, it is equivalent to: auto&& [_, _, ...child] = sndr; return when_all(into_variant(std::forward_like<decltype((sndr))>(child))...);
[Note 1: 
This causes the when_all_with_variant(sndrs...) sender to become when_all(into_variant(sndrs)...) when it is connected with a receiver whose execution domain does not customize when_all_with_variant.
— end note]

33.9.12.12 execution​::​into_variant [exec.into.variant]

into_variant adapts a sender with multiple value completion signatures into a sender with just one value completion signature consisting of a variant of tuples.
The name into_variant denotes a pipeable sender adaptor object.
For a subexpression sndr, let Sndr be decltype((sndr)).
If Sndr does not satisfy sender, into_variant(sndr) is ill-formed.
Otherwise, the expression into_variant(sndr) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(into_variant, {}, sndr)) except that sndr is only evaluated once.
The exposition-only class template impls-for ([exec.snd.general]) is specialized for into_variant as follows: namespace std::execution { template<> struct impls-for<into_variant_t> : default-impls { static constexpr auto get-state = see below; static constexpr auto complete = see below; }; }
The member impls-for<into_variant_t>​::​get-state is initialized with a callable object equivalent to the following lambda: []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> type_identity<value_types_of_t<child-type<Sndr>, env_of_t<Rcvr>>> { return {}; }
The member impls-for<into_variant_t>​::​complete is initialized with a callable object equivalent to the following lambda: []<class State, class Rcvr, class Tag, class... Args>( auto, State, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void { if constexpr (same_as<Tag, set_value_t>) { using variant_type = typename State::type; TRY-SET-VALUE(rcvr, variant_type(decayed-tuple<Args...>{std::forward<Args>(args)...})); } else { Tag()(std::move(rcvr), std::forward<Args>(args)...); } }

33.9.12.13 execution​::​stopped_as_optional [exec.stopped.opt]

stopped_as_optional maps a sender's stopped completion operation into a value completion operation as a disengaged optional.
The sender's value completion operation is also converted into an optional.
The result is a sender that never completes with stopped, reporting cancellation by completing with a disengaged optional.
The name stopped_as_optional denotes a pipeable sender adaptor object.
For a subexpression sndr, let Sndr be decltype((sndr)).
The expression stopped_as_optional(sndr) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(stopped_as_optional, {}, sndr)) except that sndr is only evaluated once.
Let sndr and env be subexpressions such that Sndr is decltype((sndr)) and Env is decltype((env)).
If sender-for<Sndr, stopped_as_optional_t> is false, or if the type single-sender-value-type<Sndr, Env> is ill-formed or void, then the expression stopped_as_optional.transform_sender(sndr, env) is ill-formed; otherwise, it is equivalent to: auto&& [_, _, child] = sndr; using V = single-sender-value-type<Sndr, Env>; return let_stopped( then(std::forward_like<Sndr>(child), []<class... Ts>(Ts&&... ts) noexcept(is_nothrow_constructible_v<V, Ts...>) { return optional<V>(in_place, std::forward<Ts>(ts)...); }), []() noexcept { return just(optional<V>()); });

33.9.12.14 execution​::​stopped_as_error [exec.stopped.err]

stopped_as_error maps an input sender's stopped completion operation into an error completion operation as a custom error type.
The result is a sender that never completes with stopped, reporting cancellation by completing with an error.
The name stopped_as_error denotes a pipeable sender adaptor object.
For some subexpressions sndr and err, let Sndr be decltype((sndr)) and let Err be decltype((err)).
If the type Sndr does not satisfy sender or if the type Err does not satisfy movable-value, stopped_as_error(sndr, err) is ill-formed.
Otherwise, the expression stopped_as_error(sndr, err) is expression-equivalent to: transform_sender(get-domain-early(sndr), make-sender(stopped_as_error, err, sndr)) except that sndr is only evaluated once.
Let sndr and env be subexpressions such that Sndr is decltype((sndr)) and Env is decltype((env)).
If sender-for<Sndr, stopped_as_error_t> is false, then the expression stopped_as_error.transform_sender(sndr, env) is ill-formed; otherwise, it is equivalent to: auto&& [_, err, child] = sndr; using E = decltype(auto(err)); return let_stopped( std::forward_like<Sndr>(child), [err = std::forward_like<Sndr>(err)]() mutable noexcept(is_nothrow_move_constructible_v<E>) { return just_error(std::move(err)); });

33.9.13 Sender consumers [exec.consumers]

33.9.13.1 this_thread​::​sync_wait [exec.sync.wait]

this_thread​::​sync_wait and this_thread​::​sync_wait_with_variant are used to block the current thread of execution until the specified sender completes and to return its async result.
sync_wait mandates that the input sender has exactly one value completion signature.
Let sync-wait-env be the following exposition-only class type: namespace std::this_thread { struct sync-wait-env { execution::run_loop* loop; // exposition only auto query(execution::get_scheduler_t) const noexcept { return loop->get_scheduler(); } auto query(execution::get_delegation_scheduler_t) const noexcept { return loop->get_scheduler(); } }; }
Let sync-wait-result-type and sync-wait-with-variant-result-type be exposition-only alias templates defined as follows: namespace std::this_thread { template<execution::sender_in<sync-wait-env> Sndr> using sync-wait-result-type = optional<execution::value_types_of_t<Sndr, sync-wait-env, decayed-tuple, type_identity_t>>; template<execution::sender_in<sync-wait-env> Sndr> using sync-wait-with-variant-result-type = optional<execution::value_types_of_t<Sndr, sync-wait-env>>; }
The name this_thread​::​sync_wait denotes a customization point object.
For a subexpression sndr, let Sndr be decltype((sndr)).
If sender_in<Sndr, sync-wait-env> is false, the expression this_thread​::​sync_wait(sndr) is ill-formed.
Otherwise, it is expression-equivalent to the following, except that sndr is evaluated only once: apply_sender(get-domain-early(sndr), sync_wait, sndr) Mandates:
  • The type sync-wait-result-type<Sndr> is well-formed.
  • same_as<decltype(e), sync-wait-result-type<Sndr>> is true, where e is the apply_sender expression above.
Let sync-wait-state and sync-wait-receiver be the following exposition-only class templates: namespace std::this_thread { template<class Sndr> struct sync-wait-state { // exposition only execution::run_loop loop; // exposition only exception_ptr error; // exposition only sync-wait-result-type<Sndr> result; // exposition only }; template<class Sndr> struct sync-wait-receiver { // exposition only using receiver_concept = execution::receiver_t; sync-wait-state<Sndr>* state; // exposition only template<class... Args> void set_value(Args&&... args) && noexcept; template<class Error> void set_error(Error&& err) && noexcept; void set_stopped() && noexcept; sync-wait-env get_env() const noexcept { return {&state->loop}; } }; }
template<class... Args> void set_value(Args&&... args) && noexcept;
Effects: Equivalent to: try { state->result.emplace(std::forward<Args>(args)...); } catch (...) { state->error = current_exception(); } state->loop.finish();
template<class Error> void set_error(Error&& err) && noexcept;
Effects: Equivalent to: state->error = AS-EXCEPT-PTR(std::forward<Error>(err)); // see [exec.general] state->loop.finish();
void set_stopped() && noexcept;
Effects: Equivalent to state->loop.finish().
For a subexpression sndr, let Sndr be decltype((sndr)).
If sender_to<Sndr, sync-wait-receiver<Sndr>> is false, the expression sync_wait.apply_sender(sndr) is ill-formed; otherwise, it is equivalent to: sync-wait-state<Sndr> state; auto op = connect(sndr, sync-wait-receiver<Sndr>{&state}); start(op); state.loop.run(); if (state.error) { rethrow_exception(std::move(state.error)); } return std::move(state.result);
The behavior of this_thread​::​sync_wait(sndr) is undefined unless:
  • It blocks the current thread of execution ([defns.block]) with forward progress guarantee delegation ([intro.progress]) until the specified sender completes.
    [Note 1: 
    The default implementation of sync_wait achieves forward progress guarantee delegation by providing a run_loop scheduler via the get_delegation_scheduler query on the sync-wait-receiver's environment.
    The run_loop is driven by the current thread of execution.
    — end note]
  • It returns the specified sender's async results as follows:
    • For a value completion, the result datums are returned in a tuple in an engaged optional object.
    • For an error completion, an exception is thrown.
    • For a stopped completion, a disengaged optional object is returned.

33.9.13.2 this_thread​::​sync_wait_with_variant [exec.sync.wait.var]

The name this_thread​::​sync_wait_with_variant denotes a customization point object.
For a subexpression sndr, let Sndr be decltype(into_variant(sndr)).
If sender_in<Sndr, sync-wait-env> is false, this_thread​::​sync_wait_with_variant(sndr) is ill-formed.
Otherwise, it is expression-equivalent to the following, except sndr is evaluated only once: apply_sender(get-domain-early(sndr), sync_wait_with_variant, sndr) Mandates:
  • The type sync-wait-with-variant-result-type<Sndr> is well-formed.
  • same_as<decltype(e), sync-wait-with-variant-result-type<Sndr>> is true, where e is the apply_sender expression above.
If callable<sync_wait_t, Sndr> is false, the expression sync_wait_with_variant.apply_sender(sndr) is ill-formed.
Otherwise, it is equivalent to: using result_type = sync-wait-with-variant-result-type<Sndr>; if (auto opt_value = sync_wait(into_variant(sndr))) { return result_type(std::move(get<0>(*opt_value))); } return result_type(nullopt);
The behavior of this_thread​::​sync_wait_with_variant(sndr) is undefined unless:
  • It blocks the current thread of execution ([defns.block]) with forward progress guarantee delegation ([intro.progress]) until the specified sender completes.
    [Note 1: 
    The default implementation of sync_wait_with_variant achieves forward progress guarantee delegation by relying on the forward progress guarantee delegation provided by sync_wait.
    — end note]
  • It returns the specified sender's async results as follows:
    • For a value completion, the result datums are returned in an engaged optional object that contains a variant of tuples.
    • For an error completion, an exception is thrown.
    • For a stopped completion, a disengaged optional object is returned.

33.10 Sender/receiver utilities [exec.util]

33.10.1 execution​::​completion_signatures [exec.util.cmplsig]

completion_signatures is a type that encodes a set of completion signatures ([exec.async.ops]).
[Example 1: struct my_sender { using sender_concept = sender_t; using completion_signatures = execution::completion_signatures< set_value_t(), set_value_t(int, float), set_error_t(exception_ptr), set_error_t(error_code), set_stopped_t()>; };
Declares my_sender to be a sender that can complete by calling one of the following for a receiver expression rcvr:
  • set_value(rcvr)
  • set_value(rcvr, int{...}, float{...})
  • set_error(rcvr, exception_ptr{...})
  • set_error(rcvr, error_code{...})
  • set_stopped(rcvr)
— end example]
This subclause makes use of the following exposition-only entities: template<class Fn> concept completion-signature = see below;
A type Fn satisfies completion-signature if and only if it is a function type with one of the following forms:
  • set_value_t(Vs...), where Vs is a pack of object or reference types.
  • set_error_t(Err), where Err is an object or reference type.
  • set_stopped_t()
template<bool> struct indirect-meta-apply { template<template<class...> class T, class... As> using meta-apply = T<As...>; // exposition only }; template<class...> concept always-true = true; // exposition only template<class Tag, valid-completion-signatures Completions, template<class...> class Tuple, template<class...> class Variant> using gather-signatures = see below;
Let Fns be a pack of the arguments of the completion_signatures specialization named by Completions, let TagFns be a pack of the function types in Fns whose return types are Tag, and let be a pack of the function argument types in the n-th type in TagFns.
Then, given two variadic templates Tuple and Variant, the type gather-signatures<Tag, Completions, Tuple, Variant> names the type META-APPLY(Variant, META-APPLY(Tuple, Ts...), META-APPLY(Tuple, Ts...), …, META-APPLY(Tuple, Ts...)) where m is the size of the pack TagFns and META-APPLY(T, As...) is equivalent to: typename indirect-meta-apply<always-true<As...>>::template meta-apply<T, As...>
[Note 1: 
The purpose of META-APPLY is to make it valid to use non-variadic templates as Variant and Tuple arguments to gather-signatures.
— end note]
namespace std::execution { template<completion-signature... Fns> struct completion_signatures {}; template<class Sndr, class Env = env<>, template<class...> class Tuple = decayed-tuple, template<class...> class Variant = variant-or-empty> requires sender_in<Sndr, Env> using value_types_of_t = gather-signatures<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>; template<class Sndr, class Env = env<>, template<class...> class Variant = variant-or-empty> requires sender_in<Sndr, Env> using error_types_of_t = gather-signatures<set_error_t, completion_signatures_of_t<Sndr, Env>, type_identity_t, Variant>; template<class Sndr, class Env = env<>> requires sender_in<Sndr, Env> constexpr bool sends_stopped = !same_as<type-list<>, gather-signatures<set_stopped_t, completion_signatures_of_t<Sndr, Env>, type-list, type-list>>; }

33.10.2 execution​::​transform_completion_signatures [exec.util.cmplsig.trans]

transform_completion_signatures is an alias template used to transform one set of completion signatures into another.
It takes a set of completion signatures and several other template arguments that apply modifications to each completion signature in the set to generate a new specialization of completion_signatures.
[Example 1: 
Given a sender Sndr and an environment Env, adapt the completion signatures of Sndr by lvalue-ref qualifying the values, adding an additional exception_ptr error completion if it is not already there, and leaving the other completion signatures alone.
template<class... Args> using my_set_value_t = completion_signatures< set_value_t(add_lvalue_reference_t<Args>...)>; using my_completion_signatures = transform_completion_signatures< completion_signatures_of_t<Sndr, Env>, completion_signatures<set_error_t(exception_ptr)>, my_set_value_t>; — end example]
This subclause makes use of the following exposition-only entities: template<class... As> using default-set-value = completion_signatures<set_value_t(As...)>; template<class Err> using default-set-error = completion_signatures<set_error_t(Err)>;
namespace std::execution { template<valid-completion-signatures InputSignatures, valid-completion-signatures AdditionalSignatures = completion_signatures<>, template<class...> class SetValue = default-set-value, template<class> class SetError = default-set-error, valid-completion-signatures SetStopped = completion_signatures<set_stopped_t()>> using transform_completion_signatures = completion_signatures<see below>; }
SetValue shall name an alias template such that for any pack of types As, the type SetValue<As...> is either ill-formed or else valid-completion-signatures<SetValue<As...>> is satisfied.
SetError shall name an alias template such that for any type Err, SetError<Err> is either ill-formed or else valid-completion-signatures<SetError<Err>> is satisfied.
Let Vs be a pack of the types in the type-list named by gather-signatures<set_value_t, InputSignatures, SetValue, type-list>.
Let Es be a pack of the types in the type-list named by gather-signatures<set_error_t, InputSignatures, type_identity_t, error-list>, where error-list is an alias template such that error-list<Ts...> is type-list<SetError<Ts>...>.
Let Ss name the type completion_signatures<> if gather-signatures<set_stopped_t, InputSignatures, type-list, type-list> is an alias for the type type-list<>; otherwise, SetStopped.
If any of the above types are ill-formed, then transform_completion_signatures<InputSignatures, AdditionalSignatures, SetValue, SetError, SetStopped> is ill-formed.
Otherwise, transform_completion_signatures<InputSignatures, AdditionalSignatures, SetValue, SetError, SetStopped> is the type completion_signatures<Sigs...> where Sigs... is the unique set of types in all the template arguments of all the completion_signatures specializations in the set AdditionalSignatures, Vs..., Es..., Ss.

33.11 Queryable utilities [exec.envs]

33.11.1 Class template prop [exec.prop]

namespace std::execution { template<class QueryTag, class ValueType> struct prop { QueryTag query_; // exposition only ValueType value_; // exposition only constexpr const ValueType& query(QueryTag) const noexcept { return value_; } }; template<class QueryTag, class ValueType> prop(QueryTag, ValueType) -> prop<QueryTag, unwrap_reference_t<ValueType>>; }
Class template prop is for building a queryable object from a query object and a value.
Mandates: callable<QueryTag, prop-like<ValueType>> is modeled, where prop-like is the following exposition-only class template: template<class ValueType> struct prop-like { // exposition only const ValueType& query(auto) const noexcept; };
[Example 1: template<sender Sndr> sender auto parameterize_work(Sndr sndr) { // Make an environment such that get_allocator(env) returns a reference to a copy of my_alloc{}. auto e = prop(get_allocator, my_alloc{}); // Parameterize the input sender so that it will use our custom execution environment. return write_env(sndr, e); } — end example]
Specializations of prop are not assignable.

33.11.2 Class template env [exec.env]

namespace std::execution { template<queryable... Envs> struct env { Envs ; // exposition only Envs ; // exposition only ⋮ Envs ; // exposition only template<class QueryTag> constexpr decltype(auto) query(QueryTag q) const noexcept(see below); }; template<class... Envs> env(Envs...) -> env<unwrap_reference_t<Envs>...>; }
The class template env is used to construct a queryable object from several queryable objects.
Query invocations on the resulting object are resolved by attempting to query each subobject in lexical order.
Specializations of env are not assignable.
It is unspecified whether env supports initialization using a parenthesized expression-list ([dcl.init]), unless the expression-list consist of a single element of type (possibly const) env.
[Example 1: template<sender Sndr> sender auto parameterize_work(Sndr sndr) { // Make an environment such that: // get_allocator(env) returns a reference to a copy of my_alloc{} // get_scheduler(env) returns a reference to a copy of my_sched{} auto e = env{prop(get_allocator, my_alloc{}), prop(get_scheduler, my_sched{})}; // Parameterize the input sender so that it will use our custom execution environment. return write_env(sndr, e); } — end example]
template<class QueryTag> constexpr decltype(auto) query(QueryTag q) const noexcept(see below);
Let has-query be the following exposition-only concept: template<class Env, class QueryTag> concept has-query = // exposition only requires (const Env& env) { env.query(QueryTag()); };
Let fe be the first element of , , , such that the expression fe.query(q) is well-formed.
Constraints: (has-query<Envs, QueryTag> || ...) is true.
Effects: Equivalent to: return fe.query(q);
Remarks: The expression in the noexcept clause is equivalent to noexcept(fe.query(q)).

33.12 Execution contexts [exec.ctx]

33.12.1 execution​::​run_loop [exec.run.loop]

33.12.1.1 General [exec.run.loop.general]

A run_loop is an execution resource on which work can be scheduled.
It maintains a thread-safe first-in-first-out queue of work.
Its run member function removes elements from the queue and executes them in a loop on the thread of execution that calls run.
A run_loop instance has an associated count that corresponds to the number of work items that are in its queue.
Additionally, a run_loop instance has an associated state that can be one of starting, running, finishing, or finished.
Concurrent invocations of the member functions of run_loop other than run and its destructor do not introduce data races.
The member functions pop-front, push-back, and finish execute atomically.
Recommended practice: Implementations should use an intrusive queue of operation states to hold the work units to make scheduling allocation-free.
namespace std::execution { class run_loop { // [exec.run.loop.types], associated types class run-loop-scheduler; // exposition only class run-loop-sender; // exposition only struct run-loop-opstate-base { // exposition only virtual void execute() = 0; // exposition only run_loop* loop; // exposition only run-loop-opstate-base* next; // exposition only }; template<class Rcvr> using run-loop-opstate = unspecified; // exposition only // [exec.run.loop.members], member functions run-loop-opstate-base* pop-front(); // exposition only void push-back(run-loop-opstate-base*); // exposition only public: // [exec.run.loop.ctor], constructor and destructor run_loop() noexcept; run_loop(run_loop&&) = delete; ~run_loop(); // [exec.run.loop.members], member functions run-loop-scheduler get_scheduler(); void run(); void finish(); }; }

33.12.1.2 Associated types [exec.run.loop.types]

class run-loop-scheduler;
run-loop-scheduler is an unspecified type that models scheduler.
Instances of run-loop-scheduler remain valid until the end of the lifetime of the run_loop instance from which they were obtained.
Two instances of run-loop-scheduler compare equal if and only if they were obtained from the same run_loop instance.
Let sch be an expression of type run-loop-scheduler.
The expression schedule(sch) has type run-loop-
sender
and is not potentially-throwing if sch is not potentially-throwing.
class run-loop-sender;
run-loop-sender is an exposition-only type that satisfies sender.
For any type Env, completion_signatures_of_t<run-loop-sender, Env> is completion_signatures<set_value_t(), set_error_t(exception_ptr), set_stopped_t()>
An instance of run-loop-sender remains valid until the end of the lifetime of its associated run_loop instance.
Let sndr be an expression of type run-loop-sender, let rcvr be an expression such that receiver_of<decltype((rcvr)), CS> is true where CS is the completion_signatures specialization above.
Let C be either set_value_t or set_stopped_t.
Then:
  • The expression connect(sndr, rcvr) has type run-loop-opstate<decay_t<decltype((rcvr))>> and is potentially-throwing if and only if (void(sndr), auto(rcvr)) is potentially-throwing.
  • The expression get_completion_scheduler<C>(get_env(sndr)) is potentially-throwing if and only if sndr is potentially-throwing, has type run-loop-scheduler, and compares equal to the run-loop-
    scheduler
    instance from which sndr was obtained.
template<class Rcvr> struct run-loop-opstate;
run-loop-opstate<Rcvr> inherits privately and unambiguously from run-loop-opstate-base.
Let o be a non-const lvalue of type run-loop-opstate<Rcvr>, and let REC(o) be a non-const lvalue reference to an instance of type Rcvr that was initialized with the expression rcvr passed to the invocation of connect that returned o.
Then:
  • The object to which REC(o) refers remains valid for the lifetime of the object to which o refers.
  • The type run-loop-opstate<Rcvr> overrides run-loop-opstate-base​::​execute() such that o.execute() is equivalent to: if (get_stop_token(REC(o)).stop_requested()) { set_stopped(std::move(REC(o))); } else { set_value(std::move(REC(o))); }
  • The expression start(o) is equivalent to: try { o.loop->push-back(addressof(o)); } catch(...) { set_error(std::move(REC(o)), current_exception()); }

33.12.1.3 Constructor and destructor [exec.run.loop.ctor]

run_loop() noexcept;
Postconditions: count is 0 and state is starting.
~run_loop();
Effects: If count is not 0 or if state is running, invokes terminate ([except.terminate]).
Otherwise, has no effects.

33.12.1.4 Member functions [exec.run.loop.members]

run-loop-opstate-base* pop-front();
Effects: Blocks ([defns.block]) until one of the following conditions is true:
  • count is 0 and state is finishing, in which case pop-front sets state to finished and returns nullptr; or
  • count is greater than 0, in which case an item is removed from the front of the queue, count is decremented by 1, and the removed item is returned.
void push-back(run-loop-opstate-base* item);
Effects: Adds item to the back of the queue and increments count by 1.
Synchronization: This operation synchronizes with the pop-front operation that obtains item.
run-loop-scheduler get_scheduler();
Returns: An instance of run-loop-scheduler that can be used to schedule work onto this run_loop instance.
void run();
Preconditions: state is either starting or finishing.
Effects: If state is starting, sets the state to running, otherwise leaves state unchanged.
Then, equivalent to: while (auto* op = pop-front()) { op->execute(); }
Remarks: When state changes, it does so without introducing data races.
void finish();
Preconditions: state is either starting or running.
Effects: Changes state to finishing.
Synchronization: finish synchronizes with the pop-front operation that returns nullptr.

33.13 Coroutine utilities [exec.coro.util]

33.13.1 execution​::​as_awaitable [exec.as.awaitable]

as_awaitable transforms an object into one that is awaitable within a particular coroutine.
Subclause [exec.coro.util] makes use of the following exposition-only entities: namespace std::execution { template<class Sndr, class Promise> concept awaitable-sender = single-sender<Sndr, env_of_t<Promise>> && sender_to<Sndr, awaitable-receiver> && // see below requires (Promise& p) { { p.unhandled_stopped() } -> convertible_to<coroutine_handle<>>; }; template<class Sndr, class Promise> class sender-awaitable; // exposition only }
The type sender-awaitable<Sndr, Promise> is equivalent to:
namespace std::execution { template<class Sndr, class Promise> class sender-awaitable { struct unit {}; // exposition only using value-type = // exposition only single-sender-value-type<Sndr, env_of_t<Promise>>; using result-type = // exposition only conditional_t<is_void_v<value-type>, unit, value-type>; struct awaitable-receiver; // exposition only variant<monostate, result-type, exception_ptr> result{}; // exposition only connect_result_t<Sndr, awaitable-receiver> state; // exposition only public: sender-awaitable(Sndr&& sndr, Promise& p); static constexpr bool await_ready() noexcept { return false; } void await_suspend(coroutine_handle<Promise>) noexcept { start(state); } value-type await_resume(); }; }
awaitable-receiver is equivalent to: struct awaitable-receiver { using receiver_concept = receiver_t; variant<monostate, result-type, exception_ptr>* result-ptr; // exposition only coroutine_handle<Promise> continuation; // exposition only // see below };
Let rcvr be an rvalue expression of type awaitable-receiver, let crcvr be a const lvalue that refers to rcvr, let vs be a pack of subexpressions, and let err be an expression of type Err.
Then:
  • If constructible_from<result-type, decltype((vs))...> is satisfied, the expression set_value(
    rcvr, vs...)
    is equivalent to: try { rcvr.result-ptr->template emplace<1>(vs...); } catch(...) { rcvr.result-ptr->template emplace<2>(current_exception()); } rcvr.continuation.resume();
    Otherwise, set_value(rcvr, vs...) is ill-formed.
  • The expression set_error(rcvr, err) is equivalent to: rcvr.result-ptr->template emplace<2>(AS-EXCEPT-PTR(err)); // see [exec.general] rcvr.continuation.resume();
  • The expression set_stopped(rcvr) is equivalent to: static_cast<coroutine_handle<>>(rcvr.continuation.promise().unhandled_stopped()).resume();
  • For any expression tag whose type satisfies forwarding-query and for any pack of subexpressions as, get_env(crcvr).query(tag, as...) is expression-equivalent to: tag(get_env(as_const(crcvr.continuation.promise())), as...)
sender-awaitable(Sndr&& sndr, Promise& p);
Effects: Initializes state with connect(std::forward<Sndr>(sndr), awaitable-receiver{addressof(result), coroutine_handle<Promise>::from_promise(p)})
value-type await_resume();
Effects: Equivalent to: if (result.index() == 2) rethrow_exception(get<2>(result)); if constexpr (!is_void_v<value-type>) return std::forward<value-type>(get<1>(result));
as_awaitable is a customization point object.
For subexpressions expr and p where p is an lvalue, Expr names the type decltype((expr)) and Promise names the type decay_t<decltype((p))>, as_awaitable(expr, p) is expression-equivalent to, except that the evaluations of expr and p are indeterminately sequenced:
  • expr.as_awaitable(p) if that expression is well-formed.
    Mandates: is-awaitable<A, Promise> is true, where A is the type of the expression above.
  • Otherwise, (void(p), expr) if is-awaitable<Expr, U> is true, where U is an unspecified class type that is not Promise and that lacks a member named await_transform.
    Preconditions: is-awaitable<Expr, Promise> is true and the expression co_await expr in a coroutine with promise type U is expression-equivalent to the same expression in a coroutine with promise type Promise.
  • Otherwise, sender-awaitable{expr, p} if awaitable-sender<Expr, Promise> is true.
  • Otherwise, (void(p), expr).

33.13.2 execution​::​with_awaitable_senders [exec.with.awaitable.senders]

with_awaitable_senders, when used as the base class of a coroutine promise type, makes senders awaitable in that coroutine type.
In addition, it provides a default implementation of unhandled_stopped such that if a sender completes by calling set_stopped, it is treated as if an uncatchable "stopped" exception were thrown from the await-expression.
[Note 1: 
The coroutine is never resumed, and the unhandled_stopped of the coroutine caller's promise type is called.
— end note]
namespace std::execution { template<class-type Promise> struct with_awaitable_senders { template<class OtherPromise> requires (!same_as<OtherPromise, void>) void set_continuation(coroutine_handle<OtherPromise> h) noexcept; coroutine_handle<> continuation() const noexcept { return continuation; } coroutine_handle<> unhandled_stopped() noexcept { return stopped-handler(continuation.address()); } template<class Value> see below await_transform(Value&& value); private: [[noreturn]] static coroutine_handle<> default-unhandled-stopped(void*) noexcept { // exposition only terminate(); } coroutine_handle<> continuation{}; // exposition only coroutine_handle<> (*stopped-handler)(void*) noexcept = // exposition only &default-unhandled-stopped; }; }
template<class OtherPromise> requires (!same_as<OtherPromise, void>) void set_continuation(coroutine_handle<OtherPromise> h) noexcept;
Effects: Equivalent to: continuation = h; if constexpr ( requires(OtherPromise& other) { other.unhandled_stopped(); } ) { stopped-handler = [](void* p) noexcept -> coroutine_handle<> { return coroutine_handle<OtherPromise>::from_address(p) .promise().unhandled_stopped(); }; } else { stopped-handler = &default-unhandled-stopped; }
template<class Value> call-result-t<as_awaitable_t, Value, Promise&> await_transform(Value&& value);
Effects: Equivalent to: return as_awaitable(std::forward<Value>(value), static_cast<Promise&>(*this));

Annex A (informative) Grammar summary [gram]

A.1 General [gram.general]

This summary of C++ grammar is intended to be an aid to comprehension.
It is not an exact statement of the language.
In particular, the grammar described here accepts a superset of valid C++ constructs.
Disambiguation rules ([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.

A.3 Lexical conventions [gram.lex]

n-char:
any member of the translation character set except the U+007d right curly bracket or new-line character
h-char:
any member of the translation character set except new-line and U+003e greater-than sign
q-char:
any member of the translation character set except new-line and U+0022 quotation mark
preprocessing-operator: one of
# ## %: %:%:
operator-or-punctuator: one of
{ } [ ] ( )
<: :> <% %> ; : ...
? :: . .* -> ->* ~
! + - * / % ^ & |
= += -= *= /= %= ^= &= |=
== != < > <= >= <=> && ||
<< >> <<= >>= ++ -- ,
and or xor not bitand bitor compl
and_eq or_eq xor_eq not_eq
identifier-start:
nondigit
an element of the translation character set with the Unicode property XID_Start
identifier-continue:
digit
nondigit
an element of the translation character set with the Unicode property XID_Continue
nondigit: one of
a b c d e f g h i j k l m
n o p q r s t u v w x y z
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z _
digit: one of
0 1 2 3 4 5 6 7 8 9
keyword:
any identifier listed in Table 5
import-keyword
module-keyword
export-keyword
binary-digit: one of
0 1
octal-digit: one of
0 1 2 3 4 5 6 7
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
hexadecimal-prefix: one of
0x 0X
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
unsigned-suffix: one of
u U
long-suffix: one of
l L
long-long-suffix: one of
ll LL
size-suffix: one of
z Z
encoding-prefix: one of
u8  u  U  L
basic-c-char:
any member of the translation character set except the U+0027 apostrophe,
   U+005c reverse solidus, or new-line character
simple-escape-sequence-char: one of
' " ? \ a b f n r t v
conditional-escape-sequence-char:
any member of the basic character set that is not an octal-digit, a simple-escape-sequence-char, or the characters N, o, u, U, or x
sign: one of
+ -
floating-point-suffix: one of
f l f16 f32 f64 f128 bf16 F L F16 F32 F64 F128 BF16
basic-s-char:
any member of the translation character set except the U+0022 quotation mark,
   U+005c reverse solidus, or new-line character
r-char:
any member of the translation character set, except a U+0029 right parenthesis followed by
   the initial d-char-sequence (which may be empty) followed by a U+0022 quotation mark
d-char-sequence:
d-chard-char-sequence
d-char:
any member of the basic character set except:
   U+0020 space, U+0028 left parenthesis, U+0029 right parenthesis, U+005c reverse solidus,
   U+0009 character tabulation, U+000b line tabulation, U+000c form feed, and new-line
boolean-literal:
false
true

A.5 Expressions [gram.expr]

lambda-specifier:
consteval
constexpr
mutable
static
simple-capture:
identifier ...
& identifier ...
this
* this
fold-operator: one of
+   -   *   /   %   ^   &   |   <<   >>
+=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=  =
==  !=  <   >   <=  >=  &&  ||  ,   .*   ->*
unary-operator: one of
* & + - ! ~
delete-expression:
:: delete cast-expression
:: delete [ ] cast-expression
assignment-operator: one of
= *= /= %= += -= >>= <<= &= ^= |=

A.6 Statements [gram.stmt]

selection-statement:
if constexpr ( init-statement condition ) statement
if constexpr ( init-statement condition ) statement else statement
if ! consteval compound-statement
if ! consteval compound-statement else statement
switch ( init-statement condition ) statement

A.7 Declarations [gram.dcl]

storage-class-specifier:
static
thread_local
extern
mutable
cv-qualifier:
const
volatile
deleted-function-body:
= delete ;
= delete ( unevaluated-string ) ;
enum-key:
enum
enum class
enum struct
alignment-specifier:
alignas ( type-id ... )
alignas ( constant-expression ... )
balanced-token:
( balanced-token-seq )
[ balanced-token-seq ]
{ balanced-token-seq }
any token other than a parenthesis, a bracket, or a brace

A.9 Classes [gram.class]

class-key:
class
struct
union
virt-specifier:
override
final
access-specifier:
private
protected
public

A.10 Overloading [gram.over]

operator: one of
new delete new[] delete[] co_await () [] -> ->*
~ ! + - * / % ^ &
| = += -= *= /= %= ^= &=
|= == != < > <= >= <=> &&
|| << >> <<= >>= ++ -- ,

A.11 Templates [gram.temp]

type-parameter-key:
class
typename

A.13 Preprocessing directives [gram.cpp]

lparen:
a ( character not immediately preceded by whitespace
new-line:
the new-line character
has-include-expression:
__has_include ( header-name )
__has_include ( header-name-tokens )
has-attribute-expression:
__has_cpp_attribute ( pp-tokens )
pp-module:
export module pp-tokens ; new-line
pp-import:
export import header-name pp-tokens ; new-line
export import header-name-tokens pp-tokens ; new-line
export import pp-tokens ; new-line
va-opt-replacement:
__VA_OPT__ ( pp-tokens )

Annex B (informative) Implementation quantities [implimits]

Implementations can exhibit limitations for various quantities; some possibilities are presented in the following list.
The bracketed number following each quantity is a potential minimum value for that quantity.

Annex C (informative) Compatibility [diff]

C.1 C++ and ISO C++ 2023 [diff.cpp23]

C.1.1 General [diff.cpp23.general]

Subclause [diff.cpp23] lists the differences between C++ and ISO C++ 2023, by the chapters of this document.

C.1.2 [expr]: expressions [diff.cpp23.expr]

Affected subclause: [expr.arith.conv]
Change: Operations mixing a value of an enumeration type and a value of a different enumeration type or of a floating-point type are no longer valid.

Rationale: Reinforcing type safety.

Effect on original feature: A valid C++ 2023 program that performs operations mixing a value of an enumeration type and a value of a different enumeration type or of a floating-point type is ill-formed.
[Example 1: enum E1 { e }; enum E2 { f }; bool b = e <= 3.7; // ill-formed; previously well-formed int k = f - e; // ill-formed; previously well-formed auto x = true ? e : f; // ill-formed; previously well-formed — end example]
Affected subclauses: [expr.rel] and [expr.eq]
Change: Comparing two objects of array type is no longer valid.

Rationale: The old behavior was confusing since it compared not the contents of the two arrays, but their addresses.

Effect on original feature: A valid C++ 2023 program directly comparing two array objects is rejected as ill-formed in this document.
[Example 2: int arr1[5]; int arr2[5]; bool same = arr1 == arr2; // ill-formed; previously well-formed bool idem = arr1 == +arr2; // compare addresses bool less = arr1 < +arr2; // compare addresses, unspecified result — end example]
Affected subclause: [expr.delete]
Change: Calling delete on a pointer to an incomplete class is ill-formed.

Rationale: Reduce undefined behavior.

Effect on original feature: A valid C++ 2023 program that calls delete on an incomplete class type is ill-formed.
[Example 3: struct S; void f(S *p) { delete p; // ill-formed; previously well-formed } struct S {}; — end example]

C.1.3 [dcl.dcl]: declarations [diff.cpp23.dcl.dcl]

Affected subclause: [dcl.init.list]
Change: Pointer comparisons between initializer_list objects' backing arrays are unspecified.

Rationale: Permit the implementation to store backing arrays in static read-only memory.

Effect on original feature: Valid C++ 2023 code that relies on the result of pointer comparison between backing arrays may change behavior.
[Example 1: bool ne(std::initializer_list<int> a, std::initializer_list<int> b) { return a.begin() != b.begin() + 1; } bool b = ne({2,3}, {1,2,3}); // unspecified result; previously false — end example]
Affected subclause: [dcl.array]
Change: Previously, T...[n] would declare a pack of function parameters.
T...[n] is now a pack-index-specifier.

Rationale: Improve the handling of packs.

Effect on original feature: Valid C++ 2023 code that declares a pack of parameters without specifying a declarator-id becomes ill-formed.
[Example 2: template <typename... T> void f(T... [1]); template <typename... T> void g(T... ptr[1]); int main() { f<int, double>(nullptr, nullptr); // ill-formed, previously void f<int, double>(int [1], double [1]) g<int, double>(nullptr, nullptr); // ok } — end example]

C.1.4 [temp]: templates [diff.cpp23.temp]

Affected subclause: [temp.constr]
Change: Some atomic constraints become fold expanded constraints.

Rationale: Permit the subsumption of fold expressions.

Effect on original feature: Valid C++ 2023 code may become ill-formed.
[Example 1: template <typename ...V> struct A; struct S { static constexpr int compare(const S&) { return 1; } }; template <typename ...T, typename ...U> void f(A<T ...> *, A<U ...> *) requires (T::compare(U{}) && ...); // was well-formed (atomic constraint of type bool), // now ill-formed (results in an atomic constraint of type int) void g(A<S, S> *ap) { f(ap, ap); } — end example]
Affected subclause: [temp.deduct.call]
Change: Template argument deduction from overload sets succeeds in more cases.

Rationale: Allow consideration of constraints to disambiguate overload sets used as parameters in function calls.

Effect on original feature: Valid C++ 2023 code may become ill-formed.
[Example 2: template <typename T> void f(T &&, void (*)(T &&)); void g(int &); // #1 inline namespace A { void g(short &&); // #2 } inline namespace B { void g(short &&); // #3 } void q() { int x; f(x, g); // ill-formed; previously well-formed, deducing T = int& }
There is no change to the applicable deduction rules for the individual g candidates: Type deduction from #1 does not succeed; type deductions from #2 and #3 both succeed.
— end example]

C.1.5 [library]: library introduction [diff.cpp23.library]

Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new: <debugging>, <hazard_pointer>, <inplace_vector>, <linalg>, <rcu>, <simd>, and <text_encoding>.
Valid C++ 2023 code that #includes headers with these names may be invalid in this revision of C++.

C.1.6 [strings]: strings library [diff.cpp23.strings]

Affected subclause: [string.conversions]
Change: Output of floating-point overloads of to_string and to_wstring.

Rationale: Prevent loss of information and improve consistency with other formatting facilities.

Effect on original feature: to_string and to_wstring function calls that take floating-point arguments may produce a different output.
[Example 1: auto s = std::to_string(1e-7); // "1e-07" // previously "0.000000" with '.' possibly // changed according to the global C locale — end example]

C.1.7 [containers]: containers library [diff.cpp23.containers]

Affected subclause: [span.overview]
Change: span<const T> is constructible from initializer_list<T>.

Rationale: Permit passing a braced initializer list to a function taking span.

Effect on original feature: Valid C++ 2023 code that relies on the lack of this constructor may refuse to compile, or change behavior in this revision of C++.
[Example 1: void one(pair<int, int>); // #1 void one(span<const int>); // #2 void t1() { one({1, 2}); } // ambiguous between #1 and #2; previously called #1 void two(span<const int, 2>); void t2() { two({{1, 2}}); } // ill-formed; previously well-formed void *a[10]; int x = span<void* const>{a, 0}.size(); // x is 2; previously 0 any b[10]; int y = span<const any>{b, b + 10}.size(); // y is 2; previously 10 — end example]

C.1.8 [depr]: compatibility features [diff.cpp23.depr]

Change: Remove the type alias allocator<T>​::​is_always_equal.

Rationale: Non-empty allocator classes derived from allocator needed to explicitly define an is_always_equal member type so that allocator_traits would not use the one from the allocator base class.

Effect on original feature: It is simpler to correctly define an allocator class with an allocator base class.
[Example 1: template <class T> struct MyAlloc : allocator<T> { int tag; }; static_assert(!allocator_traits<MyAlloc<int>>::is_always_equal); // Error in C++ 2023, // OK in C++ 2026 — end example]
Change: Removal of atomic access API for shared_ptr objects.

Rationale: The old behavior was brittle.
shared_ptr objects using the old API were not protected by the type system, and certain interactions with code not using this API would, in some cases, silently produce undefined behavior.
A complete type-safe replacement is provided in the form of atomic<shared_ptr<T>>.

Effect on original feature: A valid C++ 2023 program that relies on the presence of the removed functions may fail to compile.
Change: Remove the basic_string​::​reserve() overload with no parameters.

Rationale: The overload of reserve with no parameters is redundant.
The shrink_to_fit member function can be used instead.

Effect on original feature: A valid C++ 2023 program that calls reserve() on a basic_string object may fail to compile.
The old functionality can be achieved by calling shrink_to_fit() instead, or the function call can be safely eliminated with no side effects.
Change: Remove header <codecvt> and all its contents.

Rationale: The header has been deprecated for the previous three editions of this document and no longer implements the current Unicode standard, supporting only the obsolete UCS-2 encoding.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program #include-ing the header or importing the header unit may fail to compile.
Code that uses any of the following names by importing the standard library modules may fail to compile:
Change: Remove header <strstream> and all its contents.

Rationale: The header has been deprecated since the original C++ standard; the <spanstream> header provides an updated, safer facility.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program #include-ing the header or importing the header unit may become ill-formed.
Code that uses any of the following classes by importing one of the standard library modules may become ill-formed:
Change: Remove convenience interfaces wstring_convert and wbuffer_convert.

Rationale: These features were underspecified with no clear error reporting mechanism and were deprecated for the last three editions of this document.
Ongoing support is at implementer's discretion, exercising freedoms granted by [zombie.names].

Effect on original feature: A valid C++ 2023 program using these interfaces may become ill-formed.

C.2 C++ and ISO C++ 2020 [diff.cpp20]

C.2.1 General [diff.cpp20.general]

Subclause [diff.cpp20] lists the differences between C++ and ISO C++ 2020, in addition to those listed above, by the chapters of this document.

C.2.2 [lex]: lexical conventions [diff.cpp20.lex]

Affected subclause: [lex.name]
Change: Previously valid identifiers containing characters not present in UAX #44 properties XID_Start or XID_Continue, or not in Normalization Form C, are now rejected.

Rationale: Prevent confusing characters in identifiers.
Requiring normalization of names ensures consistent linker behavior.

Effect on original feature: Some identifiers are no longer well-formed.
Affected subclause: [lex.string]
Change: Concatenated string-literals can no longer have conflicting encoding-prefixes.

Rationale: Removal of unimplemented conditionally-supported feature.

Effect on original feature: Concatenation of string-literals with different encoding-prefixes is now ill-formed.
[Example 1: auto c = L"a" U"b"; // was conditionally-supported; now ill-formed — end example]

C.2.3 [expr]: expressions [diff.cpp20.expr]

Affected subclause: [expr.prim.id.unqual]
Change: Change move-eligible id-expressions from lvalues to xvalues.

Rationale: Simplify the rules for implicit move.

Effect on original feature: Valid C++ 2020 code that relies on a returned id-expression's being an lvalue may change behavior or fail to compile.
[Example 1: decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int& int& g(int&& x) { return x; } // ill-formed; previously well-formed — end example]
Affected subclause: [expr.sub]
Change: Change the meaning of comma in subscript expressions.

Rationale: Enable repurposing a deprecated syntax to support multidimensional indexing.

Effect on original feature: Valid C++ 2020 code that uses a comma expression within a subscript expression may fail to compile.
[Example 2: arr[1, 2] // was equivalent to arr[(1, 2)], // now equivalent to arr.operator[](1, 2) or ill-formed — end example]

C.2.4 [stmt.stmt]: statements [diff.cpp20.stmt]

Affected subclause: [stmt.ranged]
Change: The lifetime of temporary objects in the for-range-initializer is extended until the end of the loop ([class.temporary]).

Rationale: Improve usability of the range-based for statement.

Effect on original feature: Destructors of some temporary objects are invoked later.
[Example 1: void f() { std::vector<int> v = { 42, 17, 13 }; std::mutex m; for (int x : static_cast<void>(std::lock_guard<std::mutex>(m)), v) { // lock released in C++ 2020 std::lock_guard<std::mutex> guard(m); // OK in C++ 2020, now deadlocks } } — end example]

C.2.5 [dcl.dcl]: declarations [diff.cpp20.dcl]

Affected subclause: [dcl.init.string]
Change: UTF-8 string literals may initialize arrays of char or unsigned char.

Rationale: Compatibility with previously written code that conformed to previous versions of this document.

Effect on original feature: Arrays of char or unsigned char may now be initialized with a UTF-8 string literal.
This can affect initialization that includes arrays that are directly initialized within class types, typically aggregates.
[Example 1: struct A { char8_t s[10]; }; struct B { char s[10]; }; void f(A); void f(B); int main() { f({u8""}); // ambiguous } — end example]

C.2.6 [temp]: templates [diff.cpp20.temp]

Affected subclause: [temp.deduct.type]
Change: Deducing template arguments from exception specifications.

Rationale: Facilitate generic handling of throwing and non-throwing functions.

Effect on original feature: Valid ISO C++ 2020 code may be ill-formed in this revision of C++.
[Example 1: template<bool> struct A { }; template<bool B> void f(void (*)(A<B>) noexcept(B)); void g(A<false>) noexcept; void h() { f(g); // ill-formed; previously well-formed } — end example]

C.2.7 [library]: library introduction [diff.cpp20.library]

Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new: <expected>, <flat_map>, <flat_set>, <generator>, <mdspan>, <print>, <spanstream>, <stacktrace>, <stdatomic.h>, and <stdfloat>.
Valid C++ 2020 code that #includes headers with these names may be invalid in this revision of C++.

C.2.8 [concepts]: concepts library [diff.cpp20.concepts]

Affected subclauses: [cmp.concept], [concept.equalitycomparable], and [concept.totallyordered]
Change: Replace common_reference_with in three_way_comparable_with, equality_comparable_with, and totally_ordered_with with an exposition-only concept.

Rationale: Allow uncopyable, but movable, types to model these concepts.

Effect on original feature: Valid C++ 2020 code relying on subsumption with common_reference_with may fail to compile in this revision of C++.
[Example 1: template<class T, class U> requires equality_comparable_with<T, U> bool attempted_equals(const T&, const U& u); // previously selected overload template<class T, class U> requires common_reference_with<const remove_reference_t<T>&, const remove_reference_t<U>&> bool attempted_equals(const T& t, const U& u); // ambiguous overload; previously // rejected by partial ordering bool test(shared_ptr<int> p) { return attempted_equals(p, nullptr); // ill-formed; previously well-formed } — end example]

C.2.9 [mem]: memory management library [diff.cpp20.memory]

Affected subclause: [allocator.traits.general]
Change: Forbid partial and explicit program-defined specializations of allocator_traits.

Rationale: Allow addition of allocate_at_least to allocator_traits, and potentially other members in the future.

Effect on original feature: Valid C++ 2020 code that partially or explicitly specializes allocator_traits is ill-formed with no diagnostic required in this revision of C++.

C.2.10 [utilities]: general utilities library [diff.cpp20.utilities]

Affected subclause: [format]
Change: Signature changes: format, format_to, vformat_to, format_to_n, formatted_size.
Removal of format_args_t.

Rationale: Improve safety via compile-time format string checks, avoid unnecessary template instantiations.

Effect on original feature: Valid C++ 2020 code that contained errors in format strings or relied on previous format string signatures or format_args_t may become ill-formed.
[Example 1: auto s = std::format("{:d}", "I am not a number"); // ill-formed, // previously threw format_error — end example]
Affected subclause: [format]
Change: Signature changes: format, format_to, format_to_n, formatted_size.

Rationale: Enable formatting of views that do not support iteration when const-qualified and that are not copyable.

Effect on original feature: Valid C++ 2020 code that passes bit-fields to formatting functions may become ill-formed.
[Example 2: struct tiny { int bit: 1; }; auto t = tiny(); std::format("{}", t.bit); // ill-formed, previously returned "0" — end example]
Affected subclause: [format.string.std]
Change: Restrict types of formatting arguments used as width or precision in a std-format-spec.

Rationale: Disallow types that do not have useful or portable semantics as a formatting width or precision.

Effect on original feature: Valid C++ 2020 code that passes a boolean or character type as arg-id becomes invalid.
[Example 3: std::format("{:*^{}}", "", true); // ill-formed, previously returned "*" std::format("{:*^{}}", "", '1'); // ill-formed, previously returned an // implementation-defined number of '*' characters — end example]
Affected subclause: [format.formatter.spec]
Change: Removed the formatter specialization: template<size_t N> struct formatter<const charT[N], charT>;
Rationale: The specialization is inconsistent with the design of formatter, which is intended to be instantiated only with cv-unqualified object types.

Effect on original feature: Valid C++ 2020 code that instantiated the removed specialization can become ill-formed.

C.2.11 [strings]: strings library [diff.cpp20.strings]

Affected subclause: [string.classes]
Change: Additional rvalue overload for the substr member function and the corresponding constructor.

Rationale: Improve efficiency of operations on rvalues.

Effect on original feature: Valid C++ 2020 code that created a substring by calling substr (or the corresponding constructor) on an xvalue expression with type S that is a specialization of basic_string may change meaning in this revision of C++.
[Example 1: std::string s1 = "some long string that forces allocation", s2 = s1; std::move(s1).substr(10, 5); assert(s1 == s2); // unspecified, previously guaranteed to be true std::string s3(std::move(s2), 10, 5); assert(s1 == s2); // unspecified, previously guaranteed to be true — end example]

C.2.12 [containers]: containers library [diff.cpp20.containers]

Affected subclauses: [associative.reqmts] and [unord.req]
Change: Heterogeneous extract and erase overloads for associative containers.

Rationale: Improve efficiency of erasing elements from associative containers.

Effect on original feature: Valid C++ 2020 code may fail to compile in this revision of C++.
[Example 1: struct B { auto operator<=>(const B&) const = default; }; struct D : private B { void f(std::set<B, std::less<>>& s) { s.erase(*this); // ill-formed; previously well-formed } }; — end example]

C.2.13 [thread]: concurrency support library [diff.cpp20.thread]

Affected subclause: [thread.barrier]
Change: In this revision of C++, it is implementation-defined whether a barrier's phase completion step runs if no thread calls wait.
Previously the phase completion step was guaranteed to run on the last thread that calls arrive or arrive_and_drop during the phase.
In this revision of C++, it can run on any of the threads that arrived or waited at the barrier during the phase.

Rationale: Correct contradictory wording and improve implementation flexibility for performance.

Effect on original feature: Valid C++ 2020 code using a barrier might have different semantics in this revision of C++ if it depends on a completion function's side effects occurring exactly once, on a specific thread running the phase completion step, or on a completion function's side effects occurring without wait having been called.
[Example 1: auto b0 = std::barrier(1); b0.arrive(); b0.arrive(); // implementation-defined; previously well-defined int data = 0; auto b1 = std::barrier(1, [&] { data++; }); b1.arrive(); assert(data == 1); // implementation-defined; previously well-defined b1.arrive(); // implementation-defined; previously well-defined — end example]

C.3 C++ and ISO C++ 2017 [diff.cpp17]

C.3.1 General [diff.cpp17.general]

Subclause [diff.cpp17] lists the differences between C++ and ISO C++ 2017, in addition to those listed above, by the chapters of this document.

C.3.2 [lex]: lexical conventions [diff.cpp17.lex]

Affected subclauses: [lex.pptoken], [module.unit], [module.import], [cpp.pre], [cpp.module], and [cpp.import]
Change: New identifiers with special meaning.

Rationale: Required for new features.

Effect on original feature: Logical lines beginning with module or import may be interpreted differently in this revision of C++.
[Example 1: class module {}; module m1; // was variable declaration; now module-declaration module *m2; // variable declaration class import {}; import j1; // was variable declaration; now module-import-declaration ::import j2; // variable declaration — end example]
Affected subclause: [lex.header]
Change: header-name tokens are formed in more contexts.

Rationale: Required for new features.

Effect on original feature: When the identifier import is followed by a < character, a header-name token may be formed.
[Example 2: template<typename> class import {}; import<int> f(); // ill-formed; previously well-formed ::import<int> g(); // OK — end example]
Affected subclause: [lex.key]
Change: New keywords.

Rationale: Required for new features.
Effect on original feature: Valid C++ 2017 code using char8_t, concept, consteval, constinit, co_await, co_yield, co_return, or requires as an identifier is not valid in this revision of C++.
Affected subclause: [lex.operators]
Change: New operator <=>.

Rationale: Necessary for new functionality.

Effect on original feature: Valid C++ 2017 code that contains a <= token immediately followed by a > token may be ill-formed or have different semantics in this revision of C++.
[Example 3: namespace N { struct X {}; bool operator<=(X, X); template<bool(X, X)> struct Y {}; Y<operator<=> y; // ill-formed; previously well-formed } — end example]
Affected subclause: [lex.literal]
Change: Type of UTF-8 string and character literals.

Rationale: Required for new features.
The changed types enable function overloading, template specialization, and type deduction to distinguish ordinary and UTF-8 string and character literals.

Effect on original feature: Valid C++ 2017 code that depends on UTF-8 string literals having type “array of const char” and UTF-8 character literals having type “char” is not valid in this revision of C++.
[Example 4: const auto *u8s = u8"text"; // u8s previously deduced as const char*; now deduced as const char8_t* const char *ps = u8s; // ill-formed; previously well-formed auto u8c = u8'c'; // u8c previously deduced as char; now deduced as char8_t char *pc = &u8c; // ill-formed; previously well-formed std::string s = u8"text"; // ill-formed; previously well-formed void f(const char *s); f(u8"text"); // ill-formed; previously well-formed template<typename> struct ct; template<> struct ct<char> { using type = char; }; ct<decltype(u8'c')>::type x; // ill-formed; previously well-formed. — end example]

C.3.3 [basic]: basics [diff.cpp17.basic]

Affected subclause: [basic.life]
Change: A pseudo-destructor call ends the lifetime of the object to which it is applied.

Rationale: Increase consistency of the language model.

Effect on original feature: Valid ISO C++ 2017 code may be ill-formed or have undefined behavior in this revision of C++.
[Example 1: int f() { int a = 123; using T = int; a.~T(); return a; // undefined behavior; previously returned 123 } — end example]
Affected subclause: [intro.races]
Change: Except for the initial release operation, a release sequence consists solely of atomic read-modify-write operations.

Rationale: Removal of rarely used and confusing feature.

Effect on original feature: If a memory_order_release atomic store is followed by a memory_order_relaxed store to the same variable by the same thread, then reading the latter value with a memory_order_acquire load no longer provides any “happens before” guarantees, even in the absence of intervening stores by another thread.

C.3.4 [expr]: expressions [diff.cpp17.expr]

Affected subclause: [expr.prim.lambda.capture]
Change: Implicit lambda capture may capture additional entities.

Rationale: Rule simplification, necessary to resolve interactions with constexpr if.

Effect on original feature: Lambdas with a capture-default may capture local entities that were not captured in C++ 2017 if those entities are only referenced in contexts that do not result in an odr-use.

C.3.5 [dcl.dcl]: declarations [diff.cpp17.dcl.dcl]

Affected subclause: [dcl.typedef]
Change: Unnamed classes with a typedef name for linkage purposes can contain only C-compatible constructs.

Rationale: Necessary for implementability.

Effect on original feature: Valid C++ 2017 code may be ill-formed in this revision of C++.
[Example 1: typedef struct { void f() {} // ill-formed; previously well-formed } S; — end example]
Affected subclause: [dcl.fct.default]
Change: A function cannot have different default arguments in different translation units.

Rationale: Required for modules support.

Effect on original feature: Valid C++ 2017 code may be ill-formed in this revision of C++, with no diagnostic required.
[Example 2: // Translation unit 1 int f(int a = 42); int g() { return f(); } // Translation unit 2 int f(int a = 76) { return a; } // ill-formed, no diagnostic required; previously well-formed int g(); int main() { return g(); } // used to return 42 — end example]
Affected subclause: [dcl.init.aggr]
Change: A class that has user-declared constructors is never an aggregate.

Rationale: Remove potentially error-prone aggregate initialization which may apply notwithstanding the declared constructors of a class.

Effect on original feature: Valid C++ 2017 code that aggregate-initializes a type with a user-declared constructor may be ill-formed or have different semantics in this revision of C++.
[Example 3: struct A { // not an aggregate; previously an aggregate A() = delete; }; struct B { // not an aggregate; previously an aggregate B() = default; int i = 0; }; struct C { // not an aggregate; previously an aggregate C(C&&) = default; int a, b; }; A a{}; // ill-formed; previously well-formed B b = {1}; // ill-formed; previously well-formed auto* c = new C{2, 3}; // ill-formed; previously well-formed struct Y; struct X { operator Y(); }; struct Y { // not an aggregate; previously an aggregate Y(const Y&) = default; X x; }; Y y{X{}}; // copy constructor call; previously aggregate-initialization — end example]
Affected subclause: [dcl.init.list]
Change: Boolean conversion from a pointer or pointer-to-member type is now a narrowing conversion.

Rationale: Catches bugs.

Effect on original feature: Valid C++ 2017 code may fail to compile in this revision of C++.
[Example 4: bool y[] = { "bc" }; // ill-formed; previously well-formed — end example]

C.3.6 [class]: classes [diff.cpp17.class]

Affected subclauses: [class.ctor] and [class.conv.fct]
Change: The class name can no longer be used parenthesized immediately after an explicit decl-specifier in a constructor declaration.
The conversion-function-id can no longer be used parenthesized immediately after an explicit decl-specifier in a conversion function declaration.

Rationale: Necessary for new functionality.

Effect on original feature: Valid C++ 2017 code may fail to compile in this revision of C++.
[Example 1: struct S { explicit (S)(const S&); // ill-formed; previously well-formed explicit (operator int)(); // ill-formed; previously well-formed explicit(true) (S)(int); // OK }; — end example]
Affected subclauses: [class.ctor] and [class.dtor]
Change: A simple-template-id is no longer valid as the declarator-id of a constructor or destructor.

Rationale: Remove potentially error-prone option for redundancy.

Effect on original feature: Valid C++ 2017 code may fail to compile in this revision of C++.
[Example 2: template<class T> struct A { A<T>(); // error: simple-template-id not allowed for constructor A(int); // OK, injected-class-name used ~A<T>(); // error: simple-template-id not allowed for destructor }; — end example]
Affected subclause: [class.copy.elision]
Change: A function returning an implicitly movable entity may invoke a constructor taking an rvalue reference to a type different from that of the returned expression.
Function and catch-clause parameters can be thrown using move constructors.

Rationale: Side effect of making it easier to write more efficient code that takes advantage of moves.

Effect on original feature: Valid C++ 2017 code may fail to compile or have different semantics in this revision of C++.
[Example 3: struct base { base(); base(base const &); private: base(base &&); }; struct derived : base {}; base f(base b) { throw b; // error: base(base &&) is private derived d; return d; // error: base(base &&) is private } struct S { S(const char *s) : m(s) { } S(const S&) = default; S(S&& other) : m(other.m) { other.m = nullptr; } const char * m; }; S consume(S&& s) { return s; } void g() { S s("text"); consume(static_cast<S&&>(s)); char c = *s.m; // undefined behavior; previously ok } — end example]

C.3.7 [over]: overloading [diff.cpp17.over]

Affected subclause: [over.match.oper]
Change: Equality and inequality expressions can now find reversed and rewritten candidates.

Rationale: Improve consistency of equality with three-way comparison and make it easier to write the full complement of equality operations.

Effect on original feature: For certain pairs of types where one is convertible to the other, equality or inequality expressions between an object of one type and an object of the other type invoke a different operator.
Also, for certain types, equality or inequality expressions between two objects of that type become ambiguous.
[Example 1: struct A { operator int() const; }; bool operator==(A, int); // #1 // #2 is built-in candidate: bool operator==(int, int); // #3 is built-in candidate: bool operator!=(int, int); int check(A x, A y) { return (x == y) + // ill-formed; previously well-formed (10 == x) + // calls #1, previously selected #2 (10 != x); // calls #1, previously selected #3 } — end example]
Affected subclause: [over.match.oper]
Change: Overload resolution may change for equality operators ([expr.eq]).

Rationale: Support calling operator== with reversed order of arguments.

Effect on original feature: Valid C++ 2017 code that uses equality operators with conversion functions may be ill-formed or have different semantics in this revision of C++.
[Example 2: struct A { operator int() const { return 10; } }; bool operator==(A, int); // #1 // #2 is built-in candidate: bool operator==(int, int); bool b = 10 == A(); // calls #1 with reversed order of arguments; previously selected #2 struct B { bool operator==(const B&); // member function with no cv-qualifier }; B b1; bool eq = (b1 == b1); // ambiguous; previously well-formed — end example]

C.3.8 [temp]: templates [diff.cpp17.temp]

Affected subclause: [temp.names]
Change: An unqualified-id that is followed by a < and for which name lookup finds nothing or finds a function will be treated as a template-name in order to potentially cause argument-dependent lookup to be performed.

Rationale: It was problematic to call a function template with an explicit template argument list via argument-dependent lookup because of the need to have a template with the same name visible via normal lookup.

Effect on original feature: Previously valid code that uses a function name as the left operand of a < operator would become ill-formed.
[Example 1: struct A {}; bool operator<(void (*fp)(), A); void f() {} int main() { A a; f < a; // ill-formed; previously well-formed (f) < a; // still well-formed } — end example]

C.3.9 [except]: exception handling [diff.cpp17.except]

Affected subclause: [except.spec]
Change: Remove throw() exception specification.

Rationale: Removal of obsolete feature that has been replaced by noexcept.

Effect on original feature: A valid C++ 2017 function declaration, member function declaration, function pointer declaration, or function reference declaration that uses throw() for its exception specification will be rejected as ill-formed in this revision of C++.
It should simply be replaced with noexcept for no change of meaning since C++ 2017.
[Note 1: 
There is no way to write a function declaration that is non-throwing in this revision of C++ and is also non-throwing in C++ 2003 except by using the preprocessor to generate a different token sequence in each case.
— end note]

C.3.10 [library]: library introduction [diff.cpp17.library]

Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

Valid C++ 2017 code that #includes headers with these names may be invalid in this revision of C++.
Affected subclause: [headers]
Change: Remove vacuous C++ header files.

Rationale: The empty headers implied a false requirement to achieve C compatibility with the C++ headers.

Effect on original feature: A valid C++ 2017 program that #includes any of the following headers may fail to compile: <ccomplex>, <ciso646>, <cstdalign>, <cstdbool>, and <ctgmath>.
To retain the same behavior:
  • a #include of <ccomplex> can be replaced by a #include of <complex>,
  • a #include of <ctgmath> can be replaced by a #include of <cmath> and a #include of <complex>, and
  • a #include of <ciso646>, <cstdalign>, or <cstdbool> can simply be removed.

C.3.11 [containers]: containers library [diff.cpp17.containers]

Affected subclauses: [forward.list] and [list]
Change: Return types of remove, remove_if, and unique changed from void to container​::​size_type.

Rationale: Improve efficiency and convenience of finding number of removed elements.

Effect on original feature: Code that depends on the return types might have different semantics in this revision of C++.
Translation units compiled against this version of C++ may be incompatible with translation units compiled against C++ 2017, either failing to link or having undefined behavior.

C.3.12 [iterators]: iterators library [diff.cpp17.iterators]

Affected subclause: [iterator.traits]
Change: The specialization of iterator_traits for void* and for function pointer types no longer contains any nested typedefs.

Rationale: Corrects an issue misidentifying pointer types that are not incrementable as iterator types.

Effect on original feature: A valid C++ 2017 program that relies on the presence of the typedefs may fail to compile, or have different behavior.

C.3.13 [algorithms]: algorithms library [diff.cpp17.alg.reqs]

Affected subclause: [algorithms.requirements]
Change: The number and order of deducible template parameters for algorithm declarations is now unspecified, instead of being as-declared.

Rationale: Increase implementor freedom and allow some function templates to be implemented as function objects with templated call operators.

Effect on original feature: A valid C++ 2017 program that passes explicit template arguments to algorithms not explicitly specified to allow such in this version of C++ may fail to compile or have undefined behavior.

C.3.14 [input.output]: input/output library [diff.cpp17.input.output]

Affected subclause: [istream.extractors]
Change: Character array extraction only takes array types.

Rationale: Increase safety via preventing buffer overflow at compile time.

Effect on original feature: Valid C++ 2017 code may fail to compile in this revision of C++.
[Example 1: auto p = new char[100]; char q[100]; std::cin >> std::setw(20) >> p; // ill-formed; previously well-formed std::cin >> std::setw(20) >> q; // OK — end example]
Affected subclause: [ostream.inserters.character]
Change: Overload resolution for ostream inserters used with UTF-8 literals.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2017 code that passes UTF-8 literals to basic_ostream<char, ...>​::​operator<< or basic_ostream<wchar_t, ...>​::​operator<< is now ill-formed.
[Example 2: std::cout << u8"text"; // previously called operator<<(const char*) and printed a string; // now ill-formed std::cout << u8'X'; // previously called operator<<(char) and printed a character; // now ill-formed — end example]
Affected subclause: [ostream.inserters.character]
Change: Overload resolution for ostream inserters used with wchar_t, char16_t, or char32_t types.

Rationale: Removal of surprising behavior.

Effect on original feature: Valid C++ 2017 code that passes wchar_t, char16_t, or char32_t characters or strings to basic_ostream<char, ...>​::​operator<< or that passes char16_t or char32_t characters or strings to basic_ostream<wchar_t, ...>​::​operator<< is now ill-formed.
[Example 3: std::cout << u"text"; // previously formatted the string as a pointer value; // now ill-formed std::cout << u'X'; // previously formatted the character as an integer value; // now ill-formed — end example]
Affected subclause: [fs.class.path]
Change: Return type of filesystem path format observer member functions.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2017 code that depends on the u8string() and generic_u8string() member functions of std​::​filesystem​::​path returning std​::​string is not valid in this revision of C++.
[Example 4: std::filesystem::path p; std::string s1 = p.u8string(); // ill-formed; previously well-formed std::string s2 = p.generic_u8string(); // ill-formed; previously well-formed — end example]

C.3.15 [depr]: compatibility features [diff.cpp17.depr]

Change: Remove uncaught_exception.

Rationale: The function did not have a clear specification when multiple exceptions were active, and has been superseded by uncaught_exceptions.

Effect on original feature: A valid C++ 2017 program that calls std​::​uncaught_exception may fail to compile.
It can be revised to use std​::​uncaught_exceptions instead, for clear and portable semantics.
Change: Remove support for adaptable function API.
Rationale: The deprecated support relied on a limited convention that could not be extended to support the general case or new language features.
It has been superseded by direct language support with decltype, and by the std​::​bind and std​::​not_fn function templates.

Effect on original feature: A valid C++ 2017 program that relies on the presence of result_type, argument_type, first_argument_type, or second_argument_type in a standard library class may fail to compile.
A valid C++ 2017 program that calls not1 or not2, or uses the class templates unary_negate or binary_negate, may fail to compile.
Change: Remove redundant members from std​::​allocator.

Rationale: std​::​allocator was overspecified, encouraging direct usage in user containers rather than relying on std​::​allocator_traits, leading to poor containers.

Effect on original feature: A valid C++ 2017 program that directly makes use of the pointer, const_pointer, reference, const_reference, rebind, address, construct, destroy, or max_size members of std​::​allocator, or that directly calls allocate with an additional hint argument, may fail to compile.
Change: Remove raw_storage_iterator.

Rationale: The iterator encouraged use of potentially-throwing algorithms, but did not return the number of elements successfully constructed, as would be necessary to destroy them.

Effect on original feature: A valid C++ 2017 program that uses this iterator class may fail to compile.
Change: Remove temporary buffers API.
Rationale: The temporary buffer facility was intended to provide an efficient optimization for small memory requests, but there is little evidence this was achieved in practice, while requiring the user to provide their own exception-safe wrappers to guard use of the facility in many cases.

Effect on original feature: A valid C++ 2017 program that calls get_temporary_buffer or return_temporary_buffer may fail to compile.
Change: Remove shared_ptr​::​unique.

Rationale: The result of a call to this member function is not reliable in the presence of multiple threads and weak pointers.
The member function use_count is similarly unreliable, but has a clearer contract in such cases, and remains available for well-defined use in single-threaded cases.

Effect on original feature: A valid C++ 2017 program that calls unique on a shared_ptr object may fail to compile.
Affected subclause: [depr.meta.types]
Change: Remove deprecated type traits.

Rationale: The traits had unreliable or awkward interfaces.
The is_literal_type trait provided no way to detect which subset of constructors and member functions of a type were declared constexpr.
The result_of trait had a surprising syntax that did not directly support function types.
It has been superseded by the invoke_result trait.

Effect on original feature: A valid C++ 2017 program that relies on the is_literal_type or result_of type traits, on the is_literal_type_v variable template, or on the result_of_t alias template may fail to compile.

C.4 C++ and ISO C++ 2014 [diff.cpp14]

C.4.1 General [diff.cpp14.general]

Subclause [diff.cpp14] lists the differences between C++ and ISO C++ 2014, in addition to those listed above, by the chapters of this document.

C.4.2 [lex]: lexical conventions [diff.cpp14.lex]

Affected subclause: [lex.phases]
Change: Removal of trigraph support as a required feature.

Rationale: Prevents accidental uses of trigraphs in non-raw string literals and comments.

Effect on original feature: Valid C++ 2014 code that uses trigraphs may not be valid or may have different semantics in this revision of C++.
Implementations may choose to translate trigraphs as specified in C++ 2014 if they appear outside of a raw string literal, as part of the implementation-defined mapping from input source file characters to the translation character set.
Affected subclause: [lex.ppnumber]
Change: pp-number can contain p sign and P sign.

Rationale: Necessary to enable hexadecimal-floating-point-literals.

Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this revision of C++.
Specifically, character sequences like 0p+0 and 0e1_p+0 are three separate tokens each in C++ 2014, but one single token in this revision of C++.
[Example 1: #define F(a) b ## a int b0p = F(0p+0); // ill-formed; equivalent to “int b0p = b0p + 0;'' in C++ 2014 — end example]

C.4.3 [expr]: expressions [diff.cpp14.expr]

Affected subclauses: [expr.post.incr] and [expr.pre.incr]
Change: Remove increment operator with bool operand.

Rationale: Obsolete feature with occasionally surprising semantics.

Effect on original feature: A valid C++ 2014 expression utilizing the increment operator on a bool lvalue is ill-formed in this revision of C++.
Affected subclauses: [expr.new] and [expr.delete]
Change: Dynamic allocation mechanism for over-aligned types.

Rationale: Simplify use of over-aligned types.

Effect on original feature: In C++ 2014 code that uses a new-expression to allocate an object with an over-aligned class type, where that class has no allocation functions of its own, ​::​operator new(std​::​size_t) is used to allocate the memory.
In this revision of C++, ​::​operator new(std​::​size_t, std​::​align_val_t) is used instead.

C.4.4 [dcl.dcl]: declarations [diff.cpp14.dcl.dcl]

Affected subclause: [dcl.stc]
Change: Removal of register storage-class-specifier.

Rationale: Enable repurposing of deprecated keyword in future revisions of C++.

Effect on original feature: A valid C++ 2014 declaration utilizing the register storage-class-specifier is ill-formed in this revision of C++.
The specifier can simply be removed to retain the original meaning.
Affected subclause: [dcl.spec.auto]
Change: auto deduction from braced-init-list.

Rationale: More intuitive deduction behavior.

Effect on original feature: Valid C++ 2014 code may fail to compile or may change meaning in this revision of C++.
[Example 1: auto x1{1}; // was std​::​initializer_list<int>, now int auto x2{1, 2}; // was std​::​initializer_list<int>, now ill-formed — end example]
Affected subclause: [dcl.fct]
Change: Make exception specifications be part of the type system.

Rationale: Improve type-safety.

Effect on original feature: Valid C++ 2014 code may fail to compile or change meaning in this revision of C++.
[Example 2: void g1() noexcept; void g2(); template<class T> int f(T *, T *); int x = f(g1, g2); // ill-formed; previously well-formed — end example]
Affected subclause: [dcl.init.aggr]
Change: Definition of an aggregate is extended to apply to user-defined types with base classes.

Rationale: To increase convenience of aggregate initialization.

Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this revision of C++; initialization from an empty initializer list will perform aggregate initialization instead of invoking a default constructor for the affected types.
[Example 3: struct derived; struct base { friend struct derived; private: base(); }; struct derived : base {}; derived d1{}; // error; the code was well-formed in C++ 2014 derived d2; // still OK — end example]

C.4.5 [class]: classes [diff.cpp14.class]

Affected subclause: [class.inhctor.init]
Change: Inheriting a constructor no longer injects a constructor into the derived class.

Rationale: Better interaction with other language features.

Effect on original feature: Valid C++ 2014 code that uses inheriting constructors may not be valid or may have different semantics.
A using-declaration that names a constructor now makes the corresponding base class constructors visible to initializations of the derived class rather than declaring additional derived class constructors.
[Example 1: struct A { template<typename T> A(T, typename T::type = 0); A(int); }; struct B : A { using A::A; B(int); }; B b(42L); // now calls B(int), used to call B<long>(long), // which called A(int) due to substitution failure // in A<long>(long). — end example]

C.4.6 [temp]: templates [diff.cpp14.temp]

Affected subclause: [temp.deduct.type]
Change: Allowance to deduce from the type of a non-type template argument.

Rationale: In combination with the ability to declare non-type template arguments with placeholder types, allows partial specializations to decompose from the type deduced for the non-type template argument.

Effect on original feature: Valid C++ 2014 code may fail to compile or produce different results in this revision of C++.
[Example 1: template <int N> struct A; template <typename T, T N> int foo(A<N> *) = delete; void foo(void *); void bar(A<0> *p) { foo(p); // ill-formed; previously well-formed } — end example]

C.4.7 [except]: exception handling [diff.cpp14.except]

Affected subclause: [except.spec]
Change: Remove dynamic exception specifications.

Rationale: Dynamic exception specifications were a deprecated feature that was complex and brittle in use.
They interacted badly with the type system, which became a more significant issue in this revision of C++ where (non-dynamic) exception specifications are part of the function type.

Effect on original feature: A valid C++ 2014 function declaration, member function declaration, function pointer declaration, or function reference declaration, if it has a potentially throwing dynamic exception specification, is rejected as ill-formed in this revision of C++.
Violating a non-throwing dynamic exception specification calls terminate rather than unexpected, and it is unspecified whether stack unwinding is performed prior to such a call.

C.4.8 [library]: library introduction [diff.cpp14.library]

Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

Effect on original feature: The following C++ headers are new: <any>, <charconv>, <execution>, <filesystem>, <memory_resource>, <optional>,
Valid C++ 2014 code that #includes headers with these names may be invalid in this revision of C++.
Affected subclause: [namespace.future]
Change: New reserved namespaces.

Rationale: Reserve namespaces for future revisions of the standard library that might otherwise be incompatible with existing programs.

Effect on original feature: The global namespaces std followed by an arbitrary sequence of digits ([lex.name]) are reserved for future standardization.
Valid C++ 2014 code that uses such a top-level namespace, e.g., std2, may be invalid in this revision of C++.

C.4.9 [utilities]: general utilities library [diff.cpp14.utilities]

Affected subclause: [func.wrap]
Change: Constructors taking allocators removed.

Rationale: No implementation consensus.

Effect on original feature: Valid C++ 2014 code may fail to compile or may change meaning in this revision of C++.
Specifically, constructing a std​::​function with an allocator is ill-formed and uses-allocator construction will not pass an allocator to std​::​function constructors in this revision of C++.
Affected subclause: [util.smartptr.shared]
Change: Different constraint on conversions from unique_ptr.

Rationale: Adding array support to shared_ptr, via the syntax shared_ptr<T[]> and shared_ptr<T[N]>.

Effect on original feature: Valid C++ 2014 code may fail to compile or may change meaning in this revision of C++.
[Example 1: #include <memory> std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr)); // error: int(*)[] is not compatible with int* — end example]

C.4.10 [strings]: strings library [diff.cpp14.string]

Affected subclause: [basic.string]
Change: Non-const .data() member added.

Rationale: The lack of a non-const .data() differed from the similar member of std​::​vector.
This change regularizes behavior.

Effect on original feature: Overloaded functions which have differing code paths for char* and const char* arguments will execute differently when called with a non-const string's .data() member in this revision of C++.
[Example 1: int f(char *) = delete; int f(const char *); string s; int x = f(s.data()); // ill-formed; previously well-formed — end example]

C.4.11 [containers]: containers library [diff.cpp14.containers]

Affected subclause: [associative.reqmts]
Change: Requirements change:
Rationale: Increase portability, clarification of associative container requirements.

Effect on original feature: Valid C++ 2014 code that attempts to use associative containers having a comparison object with non-const function call operator may fail to compile in this revision of C++.
[Example 1: #include <set> struct compare { bool operator()(int a, int b) { return a < b; } }; int main() { const std::set<int, compare> s; s.find(0); } — end example]

C.4.12 [depr]: compatibility features [diff.cpp14.depr]

Change: The class templates auto_ptr, unary_function, and binary_function, the function templates random_shuffle, and the function templates (and their return types) ptr_fun, mem_fun, mem_fun_ref, bind1st, and bind2nd are not defined.

Rationale: Superseded by new features.

Effect on original feature: Valid C++ 2014 code that uses these class templates and function templates may fail to compile in this revision of C++.
Change: Remove old iostreams members [depr.ios.members].

Rationale: Redundant feature for compatibility with pre-standard code has served its time.

Effect on original feature: A valid C++ 2014 program using these identifiers may be ill-formed in this revision of C++.

C.5 C++ and ISO C++ 2011 [diff.cpp11]

C.5.1 General [diff.cpp11.general]

Subclause [diff.cpp11] lists the differences between C++ and ISO C++ 2011, in addition to those listed above, by the chapters of this document.

C.5.2 [lex]: lexical conventions [diff.cpp11.lex]

Affected subclause: [lex.ppnumber]
Change: pp-number can contain one or more single quotes.

Rationale: Necessary to enable single quotes as digit separators.

Effect on original feature: Valid C++ 2011 code may fail to compile or may change meaning in this revision of C++.
For example, the following code is valid both in C++ 2011 and in this revision of C++, but the macro invocation produces different outcomes because the single quotes delimit a character-literal in C++ 2011, whereas they are digit separators in this revision of C++.
[Example 1: #define M(x, ...) __VA_ARGS__ int x[2] = { M(1'2,3'4, 5) }; // int x[2] = { 5 };      --- C++ 2011 // int x[2] = { 3'4, 5 }; --- this revision of C++ — end example]

C.5.3 [basic]: basics [diff.cpp11.basic]

Affected subclause: [basic.stc.dynamic.deallocation]
Change: New usual (non-placement) deallocator.

Rationale: Required for sized deallocation.

Effect on original feature: Valid C++ 2011 code can declare a global placement allocation function and deallocation function as follows: void* operator new(std::size_t, std::size_t); void operator delete(void*, std::size_t) noexcept;
In this revision of C++, however, the declaration of operator delete might match a predefined usual (non-placement) operator delete ([basic.stc.dynamic]).
If so, the program is ill-formed, as it was for class member allocation functions and deallocation functions ([expr.new]).

C.5.4 [expr]: expressions [diff.cpp11.expr]

Affected subclause: [expr.cond]
Change: A conditional expression with a throw expression as its second or third operand keeps the type and value category of the other operand.

Rationale: Formerly mandated conversions (lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions), especially the creation of the temporary due to lvalue-to-rvalue conversion, were considered gratuitous and surprising.

Effect on original feature: Valid C++ 2011 code that relies on the conversions may behave differently in this revision of C++.
[Example 1: struct S { int x = 1; void mf() { x = 2; } }; int f(bool cond) { S s; (cond ? s : throw 0).mf(); return s.x; }
In C++ 2011, f(true) returns 1.
In this revision of C++, it returns 2.
sizeof(true ? "" : throw 0)
In C++ 2011, the expression yields sizeof(const char*).
In this revision of C++, it yields sizeof(const char[1]).
— end example]

C.5.5 [dcl.dcl]: declarations [diff.cpp11.dcl.dcl]

Affected subclause: [dcl.constexpr]
Change: constexpr non-static member functions are not implicitly const member functions.

Rationale: Necessary to allow constexpr member functions to mutate the object.

Effect on original feature: Valid C++ 2011 code may fail to compile in this revision of C++.
[Example 1: struct S { constexpr const int &f(); int &f(); };
This code is valid in C++ 2011 but invalid in this revision of C++ because it declares the same member function twice with different return types.
— end example]
Affected subclause: [dcl.init.aggr]
Change: Classes with default member initializers can be aggregates.

Rationale: Necessary to allow default member initializers to be used by aggregate initialization.

Effect on original feature: Valid C++ 2011 code may fail to compile or may change meaning in this revision of C++.
[Example 2: struct S { // Aggregate in C++ 2014 onwards. int m = 1; }; struct X { operator int(); operator S(); }; X a{}; S b{a}; // uses copy constructor in C++ 2011, // performs aggregate initialization in this revision of C++ — end example]

C.5.6 [library]: library introduction [diff.cpp11.library]

Affected subclause: [headers]
Change: New header.

Rationale: New functionality.

Effect on original feature: The C++ header <shared_mutex> is new.
Valid C++ 2011 code that #includes a header with that name may be invalid in this revision of C++.

C.5.7 [input.output]: input/output library [diff.cpp11.input.output]

Affected subclause: [c.files]
Change: gets is not defined.

Rationale: Use of gets is considered dangerous.

Effect on original feature: Valid C++ 2011 code that uses the gets function may fail to compile in this revision of C++.

C.6 C++ and ISO C++ 2003 [diff.cpp03]

C.6.1 General [diff.cpp03.general]

Subclause [diff.cpp03] lists the differences between C++ and ISO C++ 2003, in addition to those listed above, by the chapters of this document.

C.6.2 [lex]: lexical conventions [diff.cpp03.lex]

Affected subclause: [lex.pptoken]
Change: New kinds of string-literals.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2003 code may fail to compile or produce different results in this revision of C++.
Specifically, macros named R, u8, u8R, u, uR, U, UR, or LR will not be expanded when adjacent to a string-literal but will be interpreted as part of the string-literal.
[Example 1: #define u8 "abc" const char* s = u8"def"; // Previously "abcdef", now "def" — end example]
Affected subclause: [lex.pptoken]
Change: User-defined literal string support.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2003 code may fail to compile or produce different results in this revision of C++.
[Example 2: #define _x "there" "hello"_x // #1
Previously, #1 would have consisted of two separate preprocessing tokens and the macro _x would have been expanded.
In this revision of C++, #1 consists of a single preprocessing token, so the macro is not expanded.
— end example]
Affected subclause: [lex.key]
Change: New keywords.

Rationale: Required for new features.

Effect on original feature: Added to Table 5, the following identifiers are new keywords: alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert, and thread_local.
Valid C++ 2003 code using these identifiers is invalid in this revision of C++.
Affected subclause: [lex.icon]
Change: Type of integer literals.

Rationale: C99 compatibility.

Effect on original feature: Certain integer literals larger than can be represented by long could change from an unsigned integer type to signed long long.

C.6.3 [expr]: expressions [diff.cpp03.expr]

Affected subclause: [conv.ptr]
Change: Only literals are integer null pointer constants.

Rationale: Removing surprising interactions with templates and constant expressions.

Effect on original feature: Valid C++ 2003 code may fail to compile or produce different results in this revision of C++.
[Example 1: void f(void *); // #1 void f(...); // #2 template<int N> void g() { f(0*N); // calls #2; used to call #1 } — end example]
Affected subclause: [expr.typeid]
Change: Evaluation of operands in typeid.

Rationale: Introduce additional expression value categories.

Effect on original feature: Valid C++ 2003 code that uses xvalues as operands for typeid may change behavior in this revision of C++.
[Example 2: void f() { struct B { B() {} virtual ~B() { } }; struct C { B b; }; typeid(C().b); // unevaluated in C++ 2003, evaluated in C++ 2011 } — end example]
Affected subclause: [expr.mul]
Change: Specify rounding for results of integer / and %.

Rationale: Increase portability, C99 compatibility.

Effect on original feature: Valid C++ 2003 code that uses integer division rounds the result toward 0 or toward negative infinity, whereas this revision of C++ always rounds the result toward 0.
Affected subclause: [expr.log.and]
Change: && is valid in a type-name.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2003 code may fail to compile or produce different results in this revision of C++.
[Example 3: bool b1 = new int && false; // previously false, now ill-formed struct S { operator int(); }; bool b2 = &S::operator int && false; // previously false, now ill-formed — end example]
Affected subclause: [expr.cond]
Change: Fewer copies in the conditional operator.

Rationale: Introduce additional expression value categories.

Effect on original feature: Valid C++ 2003 code that uses xvalues as operands for the conditional operator may change behavior in this revision of C++.
[Example 4: void f() { struct B { B() {} B(const B&) { } }; struct D : B {}; struct BB { B b; }; struct DD { D d; }; true ? BB().b : DD().d; // additional copy in C++ 2003, no copy or move in C++ 2011 } — end example]

C.6.4 [dcl.dcl]: declarations [diff.cpp03.dcl.dcl]

Affected subclause: [dcl.spec]
Change: Remove auto as a storage class specifier.

Rationale: New feature.

Effect on original feature: Valid C++ 2003 code that uses the keyword auto as a storage class specifier may be invalid in this revision of C++.
In this revision of C++, auto indicates that the type of a variable is to be deduced from its initializer expression.
Affected subclause: [dcl.init.list]
Change: Narrowing restrictions in aggregate initializers.

Rationale: Catches bugs.

Effect on original feature: Valid C++ 2003 code may fail to compile in this revision of C++.
[Example 1: int x[] = { 2.0 };
This code is valid in C++ 2003 but invalid in this revision of C++ because double to int is a narrowing conversion.
— end example]
Affected subclause: [dcl.link]
Change: Names declared in an anonymous namespace changed from external linkage to internal linkage; language linkage applies to names with external linkage only.

Rationale: Alignment with user expectations.

Effect on original feature: Valid C++ 2003 code may violate the one-definition rule ([basic.def.odr]) in this revision of C++.
[Example 2: namespace { extern "C" { extern int x; } } // #1, previously external linkage and C language linkage, // now internal linkage and C++ language linkage namespace A { extern "C" int x = 42; } // #2, external linkage and C language linkage int main(void) { return x; }
This code is valid in C++ 2003, but #2 is not a definition for #1 in this revision of C++, violating the one-definition rule.
— end example]

C.6.5 [class]: classes [diff.cpp03.class]

Affected subclauses: [class.default.ctor], [class.dtor], [class.copy.ctor], and [class.copy.assign]
Change: Implicitly-declared special member functions are defined as deleted when the implicit definition would have been ill-formed.

Rationale: Improves template argument deduction failure.

Effect on original feature: A valid C++ 2003 program that uses one of these special member functions in a context where the definition is not required (e.g., in an expression that is not potentially evaluated) becomes ill-formed.
Affected subclause: [class.dtor]
Change: User-declared destructors have an implicit exception specification.

Rationale: Clarification of destructor requirements.

Effect on original feature: Valid C++ 2003 code may execute differently in this revision of C++.
In particular, destructors that throw exceptions will call std​::​terminate (without calling std​::​unexpected) if their exception specification is non-throwing.

C.6.6 [temp]: templates [diff.cpp03.temp]

Affected subclause: [temp.param]
Change: Repurpose export for modules ([module], [cpp.module], [cpp.import]).

Rationale: No implementation consensus for the C++ 2003 meaning of export.

Effect on original feature: A valid C++ 2003 program containing export is ill-formed in this revision of C++.
Affected subclause: [temp.arg]
Change: Remove whitespace requirement for nested closing template right angle brackets.

Rationale: Considered a persistent but minor annoyance.
Template aliases representing non-class types would exacerbate whitespace issues.

Effect on original feature: Change to semantics of well-defined expression.
A valid C++ 2003 expression containing a right angle bracket (“>”) followed immediately by another right angle bracket may now be treated as closing two templates.
[Example 1: template <class T> struct X { }; template <int N> struct Y { }; X< Y< 1 >> 2 > > x;
This code is valid in C++ 2003 because “>>” is a right-shift operator, but invalid in this revision of C++ because “>>” closes two templates.
— end example]
Affected subclause: [temp.dep.candidate]
Change: Allow dependent calls of functions with internal linkage.

Rationale: Overly constrained, simplify overload resolution rules.

Effect on original feature: A valid C++ 2003 program can get a different result in this revision of C++.

C.6.7 [library]: library introduction [diff.cpp03.library]

Affected: [library][exec]
Change: New reserved identifiers.

Rationale: Required by new features.

Effect on original feature: Valid C++ 2003 code that uses any identifiers added to the C++ standard library by later revisions of C++ may fail to compile or produce different results in this revision of C++.
A comprehensive list of identifiers used by the C++ standard library can be found in the Index of Library Names in this document.
Affected subclause: [headers]
Change: New headers.

Rationale: New functionality.

In addition the following C compatibility headers are new: <cfenv>, <cinttypes>, <cstdint>, and <cuchar>.
Valid C++ 2003 code that #includes headers with these names may be invalid in this revision of C++.
Affected subclause: [swappable.requirements]
Change: Function swap moved to a different header.

Rationale: Remove dependency on <algorithm> for swap.

Effect on original feature: Valid C++ 2003 code that has been compiled expecting swap to be in <algorithm> may have to instead include <utility>.
Affected subclause: [namespace.posix]
Change: New reserved namespace.

Rationale: New functionality.

Effect on original feature: The global namespace posix is now reserved for standardization.
Valid C++ 2003 code that uses a top-level namespace posix may be invalid in this revision of C++.
Affected subclause: [res.on.macro.definitions]
Change: Additional restrictions on macro names.

Rationale: Avoid hard to diagnose or non-portable constructs.

Effect on original feature: Names of attribute identifiers may not be used as macro names.
Valid C++ 2003 code that defines override, final, carries_dependency, or noreturn as macros is invalid in this revision of C++.

C.6.8 [support]: language support library [diff.cpp03.language.support]

Affected subclause: [new.delete.single]
Change: operator new may throw exceptions other than std​::​bad_alloc.

Rationale: Consistent application of noexcept.

Effect on original feature: Valid C++ 2003 code that assumes that global operator new only throws std​::​bad_alloc may execute differently in this revision of C++.
Valid C++ 2003 code that replaces the global replaceable operator new is ill-formed in this revision of C++, because the exception specification of throw(std​::​bad_alloc) was removed.

C.6.9 [diagnostics]: diagnostics library [diff.cpp03.diagnostics]

Affected subclause: [errno]
Change: Thread-local error numbers.

Rationale: Support for new thread facilities.

Effect on original feature: Valid but implementation-specific C++ 2003 code that relies on errno being the same across threads may change behavior in this revision of C++.

C.6.10 [utilities]: general utilities library [diff.cpp03.utilities]

Affected subclauses: [refwrap], [arithmetic.operations], [comparisons], [logical.operations], and [bitwise.operations]
Change: Standard function object types no longer derived from std​::​unary_function or std​::​binary_function.

Rationale: Superseded by new feature; unary_function and binary_function are no longer defined.

Effect on original feature: Valid C++ 2003 code that depends on function object types being derived from unary_function or binary_function may fail to compile in this revision of C++.

C.6.11 [strings]: strings library [diff.cpp03.strings]

Affected subclause: [string.classes]
Change: basic_string requirements no longer allow reference-counted strings.

Rationale: Invalidation is subtly different with reference-counted strings.
This change regularizes behavior.

Effect on original feature: Valid C++ 2003 code may execute differently in this revision of C++.
Affected subclause: [string.require]
Change: Loosen basic_string invalidation rules.

Rationale: Allow small-string optimization.

Effect on original feature: Valid C++ 2003 code may execute differently in this revision of C++.
Some const member functions, such as data and c_str, no longer invalidate iterators.

C.6.12 [containers]: containers library [diff.cpp03.containers]

Affected subclause: [container.requirements]
Change: Complexity of size() member functions now constant.

Rationale: Lack of specification of complexity of size() resulted in divergent implementations with inconsistent performance characteristics.

Effect on original feature: Some container implementations that conform to C++ 2003 may not conform to the specified size() requirements in this revision of C++.
Adjusting containers such as std​::​list to the stricter requirements may require incompatible changes.
Affected subclause: [container.requirements]
Change: Requirements change: relaxation.

Rationale: Clarification.

Effect on original feature: Valid C++ 2003 code that attempts to meet the specified container requirements may now be over-specified.
Code that attempted to be portable across containers may need to be adjusted as follows:
  • not all containers provide size(); use empty() instead of size() == 0;
  • not all containers are empty after construction (array);
  • not all containers have constant complexity for swap() (array).
Affected subclause: [container.requirements]
Change: Requirements change: default constructible.

Rationale: Clarification of container requirements.

Effect on original feature: Valid C++ 2003 code that attempts to explicitly instantiate a container using a user-defined type with no default constructor may fail to compile.
Affected subclauses: [sequence.reqmts] and [associative.reqmts]
Change: Signature changes: from void return types.

Rationale: Old signature threw away useful information that may be expensive to recalculate.

Effect on original feature: The following member functions have changed:
  • erase(iter) for set, multiset, map, multimap
  • erase(begin, end) for set, multiset, map, multimap
  • insert(pos, num, val) for vector, deque, list, forward_list
  • insert(pos, beg, end) for vector, deque, list, forward_list
Valid C++ 2003 code that relies on these functions returning void (e.g., code that creates a pointer to member function that points to one of these functions) will fail to compile with this revision of C++.
Affected subclauses: [sequence.reqmts] and [associative.reqmts]
Change: Signature changes: from iterator to const_iterator parameters.

Rationale: Overspecification.

Effect on original feature: The signatures of the following member functions changed from taking an iterator to taking a const_iterator:
  • insert(iter, val) for vector, deque, list, set, multiset, map, multimap
  • insert(pos, beg, end) for vector, deque, list, forward_list
  • erase(begin, end) for set, multiset, map, multimap
  • all forms of list​::​splice
  • all forms of list​::​merge
Valid C++ 2003 code that uses these functions may fail to compile with this revision of C++.
Affected subclauses: [sequence.reqmts] and [associative.reqmts]
Change: Signature changes: resize.

Rationale: Performance, compatibility with move semantics.

Effect on original feature: For vector, deque, and list the fill value passed to resize is now passed by reference instead of by value, and an additional overload of resize has been added.
Valid C++ 2003 code that uses this function may fail to compile with this revision of C++.

C.6.13 [algorithms]: algorithms library [diff.cpp03.algorithms]

Affected subclause: [algorithms.general]
Change: Result state of inputs after application of some algorithms.

Rationale: Required by new feature.

Effect on original feature: A valid C++ 2003 program may detect that an object with a valid but unspecified state has a different valid but unspecified state with this revision of C++.
For example, std​::​remove and std​::​remove_if may leave the tail of the input sequence with a different set of values than previously.

C.6.14 [numerics]: numerics library [diff.cpp03.numerics]

Affected subclause: [complex.numbers]
Change: Specified representation of complex numbers.

Rationale: Compatibility with C99.

Effect on original feature: Valid C++ 2003 code that uses implementation-specific knowledge about the binary representation of the required template specializations of std​::​complex may not be compatible with this revision of C++.

C.6.15 [localization]: localization library [diff.cpp03.locale]

Affected subclause: [facet.num.get.virtuals]
Change: The num_get facet recognizes hexadecimal floating point values.

Rationale: Required by new feature.

Effect on original feature: Valid C++ 2003 code may have different behavior in this revision of C++.

C.6.16 [input.output]: input/output library [diff.cpp03.input.output]

Affected subclauses: [istream.sentry], [ostream.sentry], and [iostate.flags]
Change: Specify use of explicit in existing boolean conversion functions.

Rationale: Clarify intentions, avoid workarounds.

Effect on original feature: Valid C++ 2003 code that relies on implicit boolean conversions will fail to compile with this revision of C++.
Such conversions occur in the following conditions:
  • passing a value to a function that takes an argument of type bool;
  • using operator== to compare to false or true;
  • returning a value from a function with a return type of bool;
  • initializing members of type bool via aggregate initialization;
  • initializing a const bool& which would bind to a temporary object.
Affected subclause: [ios.failure]
Change: Change base class of std​::​ios_base​::​failure.

Rationale: More detailed error messages.

Effect on original feature: std​::​ios_base​::​failure is no longer derived directly from std​::​exception, but is now derived from std​::​system_error, which in turn is derived from std​::​runtime_error.
Valid C++ 2003 code that assumes that std​::​ios_base​::​failure is derived directly from std​::​exception may execute differently in this revision of C++.
Affected subclause: [ios.base]
Change: Flag types in std​::​ios_base are now bitmasks with values defined as constexpr static members.

Rationale: Required for new features.

Effect on original feature: Valid C++ 2003 code that relies on std​::​ios_base flag types being represented as std​::​bitset or as an integer type may fail to compile with this revision of C++.
[Example 1: #include <iostream> int main() { int flag = std::ios_base::hex; std::cout.setf(flag); // error: setf does not take argument of type int } — end example]

C.7 C++ and C [diff.iso]

C.7.1 General [diff.iso.general]

Subclause [diff.iso] lists the differences between C++ and C, in addition to those listed above, by the chapters of this document.

C.7.2 [lex]: lexical conventions [diff.lex]

Affected subclause: [lex.key]
Change: New Keywords
New keywords are added to C++; see [lex.key].

Rationale: These keywords were added in order to implement the new semantics of C++.

Effect on original feature: Change to semantics of well-defined feature.
Any C programs that used any of these keywords as identifiers are not valid C++ programs.

Difficulty of converting: Syntactic transformation.
Converting one specific program is easy.
Converting a large collection of related programs takes more work.

How widely used: Common.
Affected subclause: [lex.ccon]
Change: Type of character-literal is changed from int to char.

Rationale: This is needed for improved overloaded function argument type matching.
[Example 1: int function( int i ); int function( char c ); function( 'x' );
It is preferable that this call match the second version of function rather than the first.
— end example]

Effect on original feature: Change to semantics of well-defined feature.
C programs which depend on sizeof('x') == sizeof(int) will not work the same as C++ programs.

Difficulty of converting: Simple.

How widely used: Programs which depend upon sizeof('x') are probably rare.
Affected subclause: [lex.string]
Change: Concatenated string-literals can no longer have conflicting encoding-prefixes.

Rationale: Removal of non-portable feature.

Effect on original feature: Concatenation of string-literals with different encoding-prefixes is now ill-formed.

Difficulty of converting: Syntactic transformation.

How widely used: Seldom.
Affected subclause: [lex.string]
Change: String literals made const.

The type of a string-literal is changed from “array of char” to “array of const char.
The type of a UTF-8 string literal is changed from “array of char” to “array of const char8_t.
The type of a UTF-16 string literal is changed from “array of some-integer-type” to “array of const char16_t.
The type of a UTF-32 string literal is changed from “array of some-integer-type” to “array of const char32_t.
The type of a wide string literal is changed from “array of wchar_t” to “array of const wchar_t.

Rationale: This avoids calling an inappropriate overloaded function, which might expect to be able to modify its argument.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Syntactic transformation.
The fix is to add a cast: char* p = "abc"; // valid in C, invalid in C++ void f(char*) { char* p = (char*)"abc"; // OK, cast added f(p); f((char*)"def"); // OK, cast added }
How widely used: Programs that have a legitimate reason to treat string literal objects as potentially modifiable memory are probably rare.

C.7.3 [basic]: basics [diff.basic]

Affected subclause: [basic.def]
Change: C++ does not have “tentative definitions” as in C.
[Example 1: 
At file scope, int i; int i; is valid in C, invalid in C++.
— end example]
This makes it impossible to define mutually referential file-local objects with static storage duration, if initializers are restricted to the syntactic forms of C.
[Example 2: struct X { int i; struct X* next; }; static struct X a; static struct X b = { 0, &a }; static struct X a = { 1, &b }; — end example]

Rationale: This avoids having different initialization rules for fundamental types and user-defined types.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
In C++, the initializer for one of a set of mutually-referential file-local objects with static storage duration must invoke a function call to achieve the initialization.

How widely used: Seldom.
Affected subclause: [basic.scope]
Change: A struct is a scope in C++, not in C.
[Example 3: 
struct X { struct Y { int a; } b; }; struct Y c; is valid in C but not in C++, which would require X​::​Y c;.
— end example]

Rationale: Class scope is crucial to C++, and a struct is a class.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: C programs use struct extremely frequently, but the change is only noticeable when struct, enumeration, or enumerator names are referred to outside the struct.
The latter is probably rare.
Affected subclause: [basic.link] [also [dcl.type]]
Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage.

Rationale: Because const objects may be used as values during translation in C++, this feature urges programmers to provide an explicit initializer for each const object.
This feature allows the user to put const objects in source files that are included in more than one translation unit.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: Seldom.
Affected subclause: [basic.start.main]
Change: The main function cannot be called recursively and cannot have its address taken.

Rationale: The main function may require special actions.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Trivial: create an intermediary function such as mymain(argc, argv).

How widely used: Seldom.
Affected subclause: [basic.types]
Change: C allows “compatible types” in several places, C++ does not.

For example, otherwise-identical struct types with different tag names are “compatible” in C but are distinctly different types in C++.

Rationale: Stricter type checking is essential for C++.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
The “typesafe linkage” mechanism will find many, but not all, of such problems.
Those problems not found by typesafe linkage will continue to function properly, according to the “layout compatibility rules” of this document.

How widely used: Common.

C.7.4 [expr]: expressions [diff.expr]

Affected subclause: [conv.ptr]
Change: Converting void* to a pointer-to-object type requires casting.
[Example 1: char a[10]; void* b=a; void foo() { char* c=b; }
C accepts this usage of pointer to void being assigned to a pointer to object type.
C++ does not.
— end example]

Rationale: C++ tries harder than C to enforce compile-time type safety.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Can be automated.
Violations will be diagnosed by the C++ translator.
The fix is to add a cast.
[Example 2: char* c = (char*) b; — end example]

How widely used: This is fairly widely used but it is good programming practice to add the cast when assigning pointer-to-void to pointer-to-object.
Some C translators will give a warning if the cast is not used.
Affected subclause: [expr.arith.conv]
Change: Operations mixing a value of an enumeration type and a value of a different enumeration type or of a floating-point type are not valid.
[Example 3: enum E1 { e }; enum E2 { f }; int b = e <= 3.7; // valid in C; ill-formed in C++ int k = f - e; // valid in C; ill-formed in C++ int x = 1 ? e : f; // valid in C; ill-formed in C++ — end example]

Rationale: Reinforcing type safety in C++.

Effect on original feature: Well-formed C code will not compile with this International Standard.

Difficulty of converting: Violations will be diagnosed by the C++ translator.
The original behavior can be restored with a cast or integral promotion.
[Example 4: enum E1 { e }; enum E2 { f }; int b = (int)e <= 3.7; int k = +f - e; — end example]

How widely used: Uncommon.
Affected subclauses: [expr.post.incr] and [expr.pre.incr]
Change: Decrement operator is not allowed with bool operand.

Rationale: Feature with surprising semantics.

Effect on original feature: A valid C expression utilizing the decrement operator on a bool lvalue (for instance, via the C typedef in <stdbool.h>) is ill-formed in C++.
Affected subclauses: [expr.sizeof] and [expr.cast]
Change: In C++, types can only be defined in declarations, not in expressions.

In C, a sizeof expression or cast expression may define a new type.
[Example 5: 
p = (void*)(struct x {int i;} *)0; defines a new type, struct x.
— end example]

Rationale: This prohibition helps to clarify the location of definitions in the source code.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Seldom.
Affected subclauses: [expr.rel] and [expr.eq]
Change: C allows directly comparing two objects of array type; C++ does not.

Rationale: The behavior is confusing because it compares not the contents of the two arrays, but their addresses.

Effect on original feature: Deletion of semantically well-defined feature that had unspecified behavior in common use cases.

Difficulty of converting: Violations will be diagnosed by the C++ translator.
The original behavior can be replicated by explicitly casting either array to a pointer, such as by using a unary +.
[Example 6: int arr1[5]; int arr2[5]; int same = arr1 == arr2; // valid C, ill-formed C++ int idem = arr1 == +arr2; // valid in both C and C++ — end example]

How widely used: Rare.
Affected subclauses: [expr.cond], [expr.ass], and [expr.comma]
Change: The result of a conditional expression, an assignment expression, or a comma expression may be an lvalue.

Rationale: C++ is an object-oriented language, placing relatively more emphasis on lvalues.
For example, function calls may yield lvalues.

Effect on original feature: Change to semantics of well-defined feature.
Some C expressions that implicitly rely on lvalue-to-rvalue conversions will yield different results.
[Example 7: 
char arr[100]; sizeof(0, arr) yields 100 in C++ and sizeof(char*) in C.
— end example]

Difficulty of converting: Programs must add explicit casts to the appropriate rvalue.

How widely used: Rare.

C.7.5 [stmt.stmt]: statements [diff.stat]

Affected subclauses: [stmt.switch] and [stmt.goto]
Change: It is now invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered).

Rationale: Constructors used in initializers may allocate resources which need to be de-allocated upon leaving the block.
Allowing jump past initializers would require complicated runtime determination of allocation.
Furthermore, many operations on such an uninitialized object have undefined behavior.
With this simple compile-time rule, C++ assures that if an initialized variable is in scope, then it has assuredly been initialized.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: Seldom.
Affected subclause: [stmt.return]
Change: It is now invalid to return (explicitly or implicitly) from a function which is declared to return a value without actually returning a value.

Rationale: The caller and callee may assume fairly elaborate return-value mechanisms for the return of class objects.
If some flow paths execute a return without specifying any value, the implementation must embody many more complications.
Besides, 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 functions with void and int return types.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
Add an appropriate return value to the source code, such as zero.

How widely used: Seldom.
For several years, many existing C implementations have produced warnings in this case.

C.7.6 [dcl.dcl]: declarations [diff.dcl]

Affected subclause: [dcl.stc]
Change: In C++, the static or extern specifiers can only be applied to names of objects or functions.

Using these specifiers with type declarations is illegal in C++.
In C, these specifiers are ignored when used on type declarations.
[Example 1: static struct S { // valid C, invalid in C++ int i; }; — end example]

Rationale: Storage class specifiers don't have any meaning when associated with a type.
In C++, class members can be declared with the static storage class specifier.
Storage class specifiers on type declarations can be confusing for users.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Seldom.
Affected subclause: [dcl.stc]
Change: In C++, register is not a storage class specifier.

Rationale: The storage class specifier had no effect in C++.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Common.
Affected subclause: [dcl.typedef]
Change: A C++ typedef-name must be different from any class type name declared in the same scope (except if the typedef is a synonym of the class name with the same name).
In C, a typedef-name and a struct tag name declared in the same scope can have the same name (because they have different name spaces).
[Example 2: typedef struct name1 { /* ... */ } name1; // valid C and C++ struct name { /* ... */ }; typedef int name; // valid C, invalid C++ — end example]

Rationale: For ease of use, C++ doesn't require that a type name be prefixed with the keywords class, struct or union when used in object declarations or type casts.
[Example 3: class name { /* ... */ }; name i; // i has type class name — end example]

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
One of the 2 types has to be renamed.

How widely used: Seldom.
Affected subclause: [dcl.type] [see also [basic.link]]
Change: Const objects must be initialized in C++ but can be left uninitialized in C.
Rationale: A const object cannot be assigned to so it must be initialized to hold a useful value.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: Seldom.
Affected subclause: [dcl.spec.auto]
Change: The keyword auto cannot be used as a storage class specifier.
[Example 4: void f() { auto int x; // valid C, invalid C++ } — end example]

Rationale: Allowing the use of auto to deduce the type of a variable from its initializer results in undesired interpretations of auto as a storage class specifier in certain contexts.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Rare.
Affected subclause: [dcl.fct]
Change: In C++, a function declared with an empty parameter list takes no arguments.
In C, an empty parameter list means that the number and type of the function arguments are unknown.
[Example 5: int f(); // means int f(void) in C++ // int f( unknown ) in C — end example]

Rationale: This is to avoid function calls with the wrong number or type of arguments.

Effect on original feature: Change to semantics of well-defined feature.
This feature was marked as “obsolescent” in C.
Difficulty of converting: Syntactic transformation.
The function declarations using C incomplete declaration style must be completed to become full prototype declarations.
A program may need to be updated further if different calls to the same (non-prototype) function have different numbers of arguments or if the type of corresponding arguments differed.

How widely used: Common.
Affected subclause: [dcl.fct] [see [expr.sizeof]]
Change: In C++, types may not be defined in return or parameter types.
In C, these type definitions are allowed.
[Example 6: void f( struct S { int a; } arg ) {} // valid C, invalid C++ enum E { A, B, C } f() {} // valid C, invalid C++ — end example]

Rationale: When comparing types in different translation units, C++ relies on name equivalence when C relies on structural equivalence.
Regarding parameter types: since the type defined in a parameter list would be in the scope of the function, the only legal calls in C++ would be from within the function itself.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
The type definitions must be moved to file scope, or in header files.

How widely used: Seldom.
This style of type definition is seen as poor coding style.
Affected subclause: [dcl.fct.def]
Change: In C++, the syntax for function definition excludes the “old-style” C function.
In C, “old-style” syntax is allowed, but deprecated as “obsolescent”.

Rationale: Prototypes are essential to type safety.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Common in old programs, but already known to be obsolescent.
Affected subclause: [dcl.init.aggr]
Change: In C++, designated initialization support is restricted compared to the corresponding functionality in C.
In C++, designators for non-static data members must be specified in declaration order, designators for array elements and nested designators are not supported, and designated and non-designated initializers cannot be mixed in the same initializer list.
[Example 7: struct A { int x, y; }; struct B { struct A a; }; struct A a = {.y = 1, .x = 2}; // valid C, invalid C++ int arr[3] = {[1] = 5}; // valid C, invalid C++ struct B b = {.a.x = 0}; // valid C, invalid C++ struct A c = {.x = 1, 2}; // valid C, invalid C++ — end example]

Rationale: In C++, members are destroyed in reverse construction order and the elements of an initializer list are evaluated in lexical order, so member initializers must be specified in order.
Array designators conflict with lambda-expression syntax.
Nested designators are seldom used.

Effect on original feature: Deletion of feature that is incompatible with C++.

Difficulty of converting: Syntactic transformation.

How widely used: Out-of-order initializers are common.
The other features are seldom used.
Affected subclause: [dcl.init.string]
Change: In C++, when initializing an array of character with a string, the number of characters in the string (including the terminating '\0') must not exceed the number of elements in the array.
In C, an array can be initialized with a string even if the array is not large enough to contain the string-terminating '\0'.
[Example 8: char array[4] = "abcd"; // valid C, invalid C++ — end example]

Rationale: When these non-terminated arrays are manipulated by standard string functions, there is potential for major catastrophe.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
The arrays must be declared one element bigger to contain the string terminating '\0'.

How widely used: Seldom.
This style of array initialization is seen as poor coding style.
Affected subclause: [dcl.enum]
Change: C++ objects of enumeration type can only be assigned values of the same enumeration type.
In C, objects of enumeration type can be assigned values of any integral type.
[Example 9: enum color { red, blue, green }; enum color c = 1; // valid C, invalid C++ — end example]

Rationale: The type-safe nature of C++.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.
(The type error produced by the assignment can be automatically corrected by applying an explicit cast.)

How widely used: Common.
Affected subclause: [dcl.enum]
Change: In C++, the type of an enumerator is its enumeration.
In C, the type of an enumerator is int.
[Example 10: enum e { A }; sizeof(A) == sizeof(int) // in C sizeof(A) == sizeof(e) // in C++ /* and sizeof(int) is not necessarily equal to sizeof(e) */ — end example]

Rationale: In C++, an enumeration is a distinct type.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: Seldom.
The only time this affects existing C code is when the size of an enumerator is taken.
Taking the size of an enumerator is not a common C coding practice.
Affected subclause: [dcl.align]
Change: In C++, an alignment-specifier is an attribute-specifier.
In C, an alignment-specifier is a declaration-specifier.
[Example 11: #include <stdalign.h> unsigned alignas(8) int x; // valid C, invalid C++ unsigned int y alignas(8); // valid C++, invalid C — end example]

Rationale: C++ requires unambiguous placement of the alignment-specifier.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Syntactic transformation.

How widely used: Seldom.

C.7.7 [class]: classes [diff.class]

Affected subclause: [class.name] [see also [dcl.typedef]]
Change: In C++, a class declaration introduces the class name into the scope where it is declared and hides any object, function or other declaration of that name in an enclosing scope.
In C, an inner scope declaration of a struct tag name never hides the name of an object or function in an outer scope.
[Example 1: int x[99]; void f() { struct x { int a; }; sizeof(x); /* size of the array in C */ /* size of the struct in C++ */ } — end example]

Rationale: This is one of the few incompatibilities between C and C++ that can be attributed to the new C++ name space definition where a name can be declared as a type and as a non-type in a single scope causing the non-type name to hide the type name and requiring that the keywords class, struct, union or enum be used to refer to the type name.
This new name space definition provides important notational conveniences to C++ programmers and helps making the use of the user-defined types as similar as possible to the use of fundamental types.
The advantages of the new name space definition were judged to outweigh by far the incompatibility with C described above.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.
If the hidden name that needs to be accessed is at global scope, the ​::​ C++ operator can be used.
If the hidden name is at block scope, either the type or the struct tag has to be renamed.

How widely used: Seldom.
Affected subclause: [class.copy.ctor]
Change: Copying volatile objects.
The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile lvalue.
[Example 2: 
The following is valid in C: struct X { int i; }; volatile struct X x1 = {0}; struct X x2 = x1; // invalid C++ struct X x3; x3 = x1; // also invalid C++
— end example]

Rationale: Several alternatives were debated at length.
Changing the parameter to volatile const X& would greatly complicate the generation of efficient code for class objects.
Discussion of providing two alternative signatures for these implicitly-defined operations raised unanswered concerns about creating ambiguities and complicating the rules that specify the formation of these operators according to the bases and members.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
If volatile semantics are required for the copy, a user-declared constructor or assignment must be provided.
If non-volatile semantics are required, an explicit const_cast can be used.

How widely used: Seldom.
Affected subclause: [class.bit]
Change: Bit-fields of type plain int are signed.

Rationale: The signedness needs to be consistent among template specializations.
For consistency, the implementation freedom was eliminated for non-dependent types, too.

Effect on original feature: The choice is implementation-defined in C, but not so in C++.

Difficulty of converting: Syntactic transformation.

How widely used: Seldom.
Affected subclause: [class.nest]
Change: In C++, the name of a nested class is local to its enclosing class.
In C the name of the nested class belongs to the same scope as the name of the outermost enclosing class.
[Example 3: struct X { struct Y { /* ... */ } y; }; struct Y yy; // valid C, invalid C++ — end example]

Rationale: C++ classes have member functions which require that classes establish scopes.
The C rule would leave classes as an incomplete scope mechanism which would prevent C++ programmers from maintaining locality within a class.
A coherent set of scope rules for C++ based on the C rule would be very complicated and C++ programmers would be unable to predict reliably the meanings of nontrivial examples involving nested or local functions.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.
To make the struct type name visible in the scope of the enclosing struct, the struct tag can be declared in the scope of the enclosing struct, before the enclosing struct is defined.
[Example 4: struct Y; // struct Y and struct X are at the same scope struct X { struct Y { /* ... */ } y; }; — end example]
All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing struct can be exported to the scope of the enclosing struct.
Note: this is a consequence of the difference in scope rules, which is documented in [basic.scope].

How widely used: Seldom.
Affected subclause: [class.member.lookup]
Change: In C++, a typedef-name may not be redeclared in a class definition after being used in that definition.
[Example 5: typedef int I; struct S { I i; int I; // valid C, invalid C++ }; — end example]

Rationale: When classes become complicated, allowing such a redefinition after the type has been used can create confusion for C++ programmers as to what the meaning of I really is.

Effect on original feature: Deletion of semantically well-defined feature.

Difficulty of converting: Semantic transformation.
Either the type or the struct member has to be renamed.

How widely used: Seldom.

C.7.8 [cpp]: preprocessing directives [diff.cpp]

Affected subclause: [cpp.predefined]
Change: Whether __STDC__ is defined and if so, what its value is, are implementation-defined.

Rationale: C++ is not identical to C.
Mandating that __STDC__ be defined would require that translators make an incorrect claim.

Effect on original feature: Change to semantics of well-defined feature.

Difficulty of converting: Semantic transformation.

How widely used: Programs and headers that reference __STDC__ are quite common.

C.8 C standard library [diff.library]

C.8.1 General [diff.library.general]

Subclause [diff.library] summarizes the explicit changes in headers, definitions, declarations, or behavior between the C standard library in the C standard and the parts of the C++ standard library that were included from the C standard library.

C.8.2 Modifications to headers [diff.mods.to.headers]

For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in [support.c.headers].
There are no C++ headers for the C standard library's headers <stdnoreturn.h> and <threads.h>, nor are these headers from the C standard library headers themselves part of C++.
The C headers <complex.h> and <tgmath.h> do not contain any of the content from the C standard library and instead merely include other headers from the C++ standard library.

C.8.3 Modifications to definitions [diff.mods.to.definitions]

C.8.3.1 Types char16_t and char32_t [diff.char16]

The types char16_t and char32_t are distinct types rather than typedefs to existing integral types.
The tokens char16_t and char32_t are keywords in C++ ([lex.key]).
They do not appear as macro or type names defined in <cuchar>.

C.8.3.2 Type wchar_t [diff.wchar.t]

The type wchar_t is a distinct type rather than a typedef to an existing integral type.
The token wchar_t is a keyword in C++ ([lex.key]).
It does not appear as a macro or type name defined in any of <cstddef>, <cstdlib>, or <cwchar>.

C.8.3.3 Header <assert.h> [diff.header.assert.h]

The token static_assert is a keyword in C++.
It does not appear as a macro name defined in <cassert>.

C.8.3.4 Header <iso646.h> [diff.header.iso646.h]

The tokens and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, and xor_eq are keywords in C++ ([lex.key]), and are not introduced as macros by <iso646.h>.

C.8.3.5 Header <stdalign.h> [diff.header.stdalign.h]

The token alignas is a keyword in C++ ([lex.key]), and is not introduced as a macro by <stdalign.h>.

C.8.3.6 Header <stdbool.h> [diff.header.stdbool.h]

The tokens bool, true, and false are keywords in C++ ([lex.key]), and are not introduced as macros by <stdbool.h>.

C.8.3.7 Macro NULL [diff.null]

The macro NULL, defined in any of <clocale>, <cstddef>, <cstdio>, <cstdlib>, <cstring>, <ctime>, or <cwchar>, is an implementation-defined null pointer constant in C++ ([support.types]).

C.8.4 Modifications to declarations [diff.mods.to.declarations]

Header <cstring>: The following functions have different declarations:
Subclause [cstring.syn] describes the changes.
Header <cwchar>: The following functions have different declarations:
Subclause [cwchar.syn] describes the changes.
Header <cstddef> declares the names nullptr_t, byte, and to_integer, and the operators and operator templates in ([support.types.byteops]), in addition to the names declared in <stddef.h> in the C standard library.

C.8.5 Modifications to behavior [diff.mods.to.behavior]

C.8.5.1 General [diff.mods.to.behavior.general]

Header <cstdlib>: The following functions have different behavior:
Subclause [support.start.term] describes the changes.
Header <csetjmp>: The following functions have different behavior:
Subclause [csetjmp.syn] describes the changes.

C.8.5.2 Macro offsetof(type, member-designator) [diff.offsetof]

The macro offsetof, defined in <cstddef>, accepts a restricted set of type arguments in C++.
Subclause [support.types.layout] describes the change.

C.8.5.3 Memory allocation functions [diff.malloc]

The functions aligned_alloc, calloc, malloc, and realloc are restricted in C++.
Subclause [c.malloc] describes the changes.

Annex D (normative) Compatibility features [depr]

D.1 General [depr.general]

This Annex describes features of this document that are specified for compatibility with existing implementations.
These are deprecated features, where deprecated is defined as: Normative for the current revision of C++, but having been identified as a candidate for removal from future revisions.
An implementation may declare library names and entities described in this Clause with the deprecated attribute.

D.2 Non-local use of TU-local entities [depr.local]

A declaration of a non-TU-local entity that is an exposure ([basic.link]) is deprecated.
[Note 1: 
Such a declaration in an importable module unit is ill-formed.
— end note]
[Example 1: namespace { struct A { void f() {} }; } A h(); // deprecated: not internal linkage inline void g() {A().f();} // deprecated: inline and not internal linkage — end example]

D.3 Implicit capture of *this by reference [depr.capture.this]

For compatibility with prior revisions of C++, a lambda-expression with capture-default = ([expr.prim.lambda.capture]) may implicitly capture *this by reference.
[Example 1: struct X { int x; void foo(int n) { auto f = [=]() { x = n; }; // deprecated: x means this->x, not a copy thereof auto g = [=, this]() { x = n; }; // recommended replacement } }; — end example]

D.4 Deprecated volatile types [depr.volatile.type]

Postfix ++ and -- expressions ([expr.post.incr]) and prefix ++ and -- expressions ([expr.pre.incr]) of volatile-qualified arithmetic and pointer types are deprecated.
[Example 1: volatile int velociraptor; ++velociraptor; // deprecated — end example]
Certain assignments where the left operand is a volatile-qualified non-class type are deprecated; see [expr.ass].
[Example 2: int neck, tail; volatile int brachiosaur; brachiosaur = neck; // OK tail = brachiosaur; // OK tail = brachiosaur = neck; // deprecated brachiosaur += neck; // OK — end example]
A function type ([dcl.fct]) with a parameter with volatile-qualified type or with a volatile-qualified return type is deprecated.
[Example 3: volatile struct amber jurassic(); // deprecated void trex(volatile short left_arm, volatile short right_arm); // deprecated void fly(volatile struct pterosaur* pteranodon); // OK — end example]
A structured binding ([dcl.struct.bind]) of a volatile-qualified type is deprecated.
[Example 4: struct linhenykus { short forelimb; }; void park(linhenykus alvarezsauroid) { volatile auto [what_is_this] = alvarezsauroid; // deprecated // ... } — end example]

D.5 Non-comma-separated ellipsis parameters [depr.ellipsis.comma]

[Example 1: void f(int...); // deprecated void g(auto...); // OK, declares a function parameter pack void h(auto......); // deprecated — end example]

D.6 Implicit declaration of copy functions [depr.impldec]

The implicit definition of a copy constructor as defaulted is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.
The implicit definition of a copy assignment operator as defaulted is deprecated if the class has a user-declared copy constructor or a user-declared destructor.
It is possible that future versions of C++ will specify that these implicit definitions are deleted ([dcl.fct.def.delete]).

D.7 Redeclaration of static constexpr data members [depr.static.constexpr]

For compatibility with prior revisions of C++, a constexpr static data member may be redundantly redeclared outside the class with no initializer ([basic.def], [class.static.data]).
This usage is deprecated.
[Example 1: struct A { static constexpr int n = 5; // definition (declaration in C++ 2014) }; constexpr int A::n; // redundant declaration (definition in C++ 2014) — end example]

D.8 Literal operator function declarations using an identifier [depr.lit]

D.9 template keyword before qualified names [depr.template.template]

The use of the keyword template before the qualified name of a class or alias template without a template argument list is deprecated ([temp.names]).

D.10 has_denorm members in numeric_limits [depr.numeric.limits.has.denorm]

The following type is defined in addition to those specified in <limits>: namespace std { enum float_denorm_style { denorm_indeterminate = -1, denorm_absent = 0, denorm_present = 1 }; }
The following members are defined in addition to those specified in [numeric.limits.general]: static constexpr float_denorm_style has_denorm = denorm_absent; static constexpr bool has_denorm_loss = false;
The values of has_denorm and has_denorm_loss of specializations of numeric_limits are unspecified.
The following members of the specialization numeric_limits<bool> are defined in addition to those specified in [numeric.special]: static constexpr float_denorm_style has_denorm = denorm_absent; static constexpr bool has_denorm_loss = false;

D.11 Deprecated C macros [depr.c.macros]

The header <stdalign.h> has the following macros: #define __alignas_is_defined 1 #define __alignof_is_defined 1
The header <stdbool.h> has the following macro: #define __bool_true_false_are_defined 1

D.12 Deprecated error numbers [depr.cerrno]

The header <cerrno> has the following additional macros:
#define ENODATA see below #define ENOSR see below #define ENOSTR see below #define ETIME see below
The meaning of these macros is defined by the POSIX standard.
The following enum errc enumerators are defined in addition to those specified in [system.error.syn]:
no_message_available, // ENODATA no_stream_resources, // ENOSR not_a_stream, // ENOSTR stream_timeout, // ETIME
The value of each enum errc enumerator above is the same as the value of the <cerrno> macro shown in the above synopsis.

D.13 Deprecated type traits [depr.meta.types]

The header <type_traits> has the following addition: namespace std { template<class T> struct is_trivial; template<class T> constexpr bool is_trivial_v = is_trivial<T>::value; template<class T> struct is_pod; template<class T> constexpr bool is_pod_v = is_pod<T>::value; template<size_t Len, size_t Align = default-alignment> // see below struct aligned_storage; template<size_t Len, size_t Align = default-alignment> // see below using aligned_storage_t = typename aligned_storage<Len, Align>::type; template<size_t Len, class... Types> struct aligned_union; template<size_t Len, class... Types> using aligned_union_t = typename aligned_union<Len, Types...>::type; }
The behavior of a program that adds specializations for any of the templates defined in this subclause is undefined, unless explicitly permitted by the specification of the corresponding template.
A trivial class is a class that is trivially copyable and has one or more eligible default constructors, all of which are trivial.
[Note 1: 
In particular, a trivial class does not have virtual functions or virtual base classes.
— end note]
A trivial type is a scalar type, a trivial class, an array of such a type, or a cv-qualified version of one of these types.
A POD class is a class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD class (or array thereof).
A POD type is a scalar type, a POD class, an array of such a type, or a cv-qualified version of one of these types.
template<class T> struct is_trivial;
Preconditions: remove_all_extents_t<T> shall be a complete type or cv void.
Remarks: is_trivial<T> is a Cpp17UnaryTypeTrait ([meta.rqmts]) with a base characteristic of true_type if T is a trivial type, and false_type otherwise.
[Note 2: 
It is unspecified whether a closure type ([expr.prim.lambda.closure]) is a trivial type.
— end note]
template<class T> struct is_pod;
Preconditions: remove_all_extents_t<T> shall be a complete type or cv void.
Remarks: is_pod<T> is a Cpp17UnaryTypeTrait ([meta.rqmts]) with a base characteristic of true_type if T is a POD type, and false_type otherwise.
[Note 3: 
It is unspecified whether a closure type ([expr.prim.lambda.closure]) is a POD type.
— end note]
template<size_t Len, size_t Align = default-alignment> struct aligned_storage;
The value of default-alignment is the most stringent alignment requirement for any object type whose size is no greater than Len ([basic.types]).
Mandates: Len is not zero.
Align is equal to alignof(T) for some type T or to default-alignment.
The member typedef type denotes a trivial standard-layout type suitable for use as uninitialized storage for any object whose size is at most Len and whose alignment is a divisor of Align.
[Note 4: 
Uses of aligned_storage<Len, Align>​::​type can be replaced by an array std​::​byte[Len] declared with alignas(Align).
— end note]
[Note 5: 
A typical implementation would define aligned_storage as: template<size_t Len, size_t Alignment> struct aligned_storage { typedef struct { alignas(Alignment) unsigned char __data[Len]; } type; };
— end note]
template<size_t Len, class... Types> struct aligned_union;
Mandates: At least one type is provided.
Each type in the template parameter pack Types is a complete object type.
The member typedef type denotes a trivial standard-layout type suitable for use as uninitialized storage for any object whose type is listed in Types; its size shall be at least Len.
The static member alignment_value is an integral constant of type size_t whose value is the strictest alignment of all types listed in Types.

D.14 Relational operators [depr.relops]

The header <utility> has the following additions:
namespace std::rel_ops { template<class T> bool operator!=(const T&, const T&); template<class T> bool operator> (const T&, const T&); template<class T> bool operator<=(const T&, const T&); template<class T> bool operator>=(const T&, const T&); }
To avoid redundant definitions of operator!= out of operator== and operators >, <=, and >= out of operator<, the library provides the following:
template<class T> bool operator!=(const T& x, const T& y);
Preconditions: T meets the Cpp17EqualityComparable requirements (Table 28).
Returns: !(x == y).
template<class T> bool operator>(const T& x, const T& y);
Preconditions: T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: y < x.
template<class T> bool operator<=(const T& x, const T& y);
Preconditions: T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: !(y < x).
template<class T> bool operator>=(const T& x, const T& y);
Preconditions: T meets the Cpp17LessThanComparable requirements (Table 29).
Returns: !(x < y).

D.15 Tuple [depr.tuple]

The header <tuple> has the following additions: namespace std { template<class T> struct tuple_size<volatile T>; template<class T> struct tuple_size<const volatile T>; template<size_t I, class T> struct tuple_element<I, volatile T>; template<size_t I, class T> struct tuple_element<I, const volatile T>; }
template<class T> struct tuple_size<volatile T>; template<class T> struct tuple_size<const volatile T>;
Let TS denote tuple_size<T> of the cv-unqualified type T.
If the expression TS​::​value is well-formed when treated as an unevaluated operand, then specializations of each of the two templates meet the Cpp17TransformationTrait requirements with a base characteristic of integral_constant<size_t, TS​::​value>.
Otherwise, they have no member value.
Access checking is performed as if in a context unrelated to TS and T.
Only the validity of the immediate context of the expression is considered.
In addition to being available via inclusion of the <tuple> header, the two templates are available when any of the headers <array>, <ranges>, or <utility> are included.
template<size_t I, class T> struct tuple_element<I, volatile T>; template<size_t I, class T> struct tuple_element<I, const volatile T>;
Let TE denote tuple_element_t<I, T> of the cv-unqualified type T.
Then specializations of each of the two templates meet the Cpp17TransformationTrait requirements with a member typedef type that names the following type:
  • for the first specialization, add_volatile_t<TE>, and
  • for the second specialization, add_cv_t<TE>.
In addition to being available via inclusion of the <tuple> header, the two templates are available when any of the headers <array>, <ranges>, or <utility> are included.

D.16 Variant [depr.variant]

The header <variant> has the following additions: namespace std { template<class T> struct variant_size<volatile T>; template<class T> struct variant_size<const volatile T>; template<size_t I, class T> struct variant_alternative<I, volatile T>; template<size_t I, class T> struct variant_alternative<I, const volatile T>; }
template<class T> struct variant_size<volatile T>; template<class T> struct variant_size<const volatile T>;
Let VS denote variant_size<T> of the cv-unqualified type T.
Then specializations of each of the two templates meet the Cpp17UnaryTypeTrait requirements with a base characteristic of integral_constant<size_t, VS​::​value>.
template<size_t I, class T> struct variant_alternative<I, volatile T>; template<size_t I, class T> struct variant_alternative<I, const volatile T>;
Let VA denote variant_alternative<I, T> of the cv-unqualified type T.
Then specializations of each of the two templates meet the Cpp17TransformationTrait requirements with a member typedef type that names the following type:
  • for the first specialization, add_volatile_t<VA​::​type>, and
  • for the second specialization, add_cv_t<VA​::​type>.

D.17 Deprecated iterator class template [depr.iterator]

The header <iterator> has the following addition: namespace std { template<class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&> struct iterator { using iterator_category = Category; using value_type = T; using difference_type = Distance; using pointer = Pointer; using reference = Reference; }; }
The iterator template may be used as a base class to ease the definition of required types for new iterators.
[Note 1: 
If the new iterator type is a class template, then these aliases will not be visible from within the iterator class's template definition, but only to callers of that class.
— end note]
[Example 1: 
If a C++ program wants to define a bidirectional iterator for some data structure containing double and such that it works on a large memory model of the implementation, it can do so with: class MyIterator : public iterator<bidirectional_iterator_tag, double, long, T*, T&> { // code implementing ++, etc. };
— end example]

D.18 Deprecated move_iterator access [depr.move.iter.elem]

The following member is declared in addition to those members specified in [move.iter.elem]: namespace std { template<class Iterator> class move_iterator { public: constexpr pointer operator->() const; }; }
constexpr pointer operator->() const;
Returns: current.

D.19 Deprecated locale category facets [depr.locale.category]

The ctype locale category includes the following facets as if they were specified in table Table 86 of [locale.category].
codecvt<char16_t, char, mbstate_t> codecvt<char32_t, char, mbstate_t> codecvt<char16_t, char8_t, mbstate_t> codecvt<char32_t, char8_t, mbstate_t>
The ctype locale category includes the following facets as if they were specified in table Table 87 of [locale.category].
codecvt_byname<char16_t, char, mbstate_t> codecvt_byname<char32_t, char, mbstate_t> codecvt_byname<char16_t, char8_t, mbstate_t> codecvt_byname<char32_t, char8_t, mbstate_t>
The following class template specializations are required in addition to those specified in [locale.codecvt].
The specializations codecvt<char16_t, char, mbstate_t> and codecvt<char16_t, char8_t, mbstate_t> convert between the UTF-16 and UTF-8 encoding forms, and the specializations codecvt<char32_t, char, mbstate_t> and codecvt<char32_t, char8_t, mbstate_t> convert between the UTF-32 and UTF-8 encoding forms.

D.20 Deprecated formatting [depr.format]

D.20.1 Header <format> synopsis [depr.format.syn]

The header <format> has the following additions:
namespace std { template<class Visitor, class Context> decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg); }

D.20.2 Formatting arguments [depr.format.arg]

template<class Visitor, class Context> decltype(auto) visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
Effects: Equivalent to: return visit(std​::​forward<Visitor>(vis), arg.value);

D.21 Deprecated filesystem path factory functions [depr.fs.path.factory]

The header <filesystem> has the following additions:
template<class Source> path u8path(const Source& source); template<class InputIterator> path u8path(InputIterator first, InputIterator last);
Mandates: The value type of Source and InputIterator is char or char8_t.
Preconditions: The source and [first, last) sequences are UTF-8 encoded.
Source meets the requirements specified in [fs.path.req].
Returns:
  • If path​::​value_type is char and the current native narrow encoding ([fs.path.type.cvt]) is UTF-8, return path(source) or path(first, last); otherwise,
  • if path​::​value_type is wchar_t and the native wide encoding is UTF-16, or if path​::​value_type is char16_t or char32_t, convert source or [first, last) to a temporary, tmp, of type path​::​string_type and return path(tmp); otherwise,
  • convert source or [first, last) to a temporary, tmp, of type u32string and return path(tmp).
Remarks: Argument format conversion ([fs.path.fmt.cvt]) applies to the arguments for these functions.
How Unicode encoding conversions are performed is unspecified.
[Example 1: 
A string is to be read from a database that is encoded in UTF-8, and used to create a directory using the native encoding for filenames: namespace fs = std::filesystem; std::string utf8_string = read_utf8_data(); fs::create_directory(fs::u8path(utf8_string));
For POSIX-based operating systems with the native narrow encoding set to UTF-8, no encoding or type conversion occurs.
For POSIX-based operating systems with the native narrow encoding not set to UTF-8, a conversion to UTF-32 occurs, followed by a conversion to the current native narrow encoding.
Some Unicode characters may have no native character set representation.
For Windows-based operating systems a conversion from UTF-8 to UTF-16 occurs.
— end example]
[Note 1: 
The example above is representative of a historical use of filesystem​::​u8path.
To indicate a UTF-8 encoding, passing a std​::​u8string to path's constructor is preferred as it is consistent with path's handling of other encodings.
— end note]

D.22 Deprecated atomic operations [depr.atomics]

D.22.1 General [depr.atomics.general]

The header <atomic> has the following additions.
namespace std { template<class T> void atomic_init(volatile atomic<T>*, typename atomic<T>::value_type) noexcept; template<class T> void atomic_init(atomic<T>*, typename atomic<T>::value_type) noexcept; #define ATOMIC_VAR_INIT(value) see below }

D.22.2 Volatile access [depr.atomics.volatile]

If an atomic ([atomics.types.generic]) specialization has one of the following overloads, then that overload participates in overload resolution even if atomic<T>​::​is_always_lock_free is false: void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; T operator=(T desired) volatile noexcept; T load(memory_order order = memory_order::seq_cst) const volatile noexcept; operator T() const volatile noexcept; T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept; bool compare_exchange_weak(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) volatile noexcept; bool compare_exchange_weak(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) volatile noexcept; T fetch_key(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; T operator op=(T operand) volatile noexcept; T* fetch_key(ptrdiff_t operand, memory_order order = memory_order::seq_cst) volatile noexcept;

D.22.3 Non-member functions [depr.atomics.nonmembers]

template<class T> void atomic_init(volatile atomic<T>* object, typename atomic<T>::value_type desired) noexcept; template<class T> void atomic_init(atomic<T>* object, typename atomic<T>::value_type desired) noexcept;
Effects: Equivalent to: atomic_store_explicit(object, desired, memory_order​::​relaxed);

D.22.4 Operations on atomic types [depr.atomics.types.operations]

#define ATOMIC_VAR_INIT(value) see below
The macro expands to a token sequence suitable for constant initialization of an atomic variable of static storage duration of a type that is initialization-compatible with value.
[Note 1: 
This operation possibly needs to initialize locks.
— end note]
Concurrent access to the variable being initialized, even via an atomic operation, constitutes a data race.
[Example 1: atomic<int> v = ATOMIC_VAR_INIT(5); — end example]

Annex E (informative) Conformance with UAX #31 [uaxid]

E.1 General [uaxid.general]

This Annex describes the choices made in application of UAX #31 (“Unicode Identifier and Pattern Syntax”) to C++ in terms of the requirements from UAX #31 and how they do or do not apply to this document.
In terms of UAX #31, this document conforms by meeting the requirements R1 “Default Identifiers” and R4 “Equivalent Normalized Identifiers” from UAX #31.
The other requirements from UAX #31, also listed below, are either alternatives not taken or do not apply to this document.

E.2 R1 Default identifiers [uaxid.def]

E.2.1 General [uaxid.def.general]

UAX #31 specifies a default syntax for identifiers based on properties from the Unicode Character Database, UAX #44.
The general syntax is
<Identifier> := <Start> <Continue>* (<Medial> <Continue>+)*
where <Start> has the XID_Start property, <Continue> has the XID_Continue property, and <Medial> is a list of characters permitted between continue characters.
For C++ we add the character U+005f low line, or _, to the set of permitted <Start> characters, the <Medial> set is empty, and the <Continue> characters are unmodified.
In the grammar used in UAX #31, this is
<Identifier> := <Start> <Continue>*
<Start> := XID_Start + U+005f
<Continue> := <Start> + XID_Continue
This is described in the C++ grammar in [lex.name], where identifier is formed from identifier-start or identifier followed by identifier-continue.

E.2.2 R1a Restricted format characters [uaxid.def.rfmt]

If an implementation of UAX #31 wishes to allow format characters such as U+200d zero width joiner or U+200c zero width non-joiner it must define a profile allowing them, or describe precisely which combinations are permitted.
C++ does not allow format characters in identifiers, so this does not apply.

E.2.3 R1b Stable identifiers [uaxid.def.stable]

An implementation of UAX #31 may choose to guarantee that identifiers are stable across versions of the Unicode Standard.
Once a string qualifies as an identifier it does so in all future versions.
C++ does not make this guarantee, except to the extent that UAX #31 guarantees the stability of the XID_Start and XID_Continue properties.

E.3 R2 Immutable identifiers [uaxid.immutable]

An implementation may choose to guarantee that the set of identifiers will never change by fixing the set of code points allowed in identifiers forever.
C++ does not choose to make this guarantee.
As scripts are added to Unicode, additional characters in those scripts may become available for use in identifiers.

E.4 R3 Pattern_White_Space and Pattern_Syntax characters [uaxid.pattern]

UAX #31 describes how formal languages such as computer languages should describe and implement their use of whitespace and syntactically significant characters during the processes of lexing and parsing.
This document does not claim conformance with this requirement from UAX #31.

E.5 R4 Equivalent normalized identifiers [uaxid.eqn]

UAX #31 requires that implementations describe how identifiers are compared and considered equivalent.
This document requires that identifiers be in Normalization Form C and therefore identifiers that compare the same under NFC are equivalent.
This is described in [lex.name].

E.6 R5 Equivalent case-insensitive identifiers [uaxid.eqci]

This document considers case to be significant in identifier comparison, and does not do any case folding.
This requirement from UAX #31 does not apply to this document.

E.7 R6 Filtered normalized identifiers [uaxid.filter]

If any characters are excluded from normalization, UAX #31 requires a precise specification of those exclusions.
This document does not make any such exclusions.

E.8 R7 Filtered case-insensitive identifiers [uaxid.filterci]

C++ identifiers are case sensitive, and therefore this requirement from UAX #31 does not apply.

E.9 R8 Hashtag identifiers [uaxid.hashtag]

There are no hashtags in C++, so this requirement from UAX #31 does not apply.

Bibliography

  • ISO 4217:2015, Codes for the representation of currencies
  • ISO/IEC 10967-1:2012, Information technology — Language independent arithmetic — Part 1: Integer and floating point arithmetic
  • ISO/IEC 14882:2023, Programming Languages — C++
  • ISO/IEC 14882:2020, Programming Languages — C++
  • ISO/IEC 14882:2017, Programming Languages — C++
  • ISO/IEC 14882:2014, Information technology — Programming Languages — C++
  • ISO/IEC 14882:2011, Information technology — Programming Languages — C++
  • ISO/IEC 14882:2003, Programming Languages — C++
  • ISO/IEC TS 18661-3:2015, Information Technology — Programming languages, their environments, and system software interfaces — Floating-point extensions for C — Part 3: Interchange and extended types
  • IANA Character Sets Database.
  • IANA Time Zone Database.
  • Unicode Character Mapping Markup Language [online].
    Edited by Mark Davis and Markus Scherer.
    Revision 5.0.1; 2017-05-31 Available from: https://www.unicode.org/reports/tr22/tr22-8.html
  • Bjarne Stroustrup, The C++ Programming Language, second edition, Chapter R.
    Addison-Wesley Publishing Company, ISBN 0-201-53992-6, copyright ©1991 AT&T
  • Brian W. Kernighan and Dennis M. Ritchie, The C Programming Language, Appendix A.
    Prentice-Hall, 1978, ISBN 0-13-110163-3, copyright ©1978 AT&T
  • P.J. Plauger, The Draft Standard C++ Library.
    Prentice-Hall, ISBN 0-13-117003-1, copyright ©1995 P.J. Plauger
  • J. Demmel, I. Dumitriu, and O. Holtz, Fast linear algebra is stable, Numerische Mathematik 108 (59–91), 2007.
  • C.L. Lawson, R.J. Hanson, D. Kincaid, and F.T. Krogh, Basic linear algebra subprograms for Fortran usage.
    ACM Trans. Math. Soft., Vol. 5, pp. 308–323, 1979.
  • Jack J. Dongarra, Jeremy Du Croz, Sven Hammarling, and Richard J. Hanson, An Extended Set of FORTRAN Basic Linear Algebra Subprograms.
    ACM Trans. Math. Soft., Vol. 14, No. 1, pp. 1–17, Mar. 1988.
  • Jack J. Dongarra, Jeremy Du Croz, Sven Hammarling, and Iain Duff, A Set of Level 3 Basic Linear Algebra Subprograms.
    ACM Trans. Math. Soft., Vol. 16, No. 1, pp. 1–17, Mar. 1990.
  • E. Anderson, Z. Bai, C. Bischof, S. Blackford, J. Demmel, J. Dongarra, J. Du Croz, A. Greenbaum, S. Hammarling, A. McKenney, and D. Sorensen, LAPACK Users' Guide, Third Edition.
    SIAM, Philadelphia, PA, USA, 1999.
  • L. Susan Blackford, James Demmel, Jack Dongarra, Iain Duff, Sven Hammarling, Greg Henry, Michael Heroux, Linda Kaufman, Andrew Lumbsdaine, Antoine Petitet, Roldan Pozo, Karin Remington, and R. Client Whaley, An Updated Set of Basic Linear Algebra Subprograms (BLAS).
    ACM Trans. Math. Soft., Vol. 28, Issue 2, 2002.
  • Michael J. Flynn, Very High-Speed Computing Systems.
    Proceedings of the IEEE, Vol. 54, Issue 12, 1966.