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 ([basic.types.general]) can be used to access objects.
Reads of scalar objects are described in [conv.lval] and modifications of scalar objects are described in [expr.assign], [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 or braced-init-list 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]),
    • an occurrence of a construct described in this document as “conditionally-supported” when the implementation does not support that construct, or
    • a contract assertion ([basic.contract.eval]) evaluated with a checking semantic in a manifestly constant-evaluated context ([expr.const]) resulting in a contract violation,
    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]).
An implementation is either a hosted implementation or 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].
It is implementation-defined whether the implementation is a hardened implementation.
If it is a hardened implementation, violating a hardened precondition results in a contract violation ([structure.specifications]).
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).
Certain events in the execution of a program are termed observable checkpoints.
[Note 1: 
A call to std​::​observable ([utility.undefined]) is an observable checkpoint, as are certain parts of the evaluation of contract assertions ([basic.contract]).
— end note]
The defined prefix of an execution comprises the operations O for which for every undefined operation U there is an observable checkpoint C such that O happens before C and C happens before U.
[Note 2: 
The undefined behavior that arises from a data race ([intro.races]) occurs on all participating threads.
— end note]
A conforming implementation executing a well-formed program shall produce the observable behavior of the defined prefix of one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input.
If the selected execution contains an undefined operation, the implementation executing that program with that input may produce arbitrary additional observable behavior afterwards.
If the execution contains an operation specified as having erroneous behavior, 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 3: 
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 following specify the observable behavior of the program:
  • Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
  • Data is delivered to the host environment to be written into files (See also: ISO/IEC 9899:2018, 7.21.3).
    [Note 4: 
    Delivering such data is followed by an observable checkpoint ([cstdio.syn]).
    Not all host environments provide access to file contents before program termination.
    — end note]
  • 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.
[Note 5: 
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 ([lex.header], [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 preprocessing tokens, a common encoding-prefix is determined as specified in [lex.string].
Each such string-literal preprocessing token is then considered to have that common encoding-prefix.
6.
Adjacent string-literal preprocessing 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
post
replaceable_if_eligible
override
module
pre
trivially_relocatable_if_eligible
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
extern
protected
throw
alignof
const_cast
false
public
true
asm
continue
float
register
try
auto
contract_assert
for
reinterpret_cast
typedef
bool
co_await
friend
requires
typeid
break
co_return
goto
return
typename
case
co_yield
if
short
union
catch
decltype
inline
signed
unsigned
char
default
int
sizeof
using
char8_t
delete
long
static
virtual
char16_t
do
mutable
static_assert
void
char32_t
double
namespace
static_cast
volatile
class
dynamic_cast
new
struct
wchar_t
concept
else
noexcept
switch
while
const
enum
nullptr
template
consteval
explicit
operator
this
constexpr
export
private
thread_local
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 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:
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 that would result from an evaluation of the string-literal (see 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 constant 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]
Two names are the same if
[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]
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.
An entity is a value, object, reference, structured binding, result binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
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 local entity is a variable with automatic storage duration ([basic.stc.auto]), a structured binding ([dcl.struct.bind]) whose corresponding variable is such an entity, a result binding ([dcl.contract.res]), or the *this object ([expr.prim.this]).
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 ([dcl]) 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]); otherwise, it is a first declaration.
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 specializations ([temp.spec.partial.match]), 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, handler, or contract assertion (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 result-name-introducer ([dcl.contract.res]) is immediately after it.
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-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.4.10 Contract-assertion scope [basic.scope.contract]

Each contract assertion ([basic.contract]) C introduces a contract-assertion scope that includes C.
If a result-name-introducer ([dcl.contract.res]) that is not name-independent ([basic.scope.scope]) and whose enclosing postcondition assertion is associated with a function F potentially conflicts with a declaration whose target scope is the program is ill-formed.

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 type 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 type 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 type template template arguments; and the classes of which any member templates used as type template template arguments are members.
    [Note 2: 
    Constant template arguments, variable template template arguments, and concept 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.assign]).
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.assign]) 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 ([dcl.fct.def.replace]).
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 ([basic.stc.static]), for objects or references with thread storage duration ([basic.stc.thread]), for objects of type std​::​type_info ([expr.typeid]), for an object of type std​::​contracts​::​contract_violation when a contract violation occurs ([basic.contract.eval]), or for an exception object ([except.throw]).
— 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 suitable 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 is
  • a scalar type or
  • a class type that has at least one eligible copy or move constructor ([special]), where each such constructor is trivial, and the destructor of X is either trivial or deleted,
implementations are permitted to create temporary objects to hold the function parameter or result object, as follows:
  • The first such temporary object is constructed from the function argument or return value, respectively.
  • Each successive temporary object is initialized from the previous one as if by direct-initialization if X is a scalar type, otherwise by using an eligible trivial constructor.
  • The function parameter or return object is initialized from the final temporary as if by direct-initialization if X is a scalar type, otherwise by using an eligible trivial constructor.
(In all cases, the eligible constructor is used 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 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, trivially relocatable class types ([class.prop]), arrays of such types, and cv-qualified versions of these types are collectively called trivially relocatable types.
Cv-unqualified scalar types, replaceable class types ([class.prop]), and arrays of such types are collectively called replaceable 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-variant non-static 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 declared 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 declared 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 declared 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 declared 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 declared 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 declared 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 analogous _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 f (whether or not the function is inline), every argument expression and the postfix expression designating f are sequenced before every precondition assertion of f ([dcl.contract.func]), which in turn are sequenced before every expression or statement in the body of f, which in turn are sequenced before every postcondition assertion of f.
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 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 happens before an evaluation B (or, equivalently, B happens after A) if either
  • A is sequenced before B, or
  • A synchronizes with B, or
  • A happens before X and X happens before B.
[Note 7: 
An evaluation does not happen before itself.
— 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 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 8: 
Informally, if A strongly happens before B, then A appears to be evaluated before B in all contexts.
— 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 9: 
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 10: 
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 11: 
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 12: 
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 13: 
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 14: 
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 15: 
This requirement is known as write-read coherence.
— end note]
[Note 16: 
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 17: 
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 18: 
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 non-bit-field 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 19: 
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 20: 
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 evaluating any postcondition assertions of main) 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().

6.10 Contract assertions [basic.contract]

6.10.1 General [basic.contract.general]

Contract assertions allow the programmer to specify properties of the state of the program that are expected to hold at certain points during execution.
Each contract assertion has a contract-assertion predicate, which is an expression of type bool.
[Note 1: 
The value of the predicate is used to identify program states that are expected.
— end note]
An invocation of the macro va_start ([cstdarg.syn]) shall not be a subexpression of the predicate of a contract assertion, no diagnostic required.
[Note 2: 
Within the predicate of a contract assertion, id-expressions referring to variables declared outside the contract assertion are const ([expr.prim.id.unqual]), this is a pointer to const ([expr.prim.this]), and the result object can be named if a result-name-introducer ([dcl.contract.res]) has been specified.
— end note]

6.10.2 Evaluation [basic.contract.eval]

An evaluation of a contract assertion uses one of the following four evaluation semantics: ignore, observe, enforce, or quick-enforce.
Observe, enforce, and quick-enforce are checking semantics; enforce and quick-enforce are terminating semantics.
It is implementation-defined which evaluation semantic is used for any given evaluation of a contract assertion.
[Note 1: 
The range and flexibility of available choices of evaluation semantics depends on the implementation and need not allow all four evaluation semantics as possibilities.
The evaluation semantics can differ for different evaluations of the same contract assertion, including evaluations during constant evaluation.
— end note]
Recommended practice: An implementation should provide the option to translate a program such that all evaluations of contract assertions use the ignore semantic as well as the option to translate a program such that all evaluations of contract assertions use the enforce semantic.
By default, evaluations of contract assertions should use the enforce semantic.
The evaluation of a contract assertion using the ignore semantic has no effect.
[Note 2: 
The predicate is potentially evaluated ([basic.def.odr]), but not evaluated.
— end note]
The evaluation A of a contract assertion using a checking semantic determines the value of the predicate.
It is unspecified whether the predicate is evaluated.
Let B be the value that would result from evaluating the predicate.
[Note 3: 
To determine whether a predicate would evaluate to true or false, an alternative evaluation that produces the same value as the predicate but has no side effects can occur.
[Example 1: struct S { mutable int g = 5; } s; void f() pre(( s.g++, false )); // #1 void g() { f(); // Increment of s.g might not occur, even if #1 uses a checking semantic. } — end example]
— end note]
There is an observable checkpoint ([intro.abstract]) C that happens before A such that any other operation O that happens before A also happens before C.
A contract violation occurs when
  • B is false,
  • the evaluation of the predicate exits via an exception, or
  • the evaluation of the predicate is performed in a context that is manifestly constant-evaluated ([expr.const]) and the predicate is not a core constant expression.
[Note 4: 
If B is true, no contract violation occurs and control flow continues normally after the point of evaluation of the contract assertion.
The evaluation of the predicate can fail to produce a value without causing a contract violation, for example, by calling longjmp ([csetjmp.syn]) or terminating the program.
— end note]
If a contract violation occurs in a context that is manifestly constant-evaluated ([expr.const]), and the evaluation semantic is a terminating semantic, the program is ill-formed.
[Note 5: 
A diagnostic is produced if the evaluation semantic is observe ([intro.compliance]).
— end note]
[Note 6: 
Different evaluation semantics chosen for the same contract assertion in different translation units can result in violations of the one-definition rule ([basic.def.odr]) when a contract assertion has side effects that alter the value produced by a constant expression.
[Example 2: constexpr int f(int i) { contract_assert((++const_cast<int&>(i), true)); return i; } inline void g() { int a[f(1)]; // size dependent on the evaluation semantic of contract_assert above } — end example]
— end note]
When the program is contract-terminated, it is implementation-defined (depending on context) whether
  • std​::​terminate is called,
  • std​::​abort is called, or
  • execution is terminated.
    [Note 7: 
    No further execution steps occur ([intro.progress]).
    — end note]
[Note 8: 
Performing the actions of std​::​terminate or std​::​abort without actually making a library call is a conforming implementation of contract-termination ([intro.abstract]).
— end note]
If a contract violation occurs in a context that is not manifestly constant-evaluated and the evaluation semantic is quick-enforce, the program is contract-terminated.
If a contract violation occurs in a context that is not manifestly constant-evaluated and the evaluation semantic is enforce or observe, the contract-violation handler ([basic.contract.handler]) is invoked with an lvalue referring to an object v of type const std​::​contracts​::​contract_violation ([support.contract.violation]) containing information about the contract violation.
Storage for v is allocated in an unspecified manner except as noted in [basic.stc.dynamic.allocation].
The lifetime of v persists for the duration of the invocation of the contract-violation handler.
If the contract violation occurred because the evaluation of the predicate exited via an exception, the contract-violation handler is invoked from within an active implicit handler for that exception ([except.handle]).
If the contract-violation handler returns normally and the evaluation semantic is observe, that implicit handler is no longer considered active.
[Note 9: 
The exception can be inspected or rethrown within the contract-violation handler.
— end note]
If the contract-violation handler returns normally and the evaluation semantic is enforce, the program is contract-terminated; if violation occurred as the result of an uncaught exception from the evaluation of the predicate, the implicit handler remains active when contract termination occurs.
[Note 10: 
If the contract-violation handler returns normally and the evaluation semantic is observe, control flow continues normally after the point of evaluation of the contract assertion.
— end note]
There is an observable checkpoint ([intro.abstract]) C that happens after the contract-violation handler returns normally such that any other operation O that happens after the contract-violation handler returns also happens after C.
[Note 11: 
The terminating semantics terminate the program if execution would otherwise continue normally past a contract violation: the enforce semantic provides the opportunity to log information about the contract violation before terminating the program or to throw an exception to avoid termination, and the quick-enforce semantic is intended to terminate the program as soon as possible as well as to minimize the impact of contract checks on the generated code size.
Conversely, the observe semantic provides the opportunity to log information about the contract violation without having to terminate the program.
— end note]
If a contract-violation handler invoked from the evaluation of a function contract assertion ([dcl.contract.func]) exits via an exception, the behavior is as if the function body exits via that same exception.
[Note 12: 
A function-try-block ([except.pre]) is the function body when present and thus does not have an opportunity to catch the exception.
If the function has a non-throwing exception specification, the function std​::​terminate is invoked ([except.terminate]).
— end note]
[Note 13: 
If a contract-violation handler invoked from an assertion-statement ([stmt.contract.assert])) exits via an exception, the search for a handler continues from the execution of that statement.
— end note]
To evaluate in sequence a list R of contract assertions:
  • Construct a list of contract assertions S such that
    • all elements of R are in S,
    • each element of R may be repeated an implementation-defined number of times within S, and
    • if a contract assertion A precedes another contract assertion B in R, then the first occurrence of A precedes the first occurrence of B in S.
  • Evaluate each element of S such that, if a contract assertion A precedes a contract assertion B in S, then the evaluation of A is sequenced before the evaluation of B.
[Example 3: void f(int i) { contract_assert(i > 0); // #1 contract_assert(i < 10); // #2 // valid sequence of evaluations: #1 #2 // valid sequence of evaluations: #1 #1 #2 #2 // valid sequence of evaluations: #1 #2 #1 #2 // valid sequence of evaluations: #1 #2 #2 #1 // invalid sequence of evaluations: #2 #1 } — end example]
Recommended practice: An implementation should provide an option to perform a specified number of repeated evaluations for contract assertions.
By default, no repeated evaluations should be performed.

6.10.3 Contract-violation handler [basic.contract.handler]

The contract-violation handler of a program is a function named ​::​handle_contract_violation.
The contract-violation handler shall have a single parameter of type “lvalue reference to const std​::​contracts​::​contract_violation” and shall return void.
The contract-violation handler may have a non-throwing exception specification.
The implementation shall provide a definition of the contract-violation handler, called the default contract-violation handler.
[Note 1: 
No declaration for the default contract-violation handler is provided by any standard library header.
— end note]
Recommended practice: The default contract-violation handler should produce diagnostic output that suitably formats the most relevant contents of the std​::​contracts​::​contract_violation object, rate-limited for potentially repeated violations of observed contract assertions, and then return normally.
It is implementation-defined whether the contract-violation handler is replaceable ([dcl.fct.def.replace]).
If the contract-violation handler is not replaceable, a declaration of a replacement function for the contract-violation handler is ill-formed, no diagnostic required.

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.assign].

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 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 object 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 that is not the result of the lvalue-to-rvalue conversion ([conv.lval]) appears as an operand of an operator, 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.assign], [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.compound]), 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 the expression this appears within the predicate of a contract assertion ([basic.contract.general]) (including as the result of an implicit transformation ([expr.prim.id.general]) and including in the bodies of nested lambda-expressions) and the current class encloses the contract assertion, const is combined with the cv-qualifier-seq used to generate the resulting type (see below).
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.
If this transformation occurs in the predicate of a precondition assertion of a constructor of X or a postcondition assertion of a destructor of X, the expression is ill-formed.
[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]).
[Example 1: struct C { bool b; C() pre(b) // error pre(&this->b) // OK pre(sizeof(b) > 0); // OK, b is not potentially evaluated. }; — end example]
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 2: 
    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 3: 
    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 4: 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 5: 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]) or if it appears as part of a declarator-id ([dcl.decl]).
[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 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 the unqualified-id names a coroutine parameter, the type of the expression is that of the copy of the parameter ([dcl.fct.def.coroutine]), and the result is that copy.
Otherwise, if the unqualified-id names a result binding ([dcl.contract.res]) attached to a function f with return type U,
  • if U is “reference to T”, then the type of the expression is const T;
  • otherwise, the type of the expression is const U.
Otherwise, if the unqualified-id appears in the predicate of a contract assertion C ([basic.contract]) and the entity is
  • a variable declared outside of C of object type T,
  • a variable or template parameter declared outside of C of type “reference to T”, or
  • a structured binding of type T whose corresponding variable is declared outside of C,
then the type of the expression is const T.
[Example 1: int n = 0; struct X { bool m(); }; struct Y { int z = 0; void f(int i, int* p, int& r, X x, X* px) pre (++n) // error: attempting to modify const lvalue pre (++i) // error: attempting to modify const lvalue pre (++(*p)) // OK pre (++r) // error: attempting to modify const lvalue pre (x.m()) // error: calling non-const member function pre (px->m()) // OK pre ([=,&i,*this] mutable { ++n; // error: attempting to modify const lvalue ++i; // error: attempting to modify const lvalue ++p; // OK, refers to member of closure type ++r; // OK, refers to non-reference member of closure type ++this->z; // OK, captured *this ++z; // OK, captured *this int j = 17; [&]{ int k = 34; ++i; // error: attempting to modify const lvalue ++j; // OK ++k; // OK }(); return true; }()); template <int N, int& R, int* P> void g() pre(++N) // error: attempting to modify prvalue pre(++R) // error: attempting to modify const lvalue pre(++(*P)); // OK int h() post(r : ++r) // error: attempting to modify const lvalue post(r: [=] mutable { ++r; // OK, refers to member of closure type return true; }()); int& k() post(r : ++r); // error: attempting to modify const lvalue }; — end example]
Otherwise, 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 ([dcl.struct.bind]), result binding ([dcl.contract.res]), data member, or template parameter object; and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.
If an id-expression E appears in the predicate of a function contract assertion attached to a function f and denotes a function parameter of f and the implementation introduces any temporary objects to hold the value of that parameter as specified in [class.temporary],
  • if the contract assertion is a precondition assertion and the evaluation of the precondition assertion is sequenced before the initialization of the parameter object, E refers to the most recently initialized such temporary object, and
  • if the contract assertion is a postcondition assertion, it is unspecified whether E refers to one of the temporary objects or the parameter object; the choice is consistent within a single evaluation of a postcondition assertion.
If an id-expression E names a result binding in a postcondition assertion and the implementation introduces any temporary objects to hold the result object as specified in [class.temporary], and the postcondition assertion is sequenced before the initialization of the result object ([expr.call]), E refers to the most recently initialized such temporary object.
[Example 2: 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 with automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type.
An id-expression is move-eligible if

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]).
If Q appears in the predicate of a contract assertion C ([basic.contract]) and the entity is
  • a variable declared outside of C of object type T,
  • a variable declared outside of C of type “reference to T”, or
  • a structured binding of type T whose corresponding variable is declared outside of C,
then the type of the expression is const T.
Otherwise, 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 or function-contract-specifier ([dcl.contract.func]) 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]
If all potential references to a local entity implicitly captured by a lambda-expression L occur within the function contract assertions ([dcl.contract.func]) of the call operator or operator template of L or within assertion-statements ([stmt.contract.assert]) within the body of L, the program is ill-formed.
[Note 4: 
Adding a contract assertion to an existing C++ program cannot cause additional captures.
— end note]
[Example 6: static int i = 0; void test() { auto f1 = [=] pre(i > 0) {}; // OK, no local entities are captured. int i = 1; auto f2 = [=] pre(i > 0) {}; // error: cannot implicitly capture i here auto f3 = [i] pre(i > 0) {}; // OK, i is captured explicitly. auto f4 = [=] { contract_assert(i > 0); // error: cannot implicitly capture i here }; auto f5 = [=] { contract_assert(i > 0); // OK, i is referenced elsewhere. (void)i; }; auto f6 = [=] pre( // #1 []{ bool x = true; return [=]{ return x; }(); // OK, #1 captures nothing. }()) {}; bool y = true; auto f7 = [=] pre([=]{ return y; }()); // error: outer capture of y is invalid. } — end example]
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 5: 
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 7: 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 6: 
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 8: 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 9: 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 10: 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 7: 
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 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
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 ([dcl.fct]) of any applicable subscript operator function ([over.sub]) is sequenced before each expression in the expression-list and also before any default argument ([dcl.fct.default]).
The initialization of a non-object parameter of a subscript operator function S, 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, and each precondition assertion of the function is evaluated.
([dcl.contract.func]) 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], [expr.await]) 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 or, if the implementation introduces any temporary objects to hold the values of function parameters ([class.temporary]), the initialization of those temporaries, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.
These evaluations are sequenced before the evaluation of the precondition assertions of the function, which are evaluated in sequence ([dcl.contract.func]).
For any temporaries introduced to hold the values of function parameters, the initialization of the parameter objects from those temporaries is indeterminately sequenced with respect to the evaluation of each precondition assertion.
[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.
When the called function exits normally ([stmt.return], [expr.await]), all postcondition assertions of the function are evaluated in sequence ([dcl.contract.func]).
If the implementation introduces any temporary objects to hold the result value as specified in [class.temporary], the evaluation of each postcondition assertion is indeterminately sequenced with respect to the initialization of any of those temporaries or the result object.
These evaluations, in turn, are sequenced before the destruction of any function parameters.
[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 ([support.runtime]).
[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.assign]).
[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.
An await-expression shall not be a potentially-evaluated subexpression of the predicate of a contract assertion ([basic.contract]).
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 typedef-name std​::​size_t is declared 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 typedef-name std​::​size_t is declared 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 named by 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.assign]

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.assign], [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 with all contract assertions using the ignore evaluation semantic ([basic.contract.eval]),
    [Note 2: 
    Within this evaluation, std​::​is_constant_evaluated() ([meta.const.eval]) returns true.
    — end note]
    [Note 3: 
    The initialization, when evaluated, can still evaluate contract assertions with other evaluation semantics, resulting in a diagnostic or ill-formed program if a contract violation occurs.
    — end note]
  • 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 type is const-default-constructible ([dcl.init.general]).
[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 cv std​::​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 4: 
    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.assign], [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 5: 
    A goto statement introduced by equivalence ([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 6: 
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 ([dcl.constexpr]), 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 7: 
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 8: 
Such expressions can be used in new expressions ([expr.new]), as case expressions ([stmt.switch]), as enumerator initializers if the underlying type is fixed ([dcl.enum]), as array bounds ([dcl.array]), and as constant template arguments ([temp.arg]).
— 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 result object ([basic.lval]) 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 or erroneous 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 9: 
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 10: 
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 11: 
    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 } constexpr int l(int c) pre(c >= 2) { return (c % 2 == 0) ? c / 0 : c; } const int i0 = l(0); // dynamic initialization; contract violation or undefined behavior const int i1 = l(1); // static initialization; value of 1 or contract violation at compile time const int i2 = l(2); // dynamic initialization; undefined behavior const int i3 = l(3); // static initialization; value of 3 — 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 12: 
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, with evaluations of contract assertions using the ignore evaluation semantic ([basic.contract.eval]), 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]

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]).
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.
[Note 3: 
These operations are sequenced before the destruction of local variables in each remaining enclosing block of the function ([stmt.dcl]), which, in turn, is sequenced before the evaluation of postcondition assertions of the function ([dcl.contract.func]), which, in turn, is sequenced before the destruction of function parameters ([expr.call]).
— end note]
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 Assertion statement [stmt.contract.assert]

An assertion-statement introduces a contract assertion ([basic.contract]).
The optional attribute-specifier-seq appertains to the introduced contract assertion.
The predicate ([basic.contract.general]) of an assertion-statement is its conditional-expression contextually converted to bool.
The evaluation of consecutive assertion-statements is an evaluation in sequence ([basic.contract.eval]) of the contract assertions introduced by those assertion-statements.
[Note 1: 
A sequence of assertion-statements can thus be repeatedly evaluated as a group.
[Example 1: int f(int i) { contract_assert(i == 0); // #1 contract_assert(i >= 0); // #2 return 0; } int g = f(0); // can evaluate #1, #2, #1, #2 — end example]
— end note]

8.9 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.10 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]

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] 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 type 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.assign], [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:
  • if E is an unparenthesized id-expression naming a structured binding ([dcl.struct.bind]), decltype(E) is the referenced type as given in the specification of the structured binding declaration;
  • otherwise, if E is an unparenthesized id-expression naming a constant template parameter ([temp.param]), decltype(E) is the type of the template parameter after performing any necessary type deduction ([dcl.spec.auto], [dcl.type.class.deduct]);
  • otherwise, if E is an unparenthesized id-expression or an unparenthesized class member access ([expr.ref]), decltype(E) is the type of the entity named by E.
    If there is no such entity, the program is ill-formed;
  • otherwise, if E is an xvalue, decltype(E) is T&&, where T is the type of E;
  • otherwise, if E is an lvalue, decltype(E) is T&, where T is the type of E;
  • otherwise, decltype(E) is the type of E.
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]
A result binding never has an undeduced placeholder type ([dcl.contract.res]).
[Example 5: auto f() post(r : r == 7) // OK { return 7; } — 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 6: 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 7: 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 8: 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]
The optional function-contract-specifier-seq ([dcl.contract.func]) in an init-declarator shall be present only if the declarator declares a function.

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-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-parameter declares 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 type-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 type-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 Function contract specifiers [dcl.contract]

9.4.1 General [dcl.contract.func]

A function contract assertion is a contract assertion ([basic.contract.general]) associated with a function.
A precondition-specifier introduces a precondition assertion, which is a function contract assertion associated with entering a function.
A postcondition-specifier introduces a postcondition assertion, which is a function contract assertion associated with exiting a function normally.
[Note 1: 
A postcondition assertion is not associated with exiting a function in any other fashion, such as via an exception ([expr.throw]) or via a call to longjmp ([csetjmp.syn]).
— end note]
The predicate ([basic.contract.general]) of a function contract assertion is its conditional-expression contextually converted to bool.
Each function-contract-specifier of a function-contract-specifier-seq (if any) of an unspecified first declaration ([basic.def]) of a function introduces a corresponding function contract assertion for that function.
The optional attribute-specifier-seq following pre or post appertains to the introduced contract assertion.
[Note 2: 
The function-contract-specifier-seq of a lambda-declarator applies to the function call operator or operator template of the corresponding closure type ([expr.prim.lambda.closure]).
— end note]
A declaration D of a function or function template f that is not a first declaration shall have either no function-contract-specifier-seq or the same function-contract-specifier-seq (see below) as any first declaration F reachable from D.
If D and F are in different translation units, a diagnostic is required only if D is attached to a named module.
If a declaration is a first declaration of f in one translation unit and a declaration is a first declaration of f in another translation unit, and shall specify the same function-contract-specifier-seq, no diagnostic required.
A function-contract-specifier-seq is the same as a function-contract-specifier-seq if and consist of the same function-contract-specifiers in the same order.
A function-contract-specifier on a function declaration is the same as a function-contract-specifier on a function declaration if
  • their predicates and would satisfy the one-definition rule ([basic.def.odr]) if placed in function definitions on the declarations and , respectively, except for and, if and are in different translation units, corresponding entities defined within each predicate behave as if there is a single entity with a single definition, and
  • both and specify a result-name-introducer or neither do.
If this condition is not met solely due to the comparison of two lambda-expressions that are contained within and , no diagnostic is required.
[Note 3: 
Equivalent function-contract-specifier-seqs apply to all uses and definitions of a function across all translation units.
— end note]
[Example 1:  bool b1, b2; void f() pre (b1) pre ([]{ return b2; }()); void f(); // OK, function-contract-specifiers omitted void f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types. void f() pre (b1); // error: function-contract-specifiers only partially repeated int g() post(r : b1); int g() post(b1); // error: mismatched result-name-introducer presence namespace N { void h() pre (b1); bool b1; void h() pre (b1); // error: function-contract-specifiers differ according to // the one-definition rule ([basic.def.odr]). } — end example]
A virtual function ([class.virtual]), a deleted function ([dcl.fct.def.delete]), or a function defaulted on its first declaration ([dcl.fct.def.default]) shall not have a function-contract-specifier-seq.
If the predicate of a postcondition assertion of a function f odr-uses ([basic.def.odr]) a non-reference parameter of f, that parameter and the corresponding parameter on all declarations of f shall have const type.
[Note 4: 
This requirement applies even to declarations that do not specify the postcondition-specifier.
Parameters with array or function type will decay to non-const types even if a const qualifier is present.
[Example 2: int f(const int i[10]) post(r : r == i[0]); // error: i has type const int * (not int* const). — end example]
— end note]
[Note 5: 
The function contract assertions of a function are evaluated even when invoked indirectly, such as through a pointer to function or a pointer to member function.
A pointer to function, pointer to member function, or function type alias cannot have a function-contract-specifier-seq associated directly with it.
— end note]
The function contract assertions of a function are considered to be needed ([temp.inst]) when
[Note 6: 
Overload resolution does not consider function-contract-specifiers ([temp.deduct], [temp.inst]).
[Example 3: template <typename T> void f(T t) pre( t == "" ); template <typename T> void f(T&& t); void g() { f(5); // error: ambiguous } — end example]
— end note]

9.4.2 Referring to the result object [dcl.contract.res]

The result-name-introducer introduces the identifier as the name of a result binding of the associated function.
If a postcondition assertion has a result-name-introducer and the return type of the function is cv void, the program is ill-formed.
A result binding denotes the object or reference returned by invocation of that function.
The type of a result binding is the return type of its associated function The optional attribute-specifier-seq of the attributed-identifier in the result-name-introducer appertains to the result binding so introduced.
[Note 1: 
An id-expression that names a result binding is a const lvalue ([expr.prim.id.unqual]).
— end note]
[Example 1: int f() post(r : r == 1) { return 1; } int i = f(); // Postcondition check succeeds. — end example]
[Example 2: struct A {}; struct B { B() {} B(const B&) {} }; template <typename T> T f(T* const ptr) post(r: &r == ptr) { return {}; } int main() { A a = f(&a); // The postcondition check can fail if the implementation introduces // a temporary for the return value ([class.temporary]). B b = f(&b); // The postcondition check succeeds, no temporary is introduced. } — end example]
When the declared return type of a non-templated function contains a placeholder type, a postcondition-specifier with a result-name-introducer shall be present only on a definition.
[Example 3: auto g(auto&) post (r: r >= 0); // OK, g is a template. auto h() post (r: r >= 0); // error: cannot name the return value auto k() post (r: r >= 0) // OK { return 0; } — end example]

9.5 Initializers [dcl.init]

9.5.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 with 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.5.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.5.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.5.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.assign]).
— 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.5.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.6 Function definitions [dcl.fct.def]

9.6.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.6.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.6.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.6.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 the top-level cv-qualifiers in all parameter-declarations in the declarator of its function-definition were removed and its function-body were replaced by the following replacement body:
{
   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().
[Note 1: 
An odr-use of a non-reference parameter in a postcondition assertion of a coroutine is ill-formed ([dcl.contract.func]).
— end note]
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 2: 
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]) as part of the replacement body.
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 with their original types (including cv-qualifiers) 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, a copy is created for each coroutine parameter at the beginning of the replacement body.
For a parameter whose original declaration specified the type cv T,
  • if T is a reference type, the copy is a reference of type cv T bound to the same object as a parameter;
  • otherwise, 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 3: 
An identifier in the function-body that names one of these parameters refers to the created copy, not the original parameter ([expr.prim.id.unqual]).
— 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 4: 
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.5 Replaceable function definitions [dcl.fct.def.replace]

Certain functions for which a definition is supplied by the implementation are replaceable.
A C++ program may provide a definition with the signature of a replaceable function, called a replacement function.
The replacement function is used instead of the default version supplied by the implementation.
Such replacement occurs prior to program startup ([basic.def.odr], [basic.start]).
A declaration of the replacement function
  • shall not be inline,
  • shall be attached to the global module,
  • shall have C++ language linkage,
  • shall have the same return type as the replaceable function, and
  • if the function is declared in a standard library header, shall be such that it would be valid as a redeclaration of the declaration in that header;
no diagnostic is required.
[Note 1: 
The one-definition rule ([basic.def.odr])) applies to the definitions of a replaceable function provided by the program.
The implementation-supplied function definition is an otherwise-unnamed function with no linkage.
— end note]

9.7 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 constant template 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.8 Enumerations [enum]

9.8.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.8.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.9 Namespaces [basic.namespace]

9.9.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.9.2 Namespace definition [namespace.def]

9.9.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.9.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.9.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.9.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.10 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.11 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.13 Attributes [dcl.attr]

9.13.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], [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.13.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.13.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.13.4 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.13.5 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.13.6 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.13.7 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.13.8 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, result binding ([dcl.contract.res]), 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.13.9 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]) of non-void type 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.13.10 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.13.11 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 unless it is a namespace.
[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 namespace N { // external linkage, attached to global module, not exported void f(); } namespace N { // OK, exported namespace redeclaring non-exported namespace export void g(); } — 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-property-specifier:
final
trivially_relocatable_if_eligible
replaceable_if_eligible
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]
Each class-property-specifier shall appear at most once within a single class-property-specifier-seq.
Whenever a class-key is followed by a class-head-name, the identifier final, trivially_relocatable_if_eligible, or replaceable_if_eligible, and a colon or left brace, the identifier is interpreted as a class-property-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 trivially_relocatable_if_eligible : C{}; // OK, definition of nested class B, // not declaration of a bit-field member // trivially_relocatable_if_eligible }; — end example]
If a class is marked with the class-property-specifier final and that class appears as a class-or-decltype in a base-clause ([class.derived]), the program is ill-formed.
[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.assign], [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 C is default-movable if
  • overload resolution for direct-initializing an object of type C from an xvalue of type C selects a constructor that is a direct member of C and is neither user-provided nor deleted,
  • overload resolution for assigning to an lvalue of type C from an xvalue of type C selects an assignment operator function that is a direct member of C and is neither user-provided nor deleted, and
  • C has a destructor that is neither user-provided nor deleted.
A class is eligible for trivial relocation unless it
  • has any virtual base classes,
  • has a base class that is not a trivially relocatable class,
  • has a non-static data member of an object type that is not of a trivially relocatable type, or
  • has a deleted destructor,
except that it is implementation-defined whether an otherwise-eligible union having one or more subobjects of polymorphic class type is eligible for trivial relocation.
A class C is a trivially relocatable class if it is eligible for trivial relocation and
[Note 1: 
A class with const-qualified or reference non-static data members can be trivially relocatable.
— end note]
A class C is eligible for replacement unless
  • it has a base class that is not a replaceable class,
  • it has a non-static data member that is not of a replaceable type,
  • overload resolution fails or selects a deleted constructor when direct-initializing an object of type C from an xvalue of type C ([dcl.init.general]),
  • overload resolution fails or selects a deleted assignment operator function when assigning to an lvalue of type C from an xvalue of type C ([expr.assign], [over.assign])), or
  • it has a deleted destructor.
A class C is a replaceable class if it is eligible for replacement and
[Note 2: 
Accessibility of the special member functions is not considered when establishing trivial relocatability or replaceability.
— end note]
[Note 3: 
Not all trivially copyable classes are trivially relocatable or replaceable.
— end note]
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 4: 
    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 5: 
Standard-layout classes are useful for communicating with code written in other programming languages.
Their layout is specified in [class.mem.general] and [expr.rel].
— 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 6: 
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