Init
This commit is contained in:
153
cppdraft/basic/align.md
Normal file
153
cppdraft/basic/align.md
Normal file
@@ -0,0 +1,153 @@
|
||||
[basic.align]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.align)
|
||||
|
||||
### 6.8.3 Alignment [basic.align]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3727)
|
||||
|
||||
Object types have [*alignment requirements*](#def:alignment_requirement,implementation-defined "6.8.3 Alignment [basic.align]") ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"), [[basic.compound]](basic.compound "6.9.4 Compound types"))
|
||||
which place restrictions on the addresses at which an object of that type
|
||||
may be allocated[.](#1.sentence-1)
|
||||
|
||||
An [*alignment*](#def:alignment "6.8.3 Alignment [basic.align]") is an implementation-defined
|
||||
integer value representing the number of bytes between successive addresses
|
||||
at which a given object can be allocated[.](#1.sentence-2)
|
||||
|
||||
An object type imposes an alignment
|
||||
requirement on every object of that type; stricter alignment can be requested
|
||||
using the alignment specifier ([[dcl.align]](dcl.align "9.13.2 Alignment specifier"))[.](#1.sentence-3)
|
||||
|
||||
Attempting to create an object ([[intro.object]](intro.object "6.8.2 Object model")) in storage that
|
||||
does not meet the alignment requirements of the object's type
|
||||
is undefined behavior[.](#1.sentence-4)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3739)
|
||||
|
||||
A [*fundamental alignment*](#def:alignment,fundamental "6.8.3 Alignment [basic.align]") is represented by an alignment
|
||||
less than or equal to the greatest alignment supported by the implementation in
|
||||
all contexts, which is equal toalignof(std::max_align_t) ([[support.types]](support.types "17.2 Common definitions"))[.](#2.sentence-1)
|
||||
|
||||
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[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#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[.](#2.sentence-3)
|
||||
|
||||
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[.](#2.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
The result of the alignof operator reflects the alignment
|
||||
requirement of the type in the complete-object case[.](#2.sentence-5)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3761)
|
||||
|
||||
An [*extended alignment*](#def:alignment,extended "6.8.3 Alignment [basic.align]") is represented by an alignment
|
||||
greater than alignof(std::max_align_t)[.](#3.sentence-1)
|
||||
|
||||
It is implementation-defined
|
||||
whether any extended alignments are supported and the contexts in which they are
|
||||
supported ([[dcl.align]](dcl.align "9.13.2 Alignment specifier"))[.](#3.sentence-2)
|
||||
|
||||
A type having an extended alignment
|
||||
requirement is an [*over-aligned type*](#def:type,over-aligned "6.8.3 Alignment [basic.align]")[.](#3.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Every over-aligned type is or contains a class type
|
||||
to which extended alignment applies (possibly through a non-static data member)[.](#3.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A [*new-extended alignment*](#def:alignment,new-extended "6.8.3 Alignment [basic.align]") is represented by
|
||||
an alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__ ([[cpp.predefined]](cpp.predefined "15.12 Predefined macro names"))[.](#3.sentence-5)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3774)
|
||||
|
||||
Alignments are represented as values of the type std::size_t[.](#4.sentence-1)
|
||||
|
||||
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[.](#4.sentence-2)
|
||||
|
||||
Every alignment value shall be a non-negative integral power of two[.](#4.sentence-3)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3782)
|
||||
|
||||
Alignments have an order from [*weaker*](#def:alignment,weaker "6.8.3 Alignment [basic.align]") to[*stronger*](#def:alignment,stronger "6.8.3 Alignment [basic.align]") or [*stricter*](#def:alignment,stricter "6.8.3 Alignment [basic.align]") alignments[.](#5.sentence-1)
|
||||
|
||||
Stricter
|
||||
alignments have larger alignment values[.](#5.sentence-2)
|
||||
|
||||
An address that satisfies an alignment
|
||||
requirement also satisfies any weaker valid alignment requirement[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3788)
|
||||
|
||||
The alignment requirement of a complete type can be queried using analignof expression ([[expr.alignof]](expr.alignof "7.6.2.6 Alignof"))[.](#6.sentence-1)
|
||||
|
||||
Furthermore,
|
||||
the narrow character types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) shall have the weakest
|
||||
alignment requirement[.](#6.sentence-2)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This enables the ordinary character types to be used as the
|
||||
underlying type for an aligned memory area ([[dcl.align]](dcl.align "9.13.2 Alignment specifier"))[.](#6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3798)
|
||||
|
||||
Comparing alignments is meaningful and provides the obvious results:
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
Two alignments are equal when their numeric values are equal[.](#7.1.sentence-1)
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
Two alignments are different when their numeric values are not equal[.](#7.2.sentence-1)
|
||||
|
||||
- [(7.3)](#7.3)
|
||||
|
||||
When an alignment is larger than another it represents a stricter alignment[.](#7.3.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3807)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The runtime pointer alignment function ([[ptr.align]](ptr.align "20.2.5 Pointer alignment"))
|
||||
can be used to obtain an aligned pointer within a buffer;
|
||||
an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2 Alignment specifier"))
|
||||
can be used to align storage explicitly[.](#8.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3815)
|
||||
|
||||
If a request for a specific extended alignment in a specific context is not
|
||||
supported by an implementation, the program is ill-formed[.](#9.sentence-1)
|
||||
264
cppdraft/basic/compound.md
Normal file
264
cppdraft/basic/compound.md
Normal file
@@ -0,0 +1,264 @@
|
||||
[basic.compound]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.9 Types [[basic.types]](basic.types#basic.compound)
|
||||
|
||||
### 6.9.4 Compound types [basic.compound]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5789)
|
||||
|
||||
Compound types can be constructed in the following ways:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
[*arrays*](#def:type,array "6.9.4 Compound types [basic.compound]") of objects of a given type, [[dcl.array]](dcl.array "9.3.4.5 Arrays");
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
[*functions*](dcl.fct#def:type,function "9.3.4.6 Functions [dcl.fct]"), which have parameters of given types and returnvoid or a result of a given type, [[dcl.fct]](dcl.fct "9.3.4.6 Functions");
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
[*pointers*](#def:type,pointer "6.9.4 Compound types [basic.compound]") to cv void or objects or functions (including
|
||||
static members of classes) of a given type, [[dcl.ptr]](dcl.ptr "9.3.4.2 Pointers");
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
[*references*](#def:reference "6.9.4 Compound types [basic.compound]") to objects or functions of a given
|
||||
type, [[dcl.ref]](dcl.ref "9.3.4.3 References")[.](#1.4.sentence-1)
|
||||
There are two types of references:
|
||||
* [(1.4.1)](#1.4.1)
|
||||
|
||||
lvalue reference
|
||||
|
||||
* [(1.4.2)](#1.4.2)
|
||||
|
||||
rvalue reference
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
[*classes*](#def:class "6.9.4 Compound types [basic.compound]") containing a sequence of class members ([[class]](class "11 Classes"), [[class.mem]](class.mem "11.4 Class members")),
|
||||
and a set of restrictions
|
||||
on the access to these entities ([[class.access]](class.access "11.8 Member access control"));
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
[*unions*](#def:union "6.9.4 Compound types [basic.compound]"), which are classes capable of containing objects of
|
||||
different types at different times, [[class.union]](class.union "11.5 Unions");
|
||||
|
||||
- [(1.7)](#1.7)
|
||||
|
||||
[*enumerations*](#def:enum "6.9.4 Compound types [basic.compound]"),
|
||||
which comprise a set of named constant values, [[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations");
|
||||
|
||||
- [(1.8)](#1.8)
|
||||
|
||||
[*pointers to non-static class members*](#def:pointer_to_member "6.9.4 Compound types [basic.compound]"),[31](#footnote-31 "Static class members are objects or functions, and pointers to them are ordinary pointers to objects or functions.") which identify members of a given
|
||||
type within objects of a given class, [[dcl.mptr]](dcl.mptr "9.3.4.4 Pointers to members")[.](#1.8.sentence-1)
|
||||
Pointers to data members and pointers to member functions are collectively
|
||||
called [*pointer-to-member*](#def:pointer-to-member "6.9.4 Compound types [basic.compound]") types[.](#1.8.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5837)
|
||||
|
||||
These methods of constructing types can be applied recursively;
|
||||
restrictions are mentioned in [[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators")[.](#2.sentence-1)
|
||||
|
||||
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]](support.types "17.2 Common definitions")) is ill-formed[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5844)
|
||||
|
||||
The type of a pointer to cv void or a pointer to an object type is
|
||||
called an [*object pointer type*](#def:object_pointer_type "6.9.4 Compound types [basic.compound]")[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A pointer to void does not have a pointer-to-object type, however, because void is not
|
||||
an object type[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The type of a pointer that can designate a function
|
||||
is called a [*function pointer type*](#def:function_pointer_type "6.9.4 Compound types [basic.compound]")[.](#3.sentence-3)
|
||||
|
||||
A pointer to an object of type T is referred to as a âpointer toTâ[.](#3.sentence-4)
|
||||
|
||||
[*Example [1](#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â[.](#3.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
Except for pointers to static members, text referring to âpointersâ
|
||||
does not apply to pointers to members[.](#3.sentence-6)
|
||||
|
||||
Pointers to incomplete types are
|
||||
allowed although there are restrictions on what can be done with
|
||||
them ([[basic.types.general]](basic.types.general "6.9.1 General"))[.](#3.sentence-7)
|
||||
|
||||
Every value of pointer type is one of the following:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
a [*pointer to*](#def:pointer_to "6.9.4 Compound types [basic.compound]") an object or function (the pointer is said to [*point*](#def:point "6.9.4 Compound types [basic.compound]") to the object or function), or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
a [*pointer past the end of*](#def:pointer_past_the_end_of "6.9.4 Compound types [basic.compound]") an object ([[expr.add]](expr.add "7.6.6 Additive operators")), or
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
the [*null pointer value*](#def:value,null_pointer "6.9.4 Compound types [basic.compound]") for that type, or
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
an [*invalid pointer value*](#def:value,invalid_pointer "6.9.4 Compound types [basic.compound]")[.](#3.sentence-8)
|
||||
|
||||
A value of a
|
||||
pointer type
|
||||
that is a pointer to or past the end of an object[*represents the address*](#def:represents_the_address "6.9.4 Compound types [basic.compound]") of
|
||||
the first byte in memory ([[intro.memory]](intro.memory "6.8.1 Memory model")) occupied by the object[32](#footnote-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.") or the first byte in memory
|
||||
after the end of the storage occupied by the object,
|
||||
respectively[.](#3.sentence-9)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
A pointer past the end of an object ([[expr.add]](expr.add "7.6.6 Additive operators"))
|
||||
is not considered to point to an unrelated object
|
||||
of the object's type,
|
||||
even if the unrelated object is located at that address[.](#3.sentence-10)
|
||||
|
||||
â *end note*]
|
||||
|
||||
For purposes of pointer arithmetic ([[expr.add]](expr.add "7.6.6 Additive operators"))
|
||||
and comparison ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators")),
|
||||
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[.](#3.sentence-11)
|
||||
|
||||
The value representation of
|
||||
pointer types is implementation-defined[.](#3.sentence-12)
|
||||
|
||||
Pointers to
|
||||
layout-compatible types shall
|
||||
have the same value representation and alignment
|
||||
requirements ([[basic.align]](basic.align "6.8.3 Alignment"))[.](#3.sentence-13)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Pointers to [over-aligned types](basic.align#def:type,over-aligned "6.8.3 Alignment [basic.align]") have no special
|
||||
representation, but their range of valid values is restricted by the extended
|
||||
alignment requirement[.](#3.sentence-14)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5917)
|
||||
|
||||
A pointer value P is[*valid in the context of*](#def:valid_in_the_context_of "6.9.4 Compound types [basic.compound]") 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 andE happens before the end of the duration of the region of storage for O[.](#4.sentence-1)
|
||||
|
||||
If a pointer value P is used in an evaluation E andP is not valid in the context of E,
|
||||
then the behavior is undefined if E is
|
||||
an indirection ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")) or
|
||||
an invocation of a deallocation function ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions")),
|
||||
and implementation-defined otherwise[.](#4.sentence-2)[33](#footnote-33 "Some implementations might define that copying such a pointer value causes a system-generated runtime fault.")
|
||||
|
||||
[*Note [4](#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.life "6.8.4 Lifetime"), [[basic.lval]](basic.lval "7.2.1 Value category"), [[expr.add]](expr.add "7.6.6 Additive operators"))[.](#4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5942)
|
||||
|
||||
Two objects *a* and *b* are [*pointer-interconvertible*](#def:pointer-interconvertible "6.9.4 Compound types [basic.compound]") if
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
they are the same object, or
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
one is a union object and
|
||||
the other is a non-static data member of that object ([[class.union]](class.union "11.5 Unions")), or
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
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]](class.mem "11.4 Class members")), or
|
||||
|
||||
- [(5.4)](#5.4)
|
||||
|
||||
there exists an object *c* such that*a* and *c* are pointer-interconvertible, and*c* and *b* are pointer-interconvertible[.](#5.sentence-1)
|
||||
|
||||
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]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"))[.](#5.sentence-2)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
An array object and its first element are not pointer-interconvertible,
|
||||
even though they have the same address[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5969)
|
||||
|
||||
A byte of storage *b* is [*reachable through*](#def:storage,reachable_through_a_pointer_value "6.9.4 Compound types [basic.compound]") 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[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5979)
|
||||
|
||||
A pointer to cv void can be used to point to objects of
|
||||
unknown type[.](#7.sentence-1)
|
||||
|
||||
Such a pointer shall be able to hold any object pointer[.](#7.sentence-2)
|
||||
|
||||
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â[.](#7.sentence-3)
|
||||
|
||||
[31)](#footnote-31)[31)](#footnoteref-31)
|
||||
|
||||
Static class members are objects or functions, and pointers to them are
|
||||
ordinary pointers to objects or functions[.](#footnote-31.sentence-1)
|
||||
|
||||
[32)](#footnote-32)[32)](#footnoteref-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[.](#footnote-32.sentence-1)
|
||||
|
||||
[33)](#footnote-33)[33)](#footnoteref-33)
|
||||
|
||||
Some implementations might define that
|
||||
copying such a pointer value causes a system-generated runtime fault[.](#footnote-33.sentence-1)
|
||||
494
cppdraft/basic/contract.md
Normal file
494
cppdraft/basic/contract.md
Normal file
@@ -0,0 +1,494 @@
|
||||
[basic.contract]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.11 Contract assertions [basic.contract]
|
||||
|
||||
### [6.11.1](#general) General [[basic.contract.general]](basic.contract.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7567)
|
||||
|
||||
[*Contract assertions*](#def:contract_assertion "6.11.1 General [basic.contract.general]") allow the programmer to specify
|
||||
properties of the state of the program
|
||||
that are expected to hold at
|
||||
certain points during execution[.](#general-1.sentence-1)
|
||||
|
||||
Contract assertions are introduced by[*precondition-specifier*](dcl.contract.func#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")*s*,[*postcondition-specifier*](dcl.contract.func#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")*s* ([[dcl.contract.func]](dcl.contract.func "9.4.1 General")), and[*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]")*s* ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion statement"))[.](#general-1.sentence-2)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7578)
|
||||
|
||||
Each contract assertion has a [*contract-assertion predicate*](#def:predicate,contract-assertion "6.11.1 General [basic.contract.general]"),
|
||||
which is an expression of type bool[.](#general-2.sentence-1)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
The value of the predicate is used to identify program states that are
|
||||
expected[.](#general-2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7587)
|
||||
|
||||
An invocation of the macro va_start ([[cstdarg.syn]](cstdarg.syn "17.14.2 Header <cstdarg> synopsis"))
|
||||
shall not be a subexpression
|
||||
of the predicate of a contract assertion,
|
||||
no diagnostic required[.](#general-3.sentence-1)
|
||||
|
||||
[4](#general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7593)
|
||||
|
||||
[*Note [2](#general-note-2)*:
|
||||
|
||||
Within the predicate of a contract assertion,[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")*s* referring to
|
||||
variables declared outside the contract assertion
|
||||
are const ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")),this is a pointer to const ([[expr.prim.this]](expr.prim.this "7.5.3 This")),
|
||||
and the result object can be named
|
||||
if a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")) has been specified[.](#general-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [6.11.2](#eval) Evaluation [[basic.contract.eval]](basic.contract.eval)
|
||||
|
||||
[1](#eval-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7606)
|
||||
|
||||
An evaluation of a contract assertion
|
||||
uses one of the following four [*evaluation semantics*](#def:evaluation_semantics "6.11.2 Evaluation [basic.contract.eval]"):[*ignore*](#def:contract_evaluation_semantics,ignore "6.11.2 Evaluation [basic.contract.eval]"),[*observe*](#def:contract_evaluation_semantics,observe "6.11.2 Evaluation [basic.contract.eval]"),[*enforce*](#def:contract_evaluation_semantics,enforce "6.11.2 Evaluation [basic.contract.eval]"), or[*quick-enforce*](#def:contract_evaluation_semantics,quick-enforce "6.11.2 Evaluation [basic.contract.eval]")[.](#eval-1.sentence-1)
|
||||
|
||||
Observe, enforce, and quick-enforce are [*checking semantics*](#def:contract_evaluation_semantics,checking "6.11.2 Evaluation [basic.contract.eval]");
|
||||
enforce and quick-enforce are [*terminating semantics*](#def:contract_evaluation_semantics,terminating "6.11.2 Evaluation [basic.contract.eval]")[.](#eval-1.sentence-2)
|
||||
|
||||
[2](#eval-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7619)
|
||||
|
||||
It isimplementation-defined
|
||||
which evaluation semantic is used
|
||||
for any given evaluation of a contract assertion[.](#eval-2.sentence-1)
|
||||
|
||||
[*Note [1](#eval-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[.](#eval-2.sentence-2)
|
||||
|
||||
The evaluation semantics can differ
|
||||
for different evaluations of the same contract assertion,
|
||||
including evaluations during constant evaluation[.](#eval-2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#eval-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7633)
|
||||
|
||||
*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[.](#eval-3.sentence-1)
|
||||
|
||||
By default,
|
||||
evaluations of contract assertions should use the enforce semantic[.](#eval-3.sentence-2)
|
||||
|
||||
[4](#eval-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7644)
|
||||
|
||||
The evaluation of a contract assertion using the ignore semantic has no effect[.](#eval-4.sentence-1)
|
||||
|
||||
[*Note [2](#eval-note-2)*:
|
||||
|
||||
The predicate is potentially evaluated ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")),
|
||||
but not evaluated[.](#eval-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#eval-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7651)
|
||||
|
||||
The evaluation A of a contract assertion
|
||||
using a checking semantic
|
||||
determines the value of the predicate[.](#eval-5.sentence-1)
|
||||
|
||||
It is unspecified
|
||||
whether the predicate is evaluated[.](#eval-5.sentence-2)
|
||||
|
||||
Let B be the value that would result from evaluating the predicate[.](#eval-5.sentence-3)
|
||||
|
||||
[*Note [3](#eval-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[.](#eval-5.sentence-4)
|
||||
|
||||
[*Example [1](#eval-example-1)*: struct S {mutable int g = 5;} s;void f() pre(( s.g++, false )); // #1void g(){ f(); // Increment of s.g might not occur, even if #1 uses a checking semantic.} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#eval-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7680)
|
||||
|
||||
There is an observable checkpoint ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine")) C that happens before A such that any other operation O that happens before A also happens before C[.](#eval-6.sentence-1)
|
||||
|
||||
[7](#eval-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7687)
|
||||
|
||||
A [*contract violation*](#def:contract_violation "6.11.2 Evaluation [basic.contract.eval]") occurs when
|
||||
|
||||
- [(7.1)](#eval-7.1)
|
||||
|
||||
B is false,
|
||||
|
||||
- [(7.2)](#eval-7.2)
|
||||
|
||||
the evaluation of the predicate
|
||||
exits via an exception, or
|
||||
|
||||
- [(7.3)](#eval-7.3)
|
||||
|
||||
the evaluation of the predicate
|
||||
is performed in a context that is
|
||||
manifestly constant-evaluated ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||||
and the predicate
|
||||
is not a core constant expression[.](#eval-7.sentence-1)
|
||||
|
||||
[*Note [4](#eval-note-4)*:
|
||||
|
||||
If B is true,
|
||||
no contract violation occurs and
|
||||
control flow continues normally
|
||||
after the point of evaluation of the contract assertion[.](#eval-7.sentence-2)
|
||||
|
||||
The evaluation of the predicate
|
||||
can fail to produce a value
|
||||
without causing a contract violation,
|
||||
for example,
|
||||
by calling longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3 Header <csetjmp> synopsis"))
|
||||
or terminating the program[.](#eval-7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#eval-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7716)
|
||||
|
||||
If a contract violation occurs
|
||||
in a context that is manifestly constant-evaluated ([[expr.const]](expr.const "7.7 Constant expressions")),
|
||||
and the evaluation semantic is
|
||||
a terminating semantic,
|
||||
the program is ill-formed[.](#eval-8.sentence-1)
|
||||
|
||||
[*Note [5](#eval-note-5)*:
|
||||
|
||||
A diagnostic is produced
|
||||
if the evaluation semantic is observe ([[intro.compliance]](intro.compliance "4.1 Implementation compliance"))[.](#eval-8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [6](#eval-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]](basic.def.odr "6.3 One-definition rule"))
|
||||
when a contract assertion has side effects
|
||||
that alter the value produced by a constant expression[.](#eval-8.sentence-3)
|
||||
|
||||
[*Example [2](#eval-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*]
|
||||
|
||||
[9](#eval-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7752)
|
||||
|
||||
When the program is [*contract-terminated*](#def:contract-terminated "6.11.2 Evaluation [basic.contract.eval]"),
|
||||
it isimplementation-defined
|
||||
(depending on context) whether
|
||||
|
||||
- [(9.1)](#eval-9.1)
|
||||
|
||||
std::terminate is called,
|
||||
|
||||
- [(9.2)](#eval-9.2)
|
||||
|
||||
std::abort is called, or
|
||||
|
||||
- [(9.3)](#eval-9.3)
|
||||
|
||||
execution is terminated[.](#eval-9.sentence-1)
|
||||
[*Note [7](#eval-note-7)*:
|
||||
No further execution steps occur ([[intro.progress]](intro.progress "6.10.2.3 Forward progress"))[.](#eval-9.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[*Note [8](#eval-note-8)*:
|
||||
|
||||
Performing the actions ofstd::terminate or std::abort without actually making a library call
|
||||
is a conforming implementation of
|
||||
contract-termination ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine"))[.](#eval-9.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[10](#eval-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7778)
|
||||
|
||||
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[.](#eval-10.sentence-1)
|
||||
|
||||
[11](#eval-11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7786)
|
||||
|
||||
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]](#handler "6.11.3 Contract-violation handler"))
|
||||
is invoked with an lvalue referring to
|
||||
an object v of type const std::contracts::contract_violation ([[support.contract.violation]](support.contract.violation "17.10.3 Class contract_violation"))
|
||||
containing information about the contract violation[.](#eval-11.sentence-1)
|
||||
|
||||
Storage for v is allocated in an unspecified manner
|
||||
except as noted in [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")[.](#eval-11.sentence-2)
|
||||
|
||||
The lifetime of v persists for the duration
|
||||
of the invocation of the contract-violation handler[.](#eval-11.sentence-3)
|
||||
|
||||
[12](#eval-12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7806)
|
||||
|
||||
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]](except.handle "14.4 Handling an exception"))[.](#eval-12.sentence-1)
|
||||
|
||||
If the contract-violation handler
|
||||
returns normally
|
||||
and the evaluation semantic is observe,
|
||||
that implicit handler
|
||||
is no longer considered active[.](#eval-12.sentence-2)
|
||||
|
||||
[*Note [9](#eval-note-9)*:
|
||||
|
||||
The exception can be inspected or rethrown within the contract-violation handler[.](#eval-12.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[13](#eval-13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7823)
|
||||
|
||||
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[.](#eval-13.sentence-1)
|
||||
|
||||
[14](#eval-14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7835)
|
||||
|
||||
[*Note [10](#eval-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[.](#eval-14.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#eval-15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7845)
|
||||
|
||||
There is an observable checkpoint ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine")) 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[.](#eval-15.sentence-1)
|
||||
|
||||
[16](#eval-16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7852)
|
||||
|
||||
[*Note [11](#eval-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[.](#eval-16.sentence-1)
|
||||
|
||||
Conversely,
|
||||
the observe semantic
|
||||
provides the opportunity to
|
||||
log information about the contract violation
|
||||
without having to terminate the program[.](#eval-16.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[17](#eval-17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7873)
|
||||
|
||||
If a contract-violation handler
|
||||
invoked from the evaluation of a function contract assertion ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
exits via an exception,
|
||||
the behavior is as if
|
||||
the function body exits via that same exception[.](#eval-17.sentence-1)
|
||||
|
||||
[*Note [12](#eval-note-12)*:
|
||||
|
||||
A [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble"))
|
||||
is the function body when present
|
||||
and thus does not
|
||||
have an opportunity to catch the exception[.](#eval-17.sentence-2)
|
||||
|
||||
If the function
|
||||
has a non-throwing exception specification,
|
||||
the function std::terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#eval-17.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [13](#eval-note-13)*:
|
||||
|
||||
If a contract-violation handler
|
||||
invoked from an [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]") ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion statement"))
|
||||
exits via an exception,
|
||||
the search for a handler
|
||||
continues from the execution of that statement[.](#eval-17.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[18](#eval-18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7897)
|
||||
|
||||
To [*evaluate in sequence*](#def:evaluate_in_sequence "6.11.2 Evaluation [basic.contract.eval]") a list R of contract assertions:
|
||||
|
||||
- [(18.1)](#eval-18.1)
|
||||
|
||||
Construct a list of contract assertions S such that
|
||||
* [(18.1.1)](#eval-18.1.1)
|
||||
|
||||
all elements of R are in S,
|
||||
|
||||
* [(18.1.2)](#eval-18.1.2)
|
||||
|
||||
each element of R may be repeated animplementation-defined
|
||||
number of times
|
||||
within S, and
|
||||
|
||||
* [(18.1.3)](#eval-18.1.3)
|
||||
|
||||
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[.](#eval-18.1.sentence-1)
|
||||
|
||||
- [(18.2)](#eval-18.2)
|
||||
|
||||
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[.](#eval-18.2.sentence-1)
|
||||
|
||||
[*Example [3](#eval-example-3)*: void f(int i){contract_assert(i > 0); // #1contract_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*]
|
||||
|
||||
[19](#eval-19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7945)
|
||||
|
||||
*Recommended practice*: An implementation should
|
||||
provide an option to perform
|
||||
a specified number of repeated evaluations
|
||||
for contract assertions[.](#eval-19.sentence-1)
|
||||
|
||||
By default,
|
||||
no repeated evaluations should be performed[.](#eval-19.sentence-2)
|
||||
|
||||
### [6.11.3](#handler) Contract-violation handler [[basic.contract.handler]](basic.contract.handler)
|
||||
|
||||
[1](#handler-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7956)
|
||||
|
||||
The [*contract-violation handler*](#def:contract-violation_handler "6.11.3 Contract-violation handler [basic.contract.handler]") of a program is a function named::handle_contract_violation[.](#handler-1.sentence-1)
|
||||
|
||||
The contract-violation handler
|
||||
shall have a single parameter
|
||||
of type
|
||||
âlvalue reference to const std::contracts::contract_violationâ
|
||||
and shall return void[.](#handler-1.sentence-2)
|
||||
|
||||
The contract-violation handler
|
||||
may have a non-throwing exception specification[.](#handler-1.sentence-3)
|
||||
|
||||
The implementation
|
||||
shall provide a definition of the contract-violation handler,
|
||||
called the [*default contract-violation handler*](#def:contract-violation_handler,default "6.11.3 Contract-violation handler [basic.contract.handler]")[.](#handler-1.sentence-4)
|
||||
|
||||
[*Note [1](#handler-note-1)*:
|
||||
|
||||
No declaration
|
||||
for the default contract-violation handler
|
||||
is provided by
|
||||
any standard library header[.](#handler-1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#handler-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7979)
|
||||
|
||||
*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[.](#handler-2.sentence-1)
|
||||
|
||||
[3](#handler-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7989)
|
||||
|
||||
It isimplementation-defined
|
||||
whether the contract-violation handler
|
||||
is replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5 Replaceable function definitions"))[.](#handler-3.sentence-1)
|
||||
|
||||
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[.](#handler-3.sentence-2)
|
||||
389
cppdraft/basic/contract/eval.md
Normal file
389
cppdraft/basic/contract/eval.md
Normal file
@@ -0,0 +1,389 @@
|
||||
[basic.contract.eval]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.11 Contract assertions [[basic.contract]](basic.contract#eval)
|
||||
|
||||
### 6.11.2 Evaluation [basic.contract.eval]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7606)
|
||||
|
||||
An evaluation of a contract assertion
|
||||
uses one of the following four [*evaluation semantics*](#def:evaluation_semantics "6.11.2 Evaluation [basic.contract.eval]"):[*ignore*](#def:contract_evaluation_semantics,ignore "6.11.2 Evaluation [basic.contract.eval]"),[*observe*](#def:contract_evaluation_semantics,observe "6.11.2 Evaluation [basic.contract.eval]"),[*enforce*](#def:contract_evaluation_semantics,enforce "6.11.2 Evaluation [basic.contract.eval]"), or[*quick-enforce*](#def:contract_evaluation_semantics,quick-enforce "6.11.2 Evaluation [basic.contract.eval]")[.](#1.sentence-1)
|
||||
|
||||
Observe, enforce, and quick-enforce are [*checking semantics*](#def:contract_evaluation_semantics,checking "6.11.2 Evaluation [basic.contract.eval]");
|
||||
enforce and quick-enforce are [*terminating semantics*](#def:contract_evaluation_semantics,terminating "6.11.2 Evaluation [basic.contract.eval]")[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7619)
|
||||
|
||||
It isimplementation-defined
|
||||
which evaluation semantic is used
|
||||
for any given evaluation of a contract assertion[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#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[.](#2.sentence-2)
|
||||
|
||||
The evaluation semantics can differ
|
||||
for different evaluations of the same contract assertion,
|
||||
including evaluations during constant evaluation[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7633)
|
||||
|
||||
*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[.](#3.sentence-1)
|
||||
|
||||
By default,
|
||||
evaluations of contract assertions should use the enforce semantic[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7644)
|
||||
|
||||
The evaluation of a contract assertion using the ignore semantic has no effect[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The predicate is potentially evaluated ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")),
|
||||
but not evaluated[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7651)
|
||||
|
||||
The evaluation A of a contract assertion
|
||||
using a checking semantic
|
||||
determines the value of the predicate[.](#5.sentence-1)
|
||||
|
||||
It is unspecified
|
||||
whether the predicate is evaluated[.](#5.sentence-2)
|
||||
|
||||
Let B be the value that would result from evaluating the predicate[.](#5.sentence-3)
|
||||
|
||||
[*Note [3](#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[.](#5.sentence-4)
|
||||
|
||||
[*Example [1](#example-1)*: struct S {mutable int g = 5;} s;void f() pre(( s.g++, false )); // #1void g(){ f(); // Increment of s.g might not occur, even if #1 uses a checking semantic.} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7680)
|
||||
|
||||
There is an observable checkpoint ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine")) C that happens before A such that any other operation O that happens before A also happens before C[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7687)
|
||||
|
||||
A [*contract violation*](#def:contract_violation "6.11.2 Evaluation [basic.contract.eval]") occurs when
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
B is false,
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
the evaluation of the predicate
|
||||
exits via an exception, or
|
||||
|
||||
- [(7.3)](#7.3)
|
||||
|
||||
the evaluation of the predicate
|
||||
is performed in a context that is
|
||||
manifestly constant-evaluated ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||||
and the predicate
|
||||
is not a core constant expression[.](#7.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
If B is true,
|
||||
no contract violation occurs and
|
||||
control flow continues normally
|
||||
after the point of evaluation of the contract assertion[.](#7.sentence-2)
|
||||
|
||||
The evaluation of the predicate
|
||||
can fail to produce a value
|
||||
without causing a contract violation,
|
||||
for example,
|
||||
by calling longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3 Header <csetjmp> synopsis"))
|
||||
or terminating the program[.](#7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7716)
|
||||
|
||||
If a contract violation occurs
|
||||
in a context that is manifestly constant-evaluated ([[expr.const]](expr.const "7.7 Constant expressions")),
|
||||
and the evaluation semantic is
|
||||
a terminating semantic,
|
||||
the program is ill-formed[.](#8.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
A diagnostic is produced
|
||||
if the evaluation semantic is observe ([[intro.compliance]](intro.compliance "4.1 Implementation compliance"))[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [6](#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]](basic.def.odr "6.3 One-definition rule"))
|
||||
when a contract assertion has side effects
|
||||
that alter the value produced by a constant expression[.](#8.sentence-3)
|
||||
|
||||
[*Example [2](#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*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7752)
|
||||
|
||||
When the program is [*contract-terminated*](#def:contract-terminated "6.11.2 Evaluation [basic.contract.eval]"),
|
||||
it isimplementation-defined
|
||||
(depending on context) whether
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
std::terminate is called,
|
||||
|
||||
- [(9.2)](#9.2)
|
||||
|
||||
std::abort is called, or
|
||||
|
||||
- [(9.3)](#9.3)
|
||||
|
||||
execution is terminated[.](#9.sentence-1)
|
||||
[*Note [7](#note-7)*:
|
||||
No further execution steps occur ([[intro.progress]](intro.progress "6.10.2.3 Forward progress"))[.](#9.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[*Note [8](#note-8)*:
|
||||
|
||||
Performing the actions ofstd::terminate or std::abort without actually making a library call
|
||||
is a conforming implementation of
|
||||
contract-termination ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine"))[.](#9.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7778)
|
||||
|
||||
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[.](#10.sentence-1)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7786)
|
||||
|
||||
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]](basic.contract.handler "6.11.3 Contract-violation handler"))
|
||||
is invoked with an lvalue referring to
|
||||
an object v of type const std::contracts::contract_violation ([[support.contract.violation]](support.contract.violation "17.10.3 Class contract_violation"))
|
||||
containing information about the contract violation[.](#11.sentence-1)
|
||||
|
||||
Storage for v is allocated in an unspecified manner
|
||||
except as noted in [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")[.](#11.sentence-2)
|
||||
|
||||
The lifetime of v persists for the duration
|
||||
of the invocation of the contract-violation handler[.](#11.sentence-3)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7806)
|
||||
|
||||
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]](except.handle "14.4 Handling an exception"))[.](#12.sentence-1)
|
||||
|
||||
If the contract-violation handler
|
||||
returns normally
|
||||
and the evaluation semantic is observe,
|
||||
that implicit handler
|
||||
is no longer considered active[.](#12.sentence-2)
|
||||
|
||||
[*Note [9](#note-9)*:
|
||||
|
||||
The exception can be inspected or rethrown within the contract-violation handler[.](#12.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7823)
|
||||
|
||||
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[.](#13.sentence-1)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7835)
|
||||
|
||||
[*Note [10](#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[.](#14.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7845)
|
||||
|
||||
There is an observable checkpoint ([[intro.abstract]](intro.abstract "4.1.2 Abstract machine")) 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[.](#15.sentence-1)
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7852)
|
||||
|
||||
[*Note [11](#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[.](#16.sentence-1)
|
||||
|
||||
Conversely,
|
||||
the observe semantic
|
||||
provides the opportunity to
|
||||
log information about the contract violation
|
||||
without having to terminate the program[.](#16.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7873)
|
||||
|
||||
If a contract-violation handler
|
||||
invoked from the evaluation of a function contract assertion ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
exits via an exception,
|
||||
the behavior is as if
|
||||
the function body exits via that same exception[.](#17.sentence-1)
|
||||
|
||||
[*Note [12](#note-12)*:
|
||||
|
||||
A [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble"))
|
||||
is the function body when present
|
||||
and thus does not
|
||||
have an opportunity to catch the exception[.](#17.sentence-2)
|
||||
|
||||
If the function
|
||||
has a non-throwing exception specification,
|
||||
the function std::terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#17.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [13](#note-13)*:
|
||||
|
||||
If a contract-violation handler
|
||||
invoked from an [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]") ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion statement"))
|
||||
exits via an exception,
|
||||
the search for a handler
|
||||
continues from the execution of that statement[.](#17.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[18](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7897)
|
||||
|
||||
To [*evaluate in sequence*](#def:evaluate_in_sequence "6.11.2 Evaluation [basic.contract.eval]") a list R of contract assertions:
|
||||
|
||||
- [(18.1)](#18.1)
|
||||
|
||||
Construct a list of contract assertions S such that
|
||||
* [(18.1.1)](#18.1.1)
|
||||
|
||||
all elements of R are in S,
|
||||
|
||||
* [(18.1.2)](#18.1.2)
|
||||
|
||||
each element of R may be repeated animplementation-defined
|
||||
number of times
|
||||
within S, and
|
||||
|
||||
* [(18.1.3)](#18.1.3)
|
||||
|
||||
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[.](#18.1.sentence-1)
|
||||
|
||||
- [(18.2)](#18.2)
|
||||
|
||||
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[.](#18.2.sentence-1)
|
||||
|
||||
[*Example [3](#example-3)*: void f(int i){contract_assert(i > 0); // #1contract_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*]
|
||||
|
||||
[19](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7945)
|
||||
|
||||
*Recommended practice*: An implementation should
|
||||
provide an option to perform
|
||||
a specified number of repeated evaluations
|
||||
for contract assertions[.](#19.sentence-1)
|
||||
|
||||
By default,
|
||||
no repeated evaluations should be performed[.](#19.sentence-2)
|
||||
55
cppdraft/basic/contract/general.md
Normal file
55
cppdraft/basic/contract/general.md
Normal file
@@ -0,0 +1,55 @@
|
||||
[basic.contract.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.11 Contract assertions [[basic.contract]](basic.contract#general)
|
||||
|
||||
### 6.11.1 General [basic.contract.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7567)
|
||||
|
||||
[*Contract assertions*](#def:contract_assertion "6.11.1 General [basic.contract.general]") allow the programmer to specify
|
||||
properties of the state of the program
|
||||
that are expected to hold at
|
||||
certain points during execution[.](#1.sentence-1)
|
||||
|
||||
Contract assertions are introduced by[*precondition-specifier*](dcl.contract.func#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")*s*,[*postcondition-specifier*](dcl.contract.func#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")*s* ([[dcl.contract.func]](dcl.contract.func "9.4.1 General")), and[*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]")*s* ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion statement"))[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7578)
|
||||
|
||||
Each contract assertion has a [*contract-assertion predicate*](#def:predicate,contract-assertion "6.11.1 General [basic.contract.general]"),
|
||||
which is an expression of type bool[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The value of the predicate is used to identify program states that are
|
||||
expected[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7587)
|
||||
|
||||
An invocation of the macro va_start ([[cstdarg.syn]](cstdarg.syn "17.14.2 Header <cstdarg> synopsis"))
|
||||
shall not be a subexpression
|
||||
of the predicate of a contract assertion,
|
||||
no diagnostic required[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7593)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Within the predicate of a contract assertion,[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")*s* referring to
|
||||
variables declared outside the contract assertion
|
||||
are const ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")),this is a pointer to const ([[expr.prim.this]](expr.prim.this "7.5.3 This")),
|
||||
and the result object can be named
|
||||
if a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")) has been specified[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
60
cppdraft/basic/contract/handler.md
Normal file
60
cppdraft/basic/contract/handler.md
Normal file
@@ -0,0 +1,60 @@
|
||||
[basic.contract.handler]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.11 Contract assertions [[basic.contract]](basic.contract#handler)
|
||||
|
||||
### 6.11.3 Contract-violation handler [basic.contract.handler]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7956)
|
||||
|
||||
The [*contract-violation handler*](#def:contract-violation_handler "6.11.3 Contract-violation handler [basic.contract.handler]") of a program is a function named::handle_contract_violation[.](#1.sentence-1)
|
||||
|
||||
The contract-violation handler
|
||||
shall have a single parameter
|
||||
of type
|
||||
âlvalue reference to const std::contracts::contract_violationâ
|
||||
and shall return void[.](#1.sentence-2)
|
||||
|
||||
The contract-violation handler
|
||||
may have a non-throwing exception specification[.](#1.sentence-3)
|
||||
|
||||
The implementation
|
||||
shall provide a definition of the contract-violation handler,
|
||||
called the [*default contract-violation handler*](#def:contract-violation_handler,default "6.11.3 Contract-violation handler [basic.contract.handler]")[.](#1.sentence-4)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
No declaration
|
||||
for the default contract-violation handler
|
||||
is provided by
|
||||
any standard library header[.](#1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7979)
|
||||
|
||||
*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[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7989)
|
||||
|
||||
It isimplementation-defined
|
||||
whether the contract-violation handler
|
||||
is replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5 Replaceable function definitions"))[.](#3.sentence-1)
|
||||
|
||||
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[.](#3.sentence-2)
|
||||
214
cppdraft/basic/def.md
Normal file
214
cppdraft/basic/def.md
Normal file
@@ -0,0 +1,214 @@
|
||||
[basic.def]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.2 Declarations and definitions [basic.def]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L166)
|
||||
|
||||
A declaration ([[basic.pre]](basic.pre "6.1 Preamble")) may (re)introduce
|
||||
one or more names and/or entities into a translation
|
||||
unit[.](#1.sentence-1)
|
||||
|
||||
If so, the
|
||||
declaration specifies the interpretation and semantic properties of these names[.](#1.sentence-2)
|
||||
|
||||
A declaration of an entity X is
|
||||
a redeclaration of X if another declaration of X is reachable from it ([[module.reach]](module.reach "10.7 Reachability"));
|
||||
otherwise, it is a [*first declaration*](#def:declaration,first "6.2 Declarations and definitions [basic.def]")[.](#1.sentence-3)
|
||||
|
||||
A declaration may also have effects including:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
a static assertion ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
controlling template instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
guiding template argument deduction for constructors ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3 Deduction guides")),
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
use of [attributes](dcl.attr "9.13 Attributes [dcl.attr]"), and
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
nothing (in the case of an [*empty-declaration*](dcl.pre#nt:empty-declaration "9.1 Preamble [dcl.pre]"))[.](#1.sentence-4)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L188)
|
||||
|
||||
Each entity declared by a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") is
|
||||
also [*defined*](#def:define "6.2 Declarations and definitions [basic.def]") by that declaration unless:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
it declares a function
|
||||
without specifying the function's body ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions")),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
it contains
|
||||
theextern specifier ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers")) or a[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")[15](#footnote-15 "Appearing inside the brace-enclosed declaration-seq in a linkage-specification does not affect whether a declaration is a definition.") ([[dcl.link]](dcl.link "9.12 Linkage specifications"))
|
||||
and neither an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") nor a[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]"),
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
it declares a non-inline static data member in a class
|
||||
definition ([[class.mem]](class.mem "11.4 Class members"), [[class.static]](class.static "11.4.9 Static members")),
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
it declares a static data member outside a class definition
|
||||
and the variable was defined within the class with the constexpr specifier ([[class.static.data]](class.static.data "11.4.9.3 Static data members")) (this usage is deprecated; see [[depr.static.constexpr]](depr.static.constexpr "D.7 Redeclaration of static constexpr data members")),
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
it is an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") ([[class.name]](class.name "11.3 Class names")),
|
||||
|
||||
- [(2.6)](#2.6)
|
||||
|
||||
it is an[*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]") ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
|
||||
- [(2.7)](#2.7)
|
||||
|
||||
it is a[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(2.8)](#2.8)
|
||||
|
||||
it is a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) in a functiondeclarator that is not the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]"),
|
||||
|
||||
- [(2.9)](#2.9)
|
||||
|
||||
it is atypedef declaration ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),
|
||||
|
||||
- [(2.10)](#2.10)
|
||||
|
||||
it is
|
||||
an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),
|
||||
|
||||
- [(2.11)](#2.11)
|
||||
|
||||
it is
|
||||
a [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]") ([[namespace.alias]](namespace.alias "9.9.3 Namespace alias")),
|
||||
|
||||
- [(2.12)](#2.12)
|
||||
|
||||
it is
|
||||
a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")),
|
||||
|
||||
- [(2.13)](#2.13)
|
||||
|
||||
it is
|
||||
a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]") ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3 Deduction guides")),
|
||||
|
||||
- [(2.14)](#2.14)
|
||||
|
||||
it is
|
||||
a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||||
|
||||
- [(2.15)](#2.15)
|
||||
|
||||
it is
|
||||
a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]"),
|
||||
|
||||
- [(2.16)](#2.16)
|
||||
|
||||
it is an[*attribute-declaration*](dcl.pre#nt:attribute-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||||
|
||||
- [(2.17)](#2.17)
|
||||
|
||||
it is an[*empty-declaration*](dcl.pre#nt:empty-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||||
|
||||
- [(2.18)](#2.18)
|
||||
|
||||
it is
|
||||
a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") ([[namespace.udir]](namespace.udir "9.9.4 Using namespace directive")),
|
||||
|
||||
- [(2.19)](#2.19)
|
||||
|
||||
it is
|
||||
a [*using-enum-declaration*](enum.udecl#nt:using-enum-declaration "9.8.2 The using enum declaration [enum.udecl]") ([[enum.udecl]](enum.udecl "9.8.2 The using enum declaration")),
|
||||
|
||||
- [(2.20)](#2.20)
|
||||
|
||||
it is
|
||||
a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble"))
|
||||
whose [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") is not followed by
|
||||
either a [*concept-definition*](temp.concept#nt:concept-definition "13.7.9 Concept definitions [temp.concept]") or a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") that defines a function, a class, a variable, or a static data member,
|
||||
|
||||
- [(2.21)](#2.21)
|
||||
|
||||
it is
|
||||
an explicit instantiation declaration ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")), or
|
||||
|
||||
- [(2.22)](#2.22)
|
||||
|
||||
it is
|
||||
an [explicit specialization](temp.expl.spec "13.9.4 Explicit specialization [temp.expl.spec]") whose[*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") is not a definition[.](#2.sentence-1)
|
||||
|
||||
A declaration is said to be a [*definition*](#def:definition "6.2 Declarations and definitions [basic.def]") of each entity that it defines[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
All but one of the following are definitions:int a; // defines aextern const int c = 1; // defines cint f(int x) { return x+a; } // defines f and defines xstruct S { int a; int b; }; // defines S, S::a, and S::bstruct X { // defines Xint x; // defines non-static data member xstatic int y; // declares static data member y X(): x(0) { } // defines a constructor of X};int X::y = 1; // defines X::yenum { up, down }; // defines up and downnamespace N { int d; } // defines N and N::d X anX; // defines anX whereas these are just declarations:extern int a; // declares aextern const int c; // declares cint f(int); // declares fstruct S; // declares Stypedef int Int; // declares Intnamespace N1 = N; // declares N1extern X anotherX; // declares anotherXusing N::d; // declares d
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L304)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
In some circumstances, C++ implementations implicitly define the
|
||||
default constructor ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors")),
|
||||
copy constructor, move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")),
|
||||
copy assignment operator, move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||||
or [destructor](class.dtor "11.4.7 Destructors [class.dtor]") member functions[.](#3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
Given#include <string>struct C { std::string s; // std::string is the standard library class ([[string.classes]](string.classes "27.4 String classes"))};
|
||||
|
||||
int main() { C a;
|
||||
C b = a;
|
||||
b = a;} the implementation will implicitly define functions to make the
|
||||
definition of C equivalent tostruct 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*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L345)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
A class name can also be implicitly declared by an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L351)
|
||||
|
||||
In the definition of an object,
|
||||
the type of that object shall not be
|
||||
an incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1 General")),
|
||||
an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract classes")), or
|
||||
a (possibly multidimensional) array thereof[.](#5.sentence-1)
|
||||
|
||||
[15)](#footnote-15)[15)](#footnoteref-15)
|
||||
|
||||
Appearing inside the brace-enclosed[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]") in a [*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]") does
|
||||
not affect whether a declaration is a definition[.](#footnote-15.sentence-1)
|
||||
669
cppdraft/basic/def/odr.md
Normal file
669
cppdraft/basic/def/odr.md
Normal file
@@ -0,0 +1,669 @@
|
||||
[basic.def.odr]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.3 One-definition rule [basic.def.odr]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L366)
|
||||
|
||||
Each of the following is termed a [*definable item*](#def:item,definable "6.3 One-definition rule [basic.def.odr]"):
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
a class type ([[class]](class "11 Classes")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
an enumeration type ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
a function ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
a variable ([[basic.pre]](basic.pre "6.1 Preamble")),
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
a templated entity ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
a default argument for a parameter
|
||||
(for a function in a given scope) ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")), or
|
||||
|
||||
- [(1.7)](#1.7)
|
||||
|
||||
a default template argument ([[temp.param]](temp.param "13.2 Template parameters"))[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L379)
|
||||
|
||||
No translation unit shall contain more than one definition of any
|
||||
definable item[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L383)
|
||||
|
||||
An expression or conversion is [*potentially evaluated*](#def:potentially_evaluated "6.3 One-definition rule [basic.def.odr]") unless it is
|
||||
an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context dependence")),
|
||||
a subexpression thereof, or
|
||||
a conversion in an initialization or conversion sequence in such a context[.](#3.sentence-1)
|
||||
|
||||
The set of [*potential results*](#def:potential_results "6.3 One-definition rule [basic.def.odr]") of an expression E is
|
||||
defined as follows:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
If E is
|
||||
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") ([[expr.prim.id]](expr.prim.id "7.5.5 Names")) or
|
||||
a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](expr.prim.splice "7.5.9 Expression splicing")), the set
|
||||
contains only E[.](#3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
If E is a [subscripting](expr.sub "7.6.1.2 Subscripting [expr.sub]") operation with
|
||||
an array operand, the set contains the potential results of that operand[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
If E is a class member access
|
||||
expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")) of the formE1 . templateopt E2 naming a non-static data member,
|
||||
the set contains the potential results of E1[.](#3.3.sentence-1)
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
If E is a class member access expression
|
||||
naming a static data member,
|
||||
the set contains the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") designating the data member[.](#3.4.sentence-1)
|
||||
|
||||
- [(3.5)](#3.5)
|
||||
|
||||
If E is a [pointer-to-member expression](expr.mptr.oper "7.6.4 Pointer-to-member operators [expr.mptr.oper]") of the formE1 .* E2,
|
||||
the set contains the potential results of E1[.](#3.5.sentence-1)
|
||||
|
||||
- [(3.6)](#3.6)
|
||||
|
||||
If E has the form (E1), the set contains the
|
||||
potential results of E1[.](#3.6.sentence-1)
|
||||
|
||||
- [(3.7)](#3.7)
|
||||
|
||||
If E is a glvalue [conditional expression](expr.cond "7.6.16 Conditional operator [expr.cond]"),
|
||||
the set is the union of the sets of
|
||||
potential results of the second and third operands[.](#3.7.sentence-1)
|
||||
|
||||
- [(3.8)](#3.8)
|
||||
|
||||
If E is a [comma expression](expr.comma "7.6.20 Comma operator [expr.comma]"), the set
|
||||
contains the potential results of the right operand[.](#3.8.sentence-1)
|
||||
|
||||
- [(3.9)](#3.9)
|
||||
|
||||
Otherwise, the set is empty[.](#3.9.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
This set is a (possibly-empty) set of[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")*s* and [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]")*s*,
|
||||
each of which is either E or a subexpression of E[.](#3.sentence-3)
|
||||
|
||||
[*Example [1](#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 secondS::x subexpression[.](#3.sentence-4)
|
||||
|
||||
The set of potential results of the initializer of o contains
|
||||
the subexpression [:^^S::x:][.](#3.sentence-5)
|
||||
|
||||
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 requiredint o = [:^^S::x:]; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L438)
|
||||
|
||||
A function is [*named by*](#def:function,named_by_expression_or_conversion "6.3 One-definition rule [basic.def.odr]") an expression or conversion as follows:
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
A function is named by an expression or conversion
|
||||
if it is the selected member
|
||||
of an overload set ([[basic.lookup]](basic.lookup "6.5 Name lookup"), [[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address of an overload set"))
|
||||
in an overload resolution performed
|
||||
as part of forming that expression or conversion,
|
||||
and either
|
||||
it is not a pure virtual function or
|
||||
the expression is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") naming the function with
|
||||
an explicitly qualified name
|
||||
that does not form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators"))[.](#4.1.sentence-1)
|
||||
[*Note [2](#note-2)*:
|
||||
This covers
|
||||
taking the address of functions ([[conv.func]](conv.func "7.3.4 Function-to-pointer conversion"), [[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")),
|
||||
calls to named functions ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||||
operator overloading ([[over]](over "12 Overloading")),
|
||||
user-defined conversions ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")),
|
||||
allocation functions for [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), as well as
|
||||
non-default initialization ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#4.1.sentence-2)
|
||||
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]](class.copy.elision "11.9.6 Copy/move elision"))[.](#4.1.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
A deallocation function for a class
|
||||
is named by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") if it is the single matching deallocation function
|
||||
for the allocation function selected by overload resolution,
|
||||
as specified in [[expr.new]](expr.new "7.6.2.8 New")[.](#4.2.sentence-1)
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
A deallocation function for a class
|
||||
is named by a [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]") if it is the selected usual deallocation function
|
||||
as specified in [[expr.delete]](expr.delete "7.6.2.9 Delete") and [[class.free]](class.free "11.4.11 Allocation and deallocation functions")[.](#4.3.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L478)
|
||||
|
||||
A variable is named by an expression
|
||||
if the expression is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](expr.prim.splice "7.5.9 Expression splicing"))
|
||||
that designates it[.](#5.sentence-1)
|
||||
|
||||
A variable x that is named by a
|
||||
potentially-evaluated expression N that appears at a point P is [*odr-used*](#def:odr-use "6.3 One-definition rule [basic.def.odr]") by N unless
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
x is a reference
|
||||
that is usable in constant expressions at P ([[expr.const]](expr.const "7.7 Constant expressions")) or
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
N is an element of the set of potential results of an expression E, where
|
||||
* [(5.2.1)](#5.2.1)
|
||||
|
||||
E is a discarded-value expression ([[expr.context]](expr.context "7.2.3 Context dependence"))
|
||||
to which the lvalue-to-rvalue conversion is not applied or
|
||||
|
||||
* [(5.2.2)](#5.2.2)
|
||||
|
||||
x is a non-volatile object
|
||||
that is usable in constant expressions at P and
|
||||
has no mutable subobjects and
|
||||
+
|
||||
[(5.2.2.1)](#5.2.2.1)
|
||||
E is a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))
|
||||
naming a non-static data member of reference type and
|
||||
whose object expression has non-volatile-qualified type or
|
||||
|
||||
+
|
||||
[(5.2.2.2)](#5.2.2.2)
|
||||
the lvalue-to-rvalue conversion ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")) is applied to E andE has non-volatile-qualified non-class type
|
||||
|
||||
[*Example [2](#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 aint _ = f(cond ? a.x : r.x); // does not odr-use a or rint x, y; constexpr B b1 = {x}, b2 = {y}; // odr-uses x and yint _ = g(cond ? b1.r : b2.r); // does not odr-use b1 or b2int _ = ((cond ? x : y), 0); // does not odr-use x or yreturn [] {return b1.r; // error: b1 is odr-used here because the object// referred to by b1.r is not constexpr-referenceable here}();} â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L539)
|
||||
|
||||
A structured binding is named by an expression
|
||||
if that expression is either an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or
|
||||
a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") that designates that structured binding[.](#6.sentence-1)
|
||||
|
||||
A structured binding is odr-used
|
||||
if it is named by a potentially-evaluated expression[.](#6.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L547)
|
||||
|
||||
*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]](expr.prim.id.general "7.5.5.1 General")))[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L552)
|
||||
|
||||
A virtual member
|
||||
function is odr-used if it is not pure[.](#8.sentence-1)
|
||||
|
||||
A function is odr-used if it is named by
|
||||
a potentially-evaluated expression or conversion[.](#8.sentence-2)
|
||||
|
||||
A non-placement allocation or deallocation
|
||||
function for a class is odr-used by the definition of a constructor of that
|
||||
class[.](#8.sentence-3)
|
||||
|
||||
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]](class.dtor "11.4.7 Destructors"))[.](#8.sentence-4)[16](#footnote-16 "An implementation is not required to call allocation and deallocation functions from constructors or destructors; however, this is a permissible implementation technique.")
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L570)
|
||||
|
||||
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]](class.copy.assign "11.4.6 Copy/move assignment operator")[.](#9.sentence-1)
|
||||
|
||||
A constructor for a class is odr-used as specified
|
||||
in [[dcl.init]](dcl.init "9.5 Initializers")[.](#9.sentence-2)
|
||||
|
||||
A destructor for a class is odr-used if it is[potentially invoked](class.dtor#def:potentially_invoked "11.4.7 Destructors [class.dtor]")[.](#9.sentence-3)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L579)
|
||||
|
||||
A local entity ([[basic.pre]](basic.pre "6.1 Preamble"))
|
||||
is [*odr-usable*](#def:odr-usable "6.3 One-definition rule [basic.def.odr]") in a scope ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")) if
|
||||
|
||||
- [(10.1)](#10.1)
|
||||
|
||||
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
|
||||
|
||||
- [(10.2)](#10.2)
|
||||
|
||||
for each intervening scope ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))
|
||||
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
|
||||
* [(10.2.1)](#10.2.1)
|
||||
|
||||
the intervening scope is a block scope,
|
||||
|
||||
* [(10.2.2)](#10.2.2)
|
||||
|
||||
the intervening scope is a contract-assertion scope ([[basic.scope.contract]](basic.scope.contract "6.4.10 Contract-assertion scope")),
|
||||
|
||||
* [(10.2.3)](#10.2.3)
|
||||
|
||||
the intervening scope is the function parameter scope of
|
||||
a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") or [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]"), or
|
||||
|
||||
* [(10.2.4)](#10.2.4)
|
||||
|
||||
the intervening scope is the lambda scope of
|
||||
a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") that has a [*simple-capture*](expr.prim.lambda.capture#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") naming the entity or has a [*capture-default*](expr.prim.lambda.capture#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]"), and
|
||||
the block scope of the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") is also an intervening scope[.](#10.sentence-1)
|
||||
|
||||
If a local entity is odr-used
|
||||
in a scope in which it is not odr-usable,
|
||||
the program is ill-formed[.](#10.sentence-2)
|
||||
|
||||
[*Example [3](#example-3)*: void f(int n) {[] { n = 1; }; // error: n is not odr-usable due to intervening lambda-expressionstruct 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*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")[&] { [n]{ return n; }; }; // OK} â *end example*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L625)
|
||||
|
||||
[*Example [4](#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*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L646)
|
||||
|
||||
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](stmt.if#def:discarded_statement "8.5.2 The if statement [stmt.if]"); no diagnostic required[.](#12.sentence-1)
|
||||
|
||||
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.default.ctor "11.4.5.2 Default constructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"),[[class.dtor]](class.dtor "11.4.7 Destructors"), and [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator"))[.](#12.sentence-2)
|
||||
|
||||
[*Example [5](#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[.](#12.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L670)
|
||||
|
||||
A [*definition domain*](#def:definition_domain "6.3 One-definition rule [basic.def.odr]") is
|
||||
a [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") or
|
||||
the portion of a translation unit
|
||||
excluding its [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") (if any)[.](#13.sentence-1)
|
||||
|
||||
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[.](#13.sentence-2)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L679)
|
||||
|
||||
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[.](#14.sentence-1)
|
||||
|
||||
[*Example [6](#example-6)*:
|
||||
|
||||
The following complete translation unit is well-formed,
|
||||
even though it never defines X:struct X; // declare X as a struct typestruct X* x1; // use X in pointer formation X* x2; // use X in pointer formation
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The rules for declarations and expressions
|
||||
describe in which contexts complete class types are required[.](#14.sentence-3)
|
||||
|
||||
A class
|
||||
type T must be complete if
|
||||
|
||||
- [(14.1)](#14.1)
|
||||
|
||||
an object of type T is [defined](basic.def "6.2 Declarations and definitions [basic.def]"), or
|
||||
|
||||
- [(14.2)](#14.2)
|
||||
|
||||
a non-static class [data member](class.mem#def:data_member "11.4 Class members [class.mem]") of
|
||||
type T is declared, or
|
||||
|
||||
- [(14.3)](#14.3)
|
||||
|
||||
T is used as the allocated type or array element type in a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")), or
|
||||
|
||||
- [(14.4)](#14.4)
|
||||
|
||||
an lvalue-to-rvalue conversion is applied to
|
||||
a glvalue referring
|
||||
to an object of type T ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")), or
|
||||
|
||||
- [(14.5)](#14.5)
|
||||
|
||||
an expression is converted (either implicitly or explicitly) to
|
||||
type T ([[conv]](conv "7.3 Standard conversions"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")), or
|
||||
|
||||
- [(14.6)](#14.6)
|
||||
|
||||
an expression that is not a null pointer constant, and has type
|
||||
other than cv void*, is converted to the type pointer to T or reference to T using a standard conversion ([[conv]](conv "7.3 Standard conversions")),
|
||||
a dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")) or
|
||||
a static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")), or
|
||||
|
||||
- [(14.7)](#14.7)
|
||||
|
||||
a class member access operator is applied to an expression of typeT ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), or
|
||||
|
||||
- [(14.8)](#14.8)
|
||||
|
||||
the typeid operator ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")) or thesizeof operator ([[expr.sizeof]](expr.sizeof "7.6.2.5 Sizeof")) is applied to an operand of
|
||||
type T, or
|
||||
|
||||
- [(14.9)](#14.9)
|
||||
|
||||
a function with a return type or argument type of type T is defined ([[basic.def]](basic.def "6.2 Declarations and definitions")) or [called](expr.call "7.6.1.3 Function call [expr.call]"), or
|
||||
|
||||
- [(14.10)](#14.10)
|
||||
|
||||
a class with a base class of type T is
|
||||
defined ([[class.derived]](class.derived "11.7 Derived classes")), or
|
||||
|
||||
- [(14.11)](#14.11)
|
||||
|
||||
an lvalue of type T is assigned to ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators")), or
|
||||
|
||||
- [(14.12)](#14.12)
|
||||
|
||||
the type T is the subject of analignof expression ([[expr.alignof]](expr.alignof "7.6.2.6 Alignof")), or
|
||||
|
||||
- [(14.13)](#14.13)
|
||||
|
||||
an [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") has type T, reference toT, or pointer to T ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#14.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L730)
|
||||
|
||||
If a definable item D is defined in a translation unit
|
||||
by an injected declaration X ([[expr.const]](expr.const "7.7 Constant expressions")) and
|
||||
another translation unit contains a definition of D,
|
||||
that definition shall be an injected declaration
|
||||
having the same characteristic sequence as X;
|
||||
a diagnostic is required only if D is attached to a named module and
|
||||
a prior definition is reachable at the point where a later definition occurs[.](#15.sentence-1)
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L739)
|
||||
|
||||
For any other definable item D with definitions in multiple translation units,
|
||||
|
||||
- [(16.1)](#16.1)
|
||||
|
||||
if D is a non-inline non-templated function or variable, or
|
||||
|
||||
- [(16.2)](#16.2)
|
||||
|
||||
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[.](#16.sentence-1)
|
||||
|
||||
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[.](#16.sentence-2)
|
||||
|
||||
- [(16.3)](#16.3)
|
||||
|
||||
Each such definition
|
||||
shall not be attached to a named module ([[module.unit]](module.unit "10.1 Module units and purviews"))[.](#16.3.sentence-1)
|
||||
|
||||
- [(16.4)](#16.4)
|
||||
|
||||
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*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")[.](#16.4.sentence-1)
|
||||
|
||||
- [(16.5)](#16.5)
|
||||
|
||||
In each such definition, corresponding names, looked up
|
||||
according to [[basic.lookup]](basic.lookup "6.5 Name lookup"), shall denote the same entity, after
|
||||
overload resolution ([[over.match]](over.match "12.2 Overload resolution")) and after matching of partial
|
||||
template specializations ([[temp.spec.partial.match]](temp.spec.partial.match "13.7.6.2 Matching of partial specializations")), except that a name can refer to
|
||||
* [(16.5.1)](#16.5.1)
|
||||
|
||||
a non-volatile const object with internal or no linkage if the object
|
||||
+
|
||||
[(16.5.1.1)](#16.5.1.1)
|
||||
has the same literal type in all definitions of D,
|
||||
|
||||
+
|
||||
[(16.5.1.2)](#16.5.1.2)
|
||||
is initialized with a [constant expression](expr.const "7.7 Constant expressions [expr.const]"),
|
||||
|
||||
+
|
||||
[(16.5.1.3)](#16.5.1.3)
|
||||
is not odr-used in any definition of D, and
|
||||
|
||||
+
|
||||
[(16.5.1.4)](#16.5.1.4)
|
||||
has the same value in all definitions of D,
|
||||
|
||||
or
|
||||
|
||||
* [(16.5.2)](#16.5.2)
|
||||
|
||||
a reference with internal or no linkage
|
||||
initialized with a constant expression such that
|
||||
the reference refers to the same object or function in all definitions of D[.](#16.5.sentence-1)
|
||||
|
||||
- [(16.6)](#16.6)
|
||||
|
||||
In each such definition, except within
|
||||
the default arguments and default template arguments of D,
|
||||
corresponding [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* shall have
|
||||
the same closure type (see below)[.](#16.6.sentence-1)
|
||||
|
||||
- [(16.7)](#16.7)
|
||||
|
||||
In each such definition, corresponding entities shall have the
|
||||
same language linkage[.](#16.7.sentence-1)
|
||||
|
||||
- [(16.8)](#16.8)
|
||||
|
||||
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[.](#16.8.sentence-1)
|
||||
|
||||
- [(16.9)](#16.9)
|
||||
|
||||
In each such definition,
|
||||
corresponding manifestly constant-evaluated expressions
|
||||
that are not value-dependent
|
||||
shall have the same value ([[expr.const]](expr.const "7.7 Constant expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4 Value-dependent expressions"))[.](#16.9.sentence-1)
|
||||
|
||||
- [(16.10)](#16.10)
|
||||
|
||||
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[.](#16.10.sentence-1)
|
||||
|
||||
- [(16.11)](#16.11)
|
||||
|
||||
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*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]"), or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") 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)[.](#16.11.sentence-1)
|
||||
|
||||
- [(16.12)](#16.12)
|
||||
|
||||
In each such definition,
|
||||
corresponding [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")*s* ([[expr.reflect]](expr.reflect "7.6.2.10 The reflection operator"))
|
||||
compute equivalent values ([[expr.eq]](expr.eq "7.6.10 Equality operators"))[.](#16.12.sentence-1)
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L824)
|
||||
|
||||
For the purposes of the preceding requirements:
|
||||
|
||||
- [(17.1)](#17.1)
|
||||
|
||||
If D is a class with an implicitly-declared
|
||||
constructor ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")),
|
||||
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[.](#17.1.sentence-1)
|
||||
[*Example [7](#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*]
|
||||
|
||||
- [(17.2)](#17.2)
|
||||
|
||||
If D is a class with
|
||||
a defaulted three-way comparison operator function ([[class.spaceship]](class.spaceship "11.10.3 Three-way comparison")),
|
||||
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[.](#17.2.sentence-1)
|
||||
|
||||
- [(17.3)](#17.3)
|
||||
|
||||
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]](temp.dep "13.8.3 Dependent names"))[.](#17.3.sentence-1)
|
||||
|
||||
[18](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L875)
|
||||
|
||||
These requirements also apply to corresponding entities
|
||||
defined within each definition of D (including the closure types of [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s*,
|
||||
but excluding entities defined within default arguments or
|
||||
default template arguments of either D or
|
||||
an entity not defined within D)[.](#18.sentence-1)
|
||||
|
||||
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[.](#18.sentence-2)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The entity is still declared in multiple translation units, and [[basic.link]](basic.link "6.7 Program and linkage") still applies to these declarations[.](#18.sentence-3)
|
||||
|
||||
In particular,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions"))
|
||||
appearing in the type of D can result
|
||||
in the different declarations having distinct types, and[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* appearing in a default argument of D might still denote different types in different translation units[.](#18.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[19](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L895)
|
||||
|
||||
[*Example [8](#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[.](#19.sentence-1)
|
||||
|
||||
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*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") closure type[.](#19.sentence-2)
|
||||
|
||||
The definition of X can appear
|
||||
in multiple translation units of a valid program;
|
||||
the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* defined within
|
||||
the default argument of X::h within the definition of X denote the same closure type in each translation unit[.](#19.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[20](#20)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L925)
|
||||
|
||||
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]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
those unnamed enumeration types shall be the same; no diagnostic required[.](#20.sentence-1)
|
||||
|
||||
[16)](#footnote-16)[16)](#footnoteref-16)
|
||||
|
||||
An implementation is not required
|
||||
to call allocation and
|
||||
deallocation functions from constructors or destructors; however, this
|
||||
is a permissible implementation technique[.](#footnote-16.sentence-1)
|
||||
1780
cppdraft/basic/exec.md
Normal file
1780
cppdraft/basic/exec.md
Normal file
File diff suppressed because it is too large
Load Diff
102
cppdraft/basic/extended/fp.md
Normal file
102
cppdraft/basic/extended/fp.md
Normal file
@@ -0,0 +1,102 @@
|
||||
[basic.extended.fp]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.9 Types [[basic.types]](basic.types#basic.extended.fp)
|
||||
|
||||
### 6.9.3 Optional extended floating-point types [basic.extended.fp]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5705)
|
||||
|
||||
If the implementation supports an extended floating-point type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))
|
||||
whose properties are specified by
|
||||
the ISO/IEC 60559 floating-point interchange format binary16,
|
||||
then the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::float16_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
|
||||
the macro __STDCPP_FLOAT16_T__ is defined ([[cpp.predefined]](cpp.predefined "15.12 Predefined macro names")), and
|
||||
the floating-point literal suffixes f16 and F16 are supported ([[lex.fcon]](lex.fcon "5.13.4 Floating-point literals"))[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5715)
|
||||
|
||||
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*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::float32_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
|
||||
the macro __STDCPP_FLOAT32_T__ is defined, and
|
||||
the floating-point literal suffixes f32 and F32 are supported[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5724)
|
||||
|
||||
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*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::float64_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
|
||||
the macro __STDCPP_FLOAT64_T__ is defined, and
|
||||
the floating-point literal suffixes f64 and F64 are supported[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5733)
|
||||
|
||||
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*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::float128_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
|
||||
the macro __STDCPP_FLOAT128_T__ is defined, and
|
||||
the floating-point literal suffixes f128 and F128 are supported[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5742)
|
||||
|
||||
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*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::bfloat16_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
|
||||
the macro __STDCPP_BFLOAT16_T__ is defined, and
|
||||
the floating-point literal suffixes bf16 and BF16 are supported[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5755)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A summary of the parameters for each type is given in Table [15](#tab:basic.extended.fp "Table 15: Properties of named extended floating-point types")[.](#6.sentence-1)
|
||||
|
||||
The precision p includes the implicit 1 bit at the beginning of the significand,
|
||||
so the storage used for the significand is pâ1 bits[.](#6.sentence-2)
|
||||
|
||||
ISO/IEC 60559 does not assign a name for a type
|
||||
having the parameters specified for std::bfloat16_t[.](#6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Table [15](#tab:basic.extended.fp) — Properties of named extended floating-point types [[tab:basic.extended.fp]](./tab:basic.extended.fp)
|
||||
|
||||
| [ð](#tab:basic.extended.fp-row-1)<br>**Parameter** | **float16_t** | **float32_t** | **float64_t** | **float128_t** | **bfloat16_t** |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| [ð](#tab:basic.extended.fp-row-2)<br>ISO/IEC 60559 name | binary16 | binary32 | binary64 | binary128 | |
|
||||
| [ð](#tab:basic.extended.fp-row-3)<br>k, storage width in bits | 16 | 32 | 64 | 128 | 16 |
|
||||
| [ð](#tab:basic.extended.fp-row-4)<br>p, precision in bits | 11 | 24 | 53 | 113 | 8 |
|
||||
| [ð](#tab:basic.extended.fp-row-5)<br>emax, maximum exponent | 15 | 127 | 1023 | 16383 | 127 |
|
||||
| [ð](#tab:basic.extended.fp-row-6)<br>w, exponent field width in bits | 5 | 8 | 11 | 15 | 8 |
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5777)
|
||||
|
||||
*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>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") 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[.](#7.sentence-1)
|
||||
524
cppdraft/basic/fundamental.md
Normal file
524
cppdraft/basic/fundamental.md
Normal file
@@ -0,0 +1,524 @@
|
||||
[basic.fundamental]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.9 Types [[basic.types]](basic.types#basic.fundamental)
|
||||
|
||||
### 6.9.2 Fundamental types [basic.fundamental]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5300)
|
||||
|
||||
There are five [*standard signed integer types*](#def:type,standard_signed_integer "6.9.2 Fundamental types [basic.fundamental]"):âsigned charâ, âshort intâ, âintâ,
|
||||
âlong intâ, and âlong long intâ[.](#1.sentence-1)
|
||||
|
||||
In
|
||||
this list, each type provides at least as much storage as those
|
||||
preceding it in the list[.](#1.sentence-2)
|
||||
|
||||
There may also be implementation-defined[*extended signed integer types*](#def:type,extended_signed_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#1.sentence-3)
|
||||
|
||||
The standard and extended signed integer types are collectively called[*signed integer types*](#def:type,signed_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#1.sentence-4)
|
||||
|
||||
The range of representable values for a signed integer type isâ2Nâ1 to 2Nâ1â1 (inclusive),
|
||||
where N is called the [*width*](simd.general#def:width "29.10.1 General [simd.general]") of the type[.](#1.sentence-5)
|
||||
|
||||
[*Note [1](#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[.](#1.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5326)
|
||||
|
||||
For each of the standard signed integer types,
|
||||
there exists a corresponding (but different)[*standard unsigned integer type*](#def:type,standard_unsigned_integer "6.9.2 Fundamental types [basic.fundamental]"):âunsigned charâ, âunsigned short intâ,
|
||||
âunsigned intâ, âunsigned long intâ, and
|
||||
âunsigned long long intâ[.](#2.sentence-1)
|
||||
|
||||
Likewise, for each of the extended signed integer types,
|
||||
there exists a corresponding [*extended unsigned integer type*](#def:type,extended_unsigned_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#2.sentence-2)
|
||||
|
||||
The standard and extended unsigned integer types
|
||||
are collectively called [*unsigned integer types*](#def:type,unsigned_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#2.sentence-3)
|
||||
|
||||
An unsigned integer type has the same width *N* as the corresponding signed integer type[.](#2.sentence-4)
|
||||
|
||||
The range of representable values for the unsigned type is0 to 2Nâ1 (inclusive);
|
||||
arithmetic for the unsigned type is performed modulo 2N[.](#2.sentence-5)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Unsigned arithmetic does not overflow[.](#2.sentence-6)
|
||||
|
||||
Overflow for signed arithmetic yields undefined behavior ([[expr.pre]](expr.pre "7.1 Preamble"))[.](#2.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5354)
|
||||
|
||||
An unsigned integer type has the same
|
||||
object representation,
|
||||
value representation, and
|
||||
alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment"))
|
||||
as the corresponding signed integer type[.](#3.sentence-1)
|
||||
|
||||
For each value x of a signed integer type,
|
||||
the value of the corresponding unsigned integer type
|
||||
congruent to x modulo 2N has the same value
|
||||
of corresponding bits in its value representation[.](#3.sentence-2)[30](#footnote-30 "This is also known as two's complement representation.")
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
The value â1 of a signed integer type has the same representation as
|
||||
the largest value of the corresponding unsigned type[.](#3.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
Table [14](#tab:basic.fundamental.width) — Minimum width [[tab:basic.fundamental.width]](./tab:basic.fundamental.width)
|
||||
|
||||
| [ð](#tab:basic.fundamental.width-row-1)<br>**Type** | **Minimum width N** |
|
||||
| --- | --- |
|
||||
| [ð](#tab:basic.fundamental.width-row-2)<br>signed char | 8 |
|
||||
| [ð](#tab:basic.fundamental.width-row-3)<br>short int | 16 |
|
||||
| [ð](#tab:basic.fundamental.width-row-4)<br>int | 16 |
|
||||
| [ð](#tab:basic.fundamental.width-row-5)<br>long int | 32 |
|
||||
| [ð](#tab:basic.fundamental.width-row-6)<br>long long int | 64 |
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5385)
|
||||
|
||||
The width of each standard signed integer type
|
||||
shall not be less than the values specified in Table [14](#tab:basic.fundamental.width "Table 14: Minimum width")[.](#4.sentence-1)
|
||||
|
||||
The value representation of a signed or unsigned integer type
|
||||
comprises N bits, where N is the respective width[.](#4.sentence-2)
|
||||
|
||||
Each set of values for any padding bits ([[basic.types.general]](basic.types.general "6.9.1 General"))
|
||||
in the object representation are
|
||||
alternative representations of the value specified by the value representation[.](#4.sentence-3)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Padding bits have unspecified value, but cannot cause traps[.](#4.sentence-4)
|
||||
|
||||
In contrast, see ISO/IEC 9899:2024 6.2.6.2[.](#4.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The signed and unsigned integer types satisfy
|
||||
the constraints given in ISO/IEC 9899:2024 5.2.4.2.1[.](#4.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Except as specified above,
|
||||
the width of a signed or unsigned integer type isimplementation-defined[.](#4.sentence-7)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5405)
|
||||
|
||||
Each value x of an unsigned integer type with width N has
|
||||
a unique representation x=x020+x121+â¦+xNâ12Nâ1,
|
||||
where each coefficient xi is either 0 or 1;
|
||||
this is called the [*base-2 representation*](#def:base-2_representation "6.9.2 Fundamental types [basic.fundamental]") of x[.](#5.sentence-1)
|
||||
|
||||
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[.](#5.sentence-2)
|
||||
|
||||
The standard signed integer types and standard unsigned integer types
|
||||
are collectively called the [*standard integer types*](#def:type,standard_integer "6.9.2 Fundamental types [basic.fundamental]"), and the extended
|
||||
signed integer types and extended
|
||||
unsigned integer types are collectively called the[*extended integer types*](#def:type,extended_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5419)
|
||||
|
||||
A fundamental type specified to have
|
||||
a signed or unsigned integer type as its [*underlying type*](#def:type,underlying "6.9.2 Fundamental types [basic.fundamental]") has
|
||||
the same object representation,
|
||||
value representation,
|
||||
alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment")), and
|
||||
range of representable values as the underlying type[.](#6.sentence-1)
|
||||
|
||||
Further, each value has the same representation in both types[.](#6.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5428)
|
||||
|
||||
Type char is a distinct type
|
||||
that has an implementation-defined choice of
|
||||
âsigned charâ or âunsigned charâ as its underlying type[.](#7.sentence-1)
|
||||
|
||||
The three types char, signed char, and unsigned char are collectively called[*ordinary character types*](#def:type,ordinary_character "6.9.2 Fundamental types [basic.fundamental]")[.](#7.sentence-2)
|
||||
|
||||
The ordinary character types and char8_t are collectively called [*narrow character types*](#def:type,narrow_character "6.9.2 Fundamental types [basic.fundamental]")[.](#7.sentence-3)
|
||||
|
||||
For narrow character types,
|
||||
each possible bit pattern of the object representation represents
|
||||
a distinct value[.](#7.sentence-4)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
This requirement does not hold for other types[.](#7.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [6](#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]](basic.types.general "6.9.1 General")[.](#7.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5454)
|
||||
|
||||
Type wchar_t is a distinct type that has
|
||||
an implementation-defined
|
||||
signed or unsigned integer type as its underlying type[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5462)
|
||||
|
||||
Type char8_t denotes a distinct type
|
||||
whose underlying type is unsigned char[.](#9.sentence-1)
|
||||
|
||||
Types char16_t and char32_t denote distinct types
|
||||
whose underlying types are uint_least16_t and uint_least32_t,
|
||||
respectively, in [<cstdint>](cstdint.syn#header:%3ccstdint%3e "17.4.1 Header <cstdint> synopsis [cstdint.syn]")[.](#9.sentence-2)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5478)
|
||||
|
||||
Type bool is a distinct type that has
|
||||
the same object representation,
|
||||
value representation, and
|
||||
alignment requirements as
|
||||
an implementation-defined unsigned integer type[.](#10.sentence-1)
|
||||
|
||||
The values of type bool aretrue and false[.](#10.sentence-2)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
There are no signed, unsigned,short, or long bool types or values[.](#10.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5493)
|
||||
|
||||
The types char, wchar_t,char8_t, char16_t, and char32_t are collectively called [*character types*](#def:type,character "6.9.2 Fundamental types [basic.fundamental]")[.](#11.sentence-1)
|
||||
|
||||
The character types, bool,
|
||||
the signed and unsigned integer types,
|
||||
and cv-qualified versions ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) thereof,
|
||||
are collectively termed[*integral types*](#def:integral_type "6.9.2 Fundamental types [basic.fundamental]")[.](#11.sentence-2)
|
||||
|
||||
A synonym for integral type is [*integer type*](#def:integer_type "6.9.2 Fundamental types [basic.fundamental]")[.](#11.sentence-3)
|
||||
|
||||
[*Note [8](#note-8)*:
|
||||
|
||||
Enumerations ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) are not integral;
|
||||
however, unscoped enumerations can be promoted to integral types
|
||||
as specified in [[conv.prom]](conv.prom "7.3.7 Integral promotions")[.](#11.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5510)
|
||||
|
||||
The three distinct typesfloat,double,
|
||||
andlong double can represent floating-point numbers[.](#12.sentence-1)
|
||||
|
||||
The type double provides at least as much
|
||||
precision as float, and the type long double provides at
|
||||
least as much precision as double[.](#12.sentence-2)
|
||||
|
||||
The set of values of the typefloat is a subset of the set of values of the typedouble; the set of values of the type double is a subset
|
||||
of the set of values of the type long double[.](#12.sentence-3)
|
||||
|
||||
The typesfloat, double, and long double,
|
||||
and cv-qualified versions ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) thereof,
|
||||
are collectively termed[*standard floating-point types*](#def:type,floating-point,standard "6.9.2 Fundamental types [basic.fundamental]")[.](#12.sentence-4)
|
||||
|
||||
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*](#def:type,floating-point,extended "6.9.2 Fundamental types [basic.fundamental]")[.](#12.sentence-5)
|
||||
|
||||
The standard and extended floating-point types
|
||||
are collectively termed [*floating-point types*](#def:type,floating-point "6.9.2 Fundamental types [basic.fundamental]")[.](#12.sentence-6)
|
||||
|
||||
[*Note [9](#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[.](#12.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Except as specified in [[basic.extended.fp]](basic.extended.fp "6.9.3 Optional extended floating-point types"),
|
||||
the object and value representations and accuracy of operations
|
||||
of floating-point types are implementation-defined[.](#12.sentence-8)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5548)
|
||||
|
||||
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[.](#13.sentence-1)
|
||||
|
||||
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[.](#13.sentence-2)
|
||||
|
||||
[*Note [10](#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[.](#13.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5564)
|
||||
|
||||
Integral and floating-point types are collectively
|
||||
termed [*arithmetic types*](#def:type,arithmetic "6.9.2 Fundamental types [basic.fundamental]")[.](#14.sentence-1)
|
||||
|
||||
[*Note [11](#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>](limits.syn#header:%3climits%3e "17.3.3 Header <limits> synopsis [limits.syn]"),[<climits>](climits.syn#header:%3cclimits%3e "17.3.6 Header <climits> synopsis [climits.syn]"), and[<cfloat>](cfloat.syn#header:%3ccfloat%3e "17.3.7 Header <cfloat> synopsis [cfloat.syn]")[.](#14.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5576)
|
||||
|
||||
A type cv void is an incomplete type that cannot be completed; such a type has
|
||||
an empty set of values[.](#15.sentence-1)
|
||||
|
||||
It is used as the return
|
||||
type for functions that do not return a value[.](#15.sentence-2)
|
||||
|
||||
An expression of type cv void shall
|
||||
be used only as
|
||||
|
||||
- [(15.1)](#15.1)
|
||||
|
||||
an expression statement ([[stmt.expr]](stmt.expr "8.3 Expression statement")),
|
||||
|
||||
- [(15.2)](#15.2)
|
||||
|
||||
the expression in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement"))
|
||||
for a function with the return type cv void,
|
||||
|
||||
- [(15.3)](#15.3)
|
||||
|
||||
an operand of a comma expression ([[expr.comma]](expr.comma "7.6.20 Comma operator")),
|
||||
|
||||
- [(15.4)](#15.4)
|
||||
|
||||
the second or third operand of ?: ([[expr.cond]](expr.cond "7.6.16 Conditional operator")),
|
||||
|
||||
- [(15.5)](#15.5)
|
||||
|
||||
the operand of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
|
||||
- [(15.6)](#15.6)
|
||||
|
||||
the operand of a noexcept operator ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator")),
|
||||
|
||||
- [(15.7)](#15.7)
|
||||
|
||||
the operand of a decltype specifier ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")), or
|
||||
|
||||
- [(15.8)](#15.8)
|
||||
|
||||
the operand of an explicit conversion to typecv void ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))[.](#15.sentence-3)
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5597)
|
||||
|
||||
The types denoted by cv std::nullptr_t are distinct types[.](#16.sentence-1)
|
||||
|
||||
A prvalue of type std::nullptr_t is a null pointer
|
||||
constant ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"))[.](#16.sentence-2)
|
||||
|
||||
Such values participate in the pointer and the
|
||||
pointer-to-member conversions ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"), [[conv.mem]](conv.mem "7.3.13 Pointer-to-member conversions"))[.](#16.sentence-3)
|
||||
|
||||
sizeof(std::nullptr_t) shall be equal to sizeof(void*)[.](#16.sentence-4)
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5604)
|
||||
|
||||
A value of type std::meta::info is called a [*reflection*](#def:reflection "6.9.2 Fundamental types [basic.fundamental]")[.](#17.sentence-1)
|
||||
|
||||
There exists a unique [*null reflection*](#def:reflection,null "6.9.2 Fundamental types [basic.fundamental]");
|
||||
every other reflection is a representation of
|
||||
|
||||
- [(17.1)](#17.1)
|
||||
|
||||
a value of scalar type ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(17.2)](#17.2)
|
||||
|
||||
an object with static storage duration ([[basic.stc]](basic.stc "6.8.6 Storage duration")),
|
||||
|
||||
- [(17.3)](#17.3)
|
||||
|
||||
a variable ([[basic.pre]](basic.pre "6.1 Preamble")),
|
||||
|
||||
- [(17.4)](#17.4)
|
||||
|
||||
a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")),
|
||||
|
||||
- [(17.5)](#17.5)
|
||||
|
||||
a function ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(17.6)](#17.6)
|
||||
|
||||
a function parameter,
|
||||
|
||||
- [(17.7)](#17.7)
|
||||
|
||||
an enumerator ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
|
||||
- [(17.8)](#17.8)
|
||||
|
||||
an annotation ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics")),
|
||||
|
||||
- [(17.9)](#17.9)
|
||||
|
||||
a type alias ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),
|
||||
|
||||
- [(17.10)](#17.10)
|
||||
|
||||
a type ([[basic.types]](basic.types "6.9 Types")),
|
||||
|
||||
- [(17.11)](#17.11)
|
||||
|
||||
a class member ([[class.mem]](class.mem "11.4 Class members")),
|
||||
|
||||
- [(17.12)](#17.12)
|
||||
|
||||
an unnamed bit-field ([[class.bit]](class.bit "11.4.10 Bit-fields")),
|
||||
|
||||
- [(17.13)](#17.13)
|
||||
|
||||
a class template ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||||
|
||||
- [(17.14)](#17.14)
|
||||
|
||||
a function template,
|
||||
|
||||
- [(17.15)](#17.15)
|
||||
|
||||
a variable template,
|
||||
|
||||
- [(17.16)](#17.16)
|
||||
|
||||
an alias template ([[temp.alias]](temp.alias "13.7.8 Alias templates")),
|
||||
|
||||
- [(17.17)](#17.17)
|
||||
|
||||
a concept ([[temp.concept]](temp.concept "13.7.9 Concept definitions")),
|
||||
|
||||
- [(17.18)](#17.18)
|
||||
|
||||
a namespace alias ([[namespace.alias]](namespace.alias "9.9.3 Namespace alias")),
|
||||
|
||||
- [(17.19)](#17.19)
|
||||
|
||||
a namespace ([[basic.namespace.general]](basic.namespace.general "9.9.1 General")),
|
||||
|
||||
- [(17.20)](#17.20)
|
||||
|
||||
a direct base class relationship ([[class.derived.general]](class.derived.general "11.7.1 General")), or
|
||||
|
||||
- [(17.21)](#17.21)
|
||||
|
||||
a data member description ([[class.mem.general]](class.mem.general "11.4.1 General"))[.](#17.sentence-2)
|
||||
|
||||
A reflection is said to [*represent*](#def:represent "6.9.2 Fundamental types [basic.fundamental]") the corresponding construct[.](#17.sentence-3)
|
||||
|
||||
[*Note [12](#note-12)*:
|
||||
|
||||
A reflection of a value can be produced by library functions such asstd::meta::constant_of and std::meta::reflect_constant[.](#17.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*: int arr[] = {1, 2, 3};auto [a1, a2, a3] = arr;void fn();enum Enum { A };using Alias = int;struct B {};struct S : B {int mem; int : 0;};template<auto> struct TCls {};template<auto> void TFn();template<auto> int TVar;template<auto> concept Concept = requires { true; };namespace NS {};namespace NSAlias = NS;
|
||||
|
||||
constexpr auto ctx = std::meta::access_context::current();
|
||||
|
||||
constexpr auto r1 = std::meta::reflect_constant(42); // represents int value of 42constexpr auto r2 = std::meta::reflect_object(arr[1]); // represents int objectconstexpr auto r3 = ^^arr; // represents a variableconstexpr auto r4 = ^^a3; // represents a structured bindingconstexpr auto r5 = ^^fn; // represents a functionconstexpr auto r6 = ^^Enum::A; // represents an enumeratorconstexpr auto r7 = ^^Alias; // represents a type aliasconstexpr auto r8 = ^^S; // represents a typeconstexpr auto r9 = ^^S::mem; // represents a class memberconstexpr auto r10 = std::meta::members_of(^^S, ctx)[1]; // represents an unnamed bit-fieldconstexpr auto r11 = ^^TCls; // represents a class templateconstexpr auto r12 = ^^TFn; // represents a function templateconstexpr auto r13 = ^^TVar; // represents a variable templateconstexpr auto r14 = ^^Concept; // represents a conceptconstexpr auto r15 = ^^NSAlias; // represents a namespace aliasconstexpr auto r16 = ^^NS; // represents a namespaceconstexpr auto r17 = std::meta::bases_of(^^S, ctx)[0]; // represents a direct base class relationshipconstexpr auto r18 = std::meta::data_member_spec(^^int, {.name="member"}); // represents a data member description â *end example*]
|
||||
|
||||
[18](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5679)
|
||||
|
||||
*Recommended practice*: Implementations should not represent other constructs
|
||||
specified in this document, such as[*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]")*s*,
|
||||
partial template specializations,
|
||||
attributes, placeholder types,
|
||||
statements, or
|
||||
expressions,
|
||||
as values of type std::meta::info[.](#18.sentence-1)
|
||||
|
||||
[*Note [13](#note-13)*:
|
||||
|
||||
Future revisions of this document can specify semantics for reflections
|
||||
representing any such constructs[.](#18.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[19](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5694)
|
||||
|
||||
The types described in this subclause
|
||||
are called [*fundamental types*](#def:fundamental_type "6.9.2 Fundamental types [basic.fundamental]")[.](#19.sentence-1)
|
||||
|
||||
[*Note [14](#note-14)*:
|
||||
|
||||
Even if the implementation defines two or more fundamental types to have the
|
||||
same value representation, they are nevertheless different types[.](#19.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[30)](#footnote-30)[30)](#footnoteref-30)
|
||||
|
||||
This
|
||||
is also known as two's complement representation[.](#footnote-30.sentence-1)
|
||||
121
cppdraft/basic/indet.md
Normal file
121
cppdraft/basic/indet.md
Normal file
@@ -0,0 +1,121 @@
|
||||
[basic.indet]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.indet)
|
||||
|
||||
### 6.8.5 Indeterminate and erroneous values [basic.indet]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4119)
|
||||
|
||||
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:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
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]](dcl.attr.indet "9.13.6 Indeterminate storage")),
|
||||
the bytes have [*indeterminate values*](#def:value,indeterminate "6.8.5 Indeterminate and erroneous values [basic.indet]");
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
otherwise, the bytes have [*erroneous values*](#def:value,erroneous "6.8.5 Indeterminate and erroneous values [basic.indet]"),
|
||||
where each value is determined by the implementation
|
||||
independently of the state of the program[.](#1.sentence-1)
|
||||
|
||||
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]](dcl.init.general "9.5.1 General"), [[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))[.](#1.sentence-2)
|
||||
|
||||
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]](conv.lval "7.3.2 Lvalue-to-rvalue conversion"))[.](#1.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Objects with static or thread storage duration are zero-initialized,
|
||||
see [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization")[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4148)
|
||||
|
||||
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:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
If an indeterminate or erroneous value of
|
||||
unsigned ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))
|
||||
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"))
|
||||
is produced by the evaluation of:
|
||||
* [(2.1.1)](#2.1.1)
|
||||
|
||||
the second or third operand of a [conditional expression](expr.cond "7.6.16 Conditional operator [expr.cond]"),
|
||||
|
||||
* [(2.1.2)](#2.1.2)
|
||||
|
||||
the right operand of a [comma expression](expr.comma "7.6.20 Comma operator [expr.comma]"),
|
||||
|
||||
* [(2.1.3)](#2.1.3)
|
||||
|
||||
the operand of a cast or conversion ([[conv.integral]](conv.integral "7.3.9 Integral conversions"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))
|
||||
to an unsigned ordinary character type
|
||||
or std::byte type ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis")), or
|
||||
|
||||
* [(2.1.4)](#2.1.4)
|
||||
|
||||
a [discarded-value expression](expr.context#def:discarded-value_expression "7.2.3 Context dependence [expr.context]"),
|
||||
|
||||
then the result of the operation is an indeterminate value or
|
||||
that erroneous value, respectively[.](#2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
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]](expr.assign "7.6.19 Assignment and compound assignment operators"))
|
||||
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[.](#2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
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[.](#2.3.sentence-1)
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
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[.](#2.4.sentence-1)
|
||||
|
||||
Converting an indeterminate or erroneous value of
|
||||
unsigned ordinary character type or std::byte type
|
||||
produces an indeterminate or erroneous value, respectively[.](#2.sentence-2)
|
||||
|
||||
In the latter case,
|
||||
the result of the conversion is the value of the converted operand[.](#2.sentence-3)
|
||||
|
||||
[*Example [1](#example-1)*: int f(bool b) {unsigned char *c = new unsigned char; unsigned char d = *c; // OK, d has an indeterminate valueint e = d; // undefined behaviorreturn 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 behaviorint e = d; // erroneous behaviorreturn b ? d : 0; // erroneous behavior if b is true}void h() {int d1, d2; int e1 = d1; // erroneous behaviorint 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*]
|
||||
73
cppdraft/basic/ios/cons.md
Normal file
73
cppdraft/basic/ios/cons.md
Normal file
@@ -0,0 +1,73 @@
|
||||
[basic.ios.cons]
|
||||
|
||||
# 31 Input/output library [[input.output]](./#input.output)
|
||||
|
||||
## 31.5 Iostreams base classes [[iostreams.base]](iostreams.base#basic.ios.cons)
|
||||
|
||||
### 31.5.4 Class template basic_ios [[ios]](ios#basic.ios.cons)
|
||||
|
||||
#### 31.5.4.2 Constructors [basic.ios.cons]
|
||||
|
||||
[ð](#lib:basic_ios,constructor)
|
||||
|
||||
`explicit basic_ios(basic_streambuf<charT, traits>* sb);
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1879)
|
||||
|
||||
*Effects*: Assigns initial values to its member objects by callinginit(sb)[.](#1.sentence-1)
|
||||
|
||||
[ð](#lib:basic_ios,constructor_)
|
||||
|
||||
`basic_ios();
|
||||
`
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1891)
|
||||
|
||||
*Effects*: Leaves its member objects uninitialized[.](#2.sentence-1)
|
||||
|
||||
The object
|
||||
shall be initialized by callingbasic_ios::init before its first use or before it is destroyed, whichever comes first; otherwise the
|
||||
behavior is undefined[.](#2.sentence-2)
|
||||
|
||||
[ð](#lib:basic_ios,destructor)
|
||||
|
||||
`~basic_ios();
|
||||
`
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1906)
|
||||
|
||||
*Remarks*: The destructor does not destroyrdbuf()[.](#3.sentence-1)
|
||||
|
||||
[ð](#lib:init,basic_ios)
|
||||
|
||||
`void init(basic_streambuf<charT, traits>* sb);
|
||||
`
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1918)
|
||||
|
||||
*Postconditions*: The postconditions of this function are indicated in Table [142](#tab:basic.ios.cons "Table 142: basic_ios::init() effects")[.](#4.sentence-1)
|
||||
|
||||
Table [142](#tab:basic.ios.cons) — basic_ios::init() effects [[tab:basic.ios.cons]](./tab:basic.ios.cons)
|
||||
|
||||
| [ð](#tab:basic.ios.cons-row-1)<br>**Element** | **Value** |
|
||||
| --- | --- |
|
||||
| [ð](#tab:basic.ios.cons-row-2)<br>rdbuf() | sb |
|
||||
| [ð](#tab:basic.ios.cons-row-3)<br>tie() | 0 |
|
||||
| [ð](#tab:basic.ios.cons-row-4)<br>rdstate() | goodbit if sb is not a null pointer, otherwise badbit[.](#tab:basic.ios.cons-row-4-column-2-sentence-1) |
|
||||
| [ð](#tab:basic.ios.cons-row-5)<br>exceptions() | goodbit |
|
||||
| [ð](#tab:basic.ios.cons-row-6)<br>flags() | skipws | dec |
|
||||
| [ð](#tab:basic.ios.cons-row-7)<br>width() | 0 |
|
||||
| [ð](#tab:basic.ios.cons-row-8)<br>precision() | 6 |
|
||||
| [ð](#tab:basic.ios.cons-row-9)<br>fill() | widen(' ') |
|
||||
| [ð](#tab:basic.ios.cons-row-10)<br>getloc() | a copy of the value returned by locale() |
|
||||
| [ð](#tab:basic.ios.cons-row-11)<br>*iarray* | a null pointer |
|
||||
| [ð](#tab:basic.ios.cons-row-12)<br>*parray* | a null pointer |
|
||||
291
cppdraft/basic/ios/members.md
Normal file
291
cppdraft/basic/ios/members.md
Normal file
@@ -0,0 +1,291 @@
|
||||
[basic.ios.members]
|
||||
|
||||
# 31 Input/output library [[input.output]](./#input.output)
|
||||
|
||||
## 31.5 Iostreams base classes [[iostreams.base]](iostreams.base#basic.ios.members)
|
||||
|
||||
### 31.5.4 Class template basic_ios [[ios]](ios#basic.ios.members)
|
||||
|
||||
#### 31.5.4.3 Member functions [basic.ios.members]
|
||||
|
||||
[ð](#lib:tie,basic_ios)
|
||||
|
||||
`basic_ostream<charT, traits>* tie() const;
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1956)
|
||||
|
||||
*Returns*: An output sequence that is*tied* to (synchronized with) the sequence controlled by the stream buffer[.](#1.sentence-1)
|
||||
|
||||
[ð](#lib:tie,basic_ios_)
|
||||
|
||||
`basic_ostream<charT, traits>* tie(basic_ostream<charT, traits>* tiestr);
|
||||
`
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1969)
|
||||
|
||||
*Preconditions*: If tiestr is not null, tiestr is not reachable by
|
||||
traversing the linked list of tied stream objects starting fromtiestr->tie()[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1975)
|
||||
|
||||
*Postconditions*: tiestr == tie()[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1979)
|
||||
|
||||
*Returns*: The previous value oftie()[.](#4.sentence-1)
|
||||
|
||||
[ð](#lib:rdbuf,basic_ios)
|
||||
|
||||
`basic_streambuf<charT, traits>* rdbuf() const;
|
||||
`
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L1991)
|
||||
|
||||
*Returns*: A pointer to thestreambuf associated with the stream[.](#5.sentence-1)
|
||||
|
||||
[ð](#lib:rdbuf,basic_ios_)
|
||||
|
||||
`basic_streambuf<charT, traits>* rdbuf(basic_streambuf<charT, traits>* sb);
|
||||
`
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2004)
|
||||
|
||||
*Effects*: Callsclear()[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2009)
|
||||
|
||||
*Postconditions*: sb == rdbuf()[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2013)
|
||||
|
||||
*Returns*: The previous value ofrdbuf()[.](#8.sentence-1)
|
||||
|
||||
[ð](#lib:imbue,basic_ios)
|
||||
|
||||
`locale imbue(const locale& loc);
|
||||
`
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2025)
|
||||
|
||||
*Effects*: Calls[ios_base::imbue](ios.base.locales#lib:ios_base,imbue "31.5.2.4 Functions [ios.base.locales]")(loc) and
|
||||
ifrdbuf() != 0 thenrdbuf()->[pubimbue](streambuf.locales#lib:basic_streambuf,pubimbue "31.6.3.3.1 Locales [streambuf.locales]")(loc)[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2035)
|
||||
|
||||
*Returns*: The prior value ofios_base::imbue()[.](#10.sentence-1)
|
||||
|
||||
[ð](#lib:narrow,basic_ios)
|
||||
|
||||
`char narrow(char_type c, char dfault) const;
|
||||
`
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2047)
|
||||
|
||||
*Returns*: use_facet<ctype<char_type>>(getloc()).narrow(c, dfault)[.](#11.sentence-1)
|
||||
|
||||
[ð](#lib:widen,basic_ios)
|
||||
|
||||
`char_type widen(char c) const;
|
||||
`
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2058)
|
||||
|
||||
*Returns*: use_facet<ctype<char_type>>(getloc()).widen(c)[.](#12.sentence-1)
|
||||
|
||||
[ð](#lib:fill,basic_ios)
|
||||
|
||||
`char_type fill() const;
|
||||
`
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2069)
|
||||
|
||||
*Returns*: The character used to pad (fill) an output conversion to the specified
|
||||
field width[.](#13.sentence-1)
|
||||
|
||||
[ð](#lib:fill,basic_ios_)
|
||||
|
||||
`char_type fill(char_type fillch);
|
||||
`
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2081)
|
||||
|
||||
*Postconditions*: traits::eq(fillch, fill())[.](#14.sentence-1)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2085)
|
||||
|
||||
*Returns*: The previous value offill()[.](#15.sentence-1)
|
||||
|
||||
[ð](#lib:copyfmt,basic_ios)
|
||||
|
||||
`basic_ios& copyfmt(const basic_ios& rhs);
|
||||
`
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2097)
|
||||
|
||||
*Effects*: If(this == addressof(rhs)) is true does nothing[.](#16.sentence-1)
|
||||
|
||||
Otherwise assigns to the member objects of*this the corresponding member objects of rhs as follows:
|
||||
|
||||
- [(16.1)](#16.1)
|
||||
|
||||
calls each registered callback pair (fn, idx) as(*fn)(erase_event, *this, idx);
|
||||
|
||||
- [(16.2)](#16.2)
|
||||
|
||||
then, assigns to the member objects of *this the corresponding member objects ofrhs, except that
|
||||
* [(16.2.1)](#16.2.1)
|
||||
|
||||
rdstate(), rdbuf(), and exceptions() are left unchanged;
|
||||
|
||||
* [(16.2.2)](#16.2.2)
|
||||
|
||||
the contents of arrays pointed at by pword and iword are copied,
|
||||
not the pointers themselves;[263](#footnote-263 "This suggests an infinite amount of copying, but the implementation can keep track of the maximum element of the arrays that is nonzero.") and
|
||||
|
||||
* [(16.2.3)](#16.2.3)
|
||||
|
||||
if any newly stored pointer values in *this point at objects stored outside
|
||||
the object rhs and those objects are destroyed when rhs is destroyed, the
|
||||
newly stored pointer values are altered to point at newly constructed copies of the
|
||||
objects;
|
||||
|
||||
- [(16.3)](#16.3)
|
||||
|
||||
then, calls each callback pair that was copied from rhs as(*fn)(copyfmt_event, *this, idx);
|
||||
|
||||
- [(16.4)](#16.4)
|
||||
|
||||
then, calls exceptions(rhs.exceptions())[.](#16.sentence-2)
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2134)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The second pass through the callback pairs permits a copied pword value to be zeroed, or to have its referent deep copied or reference counted, or to have
|
||||
other special action taken[.](#17.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[18](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2141)
|
||||
|
||||
*Postconditions*: The postconditions of this function are indicated in Table [143](#tab:basic.ios.copyfmt "Table 143: basic_ios::copyfmt() effects")[.](#18.sentence-1)
|
||||
|
||||
Table [143](#tab:basic.ios.copyfmt) — basic_ios::copyfmt() effects [[tab:basic.ios.copyfmt]](./tab:basic.ios.copyfmt)
|
||||
|
||||
| [ð](#tab:basic.ios.copyfmt-row-1)<br>**Element** | **Value** |
|
||||
| --- | --- |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-2)<br>rdbuf() | *unchanged* |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-3)<br>tie() | rhs.tie() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-4)<br>rdstate() | *unchanged* |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-5)<br>exceptions() | rhs.exceptions() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-6)<br>flags() | rhs.flags() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-7)<br>width() | rhs.width() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-8)<br>precision() | rhs.precision() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-9)<br>fill() | rhs.fill() |
|
||||
| [ð](#tab:basic.ios.copyfmt-row-10)<br>getloc() | rhs.getloc() |
|
||||
|
||||
[19](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2167)
|
||||
|
||||
*Returns*: *this[.](#19.sentence-1)
|
||||
|
||||
[ð](#lib:move,basic_ios)
|
||||
|
||||
`void move(basic_ios& rhs);
|
||||
void move(basic_ios&& rhs);
|
||||
`
|
||||
|
||||
[20](#20)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2179)
|
||||
|
||||
*Postconditions*: *this has the state thatrhs had before the function call, except thatrdbuf() returns nullptr[.](#20.sentence-1)
|
||||
|
||||
rhs is in a valid but
|
||||
unspecified state, except that rhs.rdbuf() returns the
|
||||
same value as it returned before the function call, andrhs.tie() returns nullptr[.](#20.sentence-2)
|
||||
|
||||
[ð](#lib:swap,basic_ios)
|
||||
|
||||
`void swap(basic_ios& rhs) noexcept;
|
||||
`
|
||||
|
||||
[21](#21)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2195)
|
||||
|
||||
*Effects*: The states of *this and rhs are exchanged, except that rdbuf() returns the same
|
||||
value as it returned before the function call, and rhs.rdbuf() returns the same value as it returned before the function call[.](#21.sentence-1)
|
||||
|
||||
[ð](#lib:set_rdbuf,basic_ios)
|
||||
|
||||
`void set_rdbuf(basic_streambuf<charT, traits>* sb);
|
||||
`
|
||||
|
||||
[22](#22)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2209)
|
||||
|
||||
*Preconditions*: sb != nullptr is true[.](#22.sentence-1)
|
||||
|
||||
[23](#23)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2213)
|
||||
|
||||
*Effects*: Associates the basic_streambuf object
|
||||
pointed to by sb with this stream without callingclear()[.](#23.sentence-1)
|
||||
|
||||
[24](#24)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2219)
|
||||
|
||||
*Postconditions*: rdbuf() == sb is true[.](#24.sentence-1)
|
||||
|
||||
[25](#25)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L2223)
|
||||
|
||||
*Throws*: Nothing[.](#25.sentence-1)
|
||||
|
||||
[263)](#footnote-263)[263)](#footnoteref-263)
|
||||
|
||||
This suggests an infinite amount of copying, but the implementation can keep
|
||||
track of the maximum element of the arrays that is nonzero[.](#footnote-263.sentence-1)
|
||||
334
cppdraft/basic/life.md
Normal file
334
cppdraft/basic/life.md
Normal file
@@ -0,0 +1,334 @@
|
||||
[basic.life]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.life)
|
||||
|
||||
### 6.8.4 Lifetime [basic.life]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3821)
|
||||
|
||||
In this subclause, âbeforeâ and âafterâ refer to the âhappens beforeâ
|
||||
relation ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3825)
|
||||
|
||||
The [*lifetime*](#def:lifetime "6.8.4 Lifetime [basic.life]") of an object or reference is a runtime property of the
|
||||
object or reference[.](#2.sentence-1)
|
||||
|
||||
A variable is said to have [*vacuous initialization*](#def:initialization,vacuous "6.8.4 Lifetime [basic.life]") 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[.](#2.sentence-2)
|
||||
|
||||
The lifetime of an object of type T begins when:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
storage with the proper alignment and size
|
||||
for type T is obtained, and
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
its initialization (if any) is complete
|
||||
(including vacuous initialization) ([[dcl.init]](dcl.init "9.5 Initializers")),
|
||||
|
||||
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]](dcl.init.aggr "9.5.2 Aggregates"), [[class.base.init]](class.base.init "11.9.3 Initializing bases and members")),
|
||||
or as described in[[class.union]](class.union "11.5 Unions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"), and [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator"),
|
||||
and except as described in [[allocator.members]](allocator.members "20.2.10.2 Members")[.](#2.sentence-3)
|
||||
|
||||
The lifetime of an object *o* of type T ends when:
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
if T is a non-class type, the object is destroyed, or
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
if T is a class type, the destructor call starts, or
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
the storage which the object occupies is released,
|
||||
or is reused by an object that is not nested within *o* ([[intro.object]](intro.object "6.8.2 Object model"))[.](#2.sentence-4)
|
||||
|
||||
When evaluating a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"),
|
||||
storage is considered reused after it is returned from the allocation function,
|
||||
but before the evaluation of the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))[.](#2.sentence-5)
|
||||
|
||||
[*Example [1](#example-1)*: struct S {int m;};
|
||||
|
||||
void f() { S x{1}; new(&x) S(x.m); // undefined behavior} â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3870)
|
||||
|
||||
The lifetime of a reference begins when its initialization is complete[.](#3.sentence-1)
|
||||
|
||||
The lifetime of a reference ends as if it were a scalar object requiring storage[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3875)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
[[class.base.init]](class.base.init "11.9.3 Initializing bases and members") describes the lifetime of base and member subobjects[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3881)
|
||||
|
||||
The properties ascribed to objects and references throughout this document
|
||||
apply for a given object or reference only during its lifetime[.](#5.sentence-1)
|
||||
|
||||
[*Note [2](#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]](class.base.init "11.9.3 Initializing bases and members"), and
|
||||
in [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")[.](#5.sentence-2)
|
||||
|
||||
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[.](#5.sentence-3)
|
||||
|
||||
[[class.base.init]](class.base.init "11.9.3 Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction") describe the behavior of an object during its periods
|
||||
of construction and destruction[.](#5.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3895)
|
||||
|
||||
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[.](#6.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
A [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]") ([[expr.delete]](expr.delete "7.6.2.9 Delete")) invokes the destructor
|
||||
prior to releasing the storage[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
In this case, the destructor is not implicitly invoked[.](#6.sentence-3)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The correct behavior of a program often depends on
|
||||
the destructor being invoked for each object of class type[.](#6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3908)
|
||||
|
||||
Before the lifetime of an object has started but after the storage which
|
||||
the object will occupy has been allocated[21](#footnote-21 "For example, before the dynamic initialization of an object with static storage duration ([basic.start.dynamic]).") 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[.](#7.sentence-1)
|
||||
|
||||
For an object under construction or destruction, see [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")[.](#7.sentence-2)
|
||||
|
||||
Otherwise, such
|
||||
a pointer refers to allocated
|
||||
storage ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")), and using the pointer as
|
||||
if the pointer were of type void* is
|
||||
well-defined[.](#7.sentence-3)
|
||||
|
||||
Indirection through such a pointer is permitted but the resulting lvalue may only be used in
|
||||
limited ways, as described below[.](#7.sentence-4)
|
||||
|
||||
The
|
||||
program has undefined behavior if
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
the pointer is used as the operand of a [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]"),
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
the pointer is used to access a non-static data member or call a
|
||||
non-static member function of the object, or
|
||||
|
||||
- [(7.3)](#7.3)
|
||||
|
||||
the pointer is implicitly converted ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions")) to a pointer
|
||||
to a virtual base class, or
|
||||
|
||||
- [(7.4)](#7.4)
|
||||
|
||||
the pointer is used as the operand of a static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9 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]](cstddef.syn "17.2.1 Header <cstddef> synopsis")), or
|
||||
|
||||
- [(7.5)](#7.5)
|
||||
|
||||
the pointer is used as the operand of a dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast"))[.](#7.sentence-5)
|
||||
|
||||
[*Example [2](#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 memoryvoid* q = pb; // OK, pb points to valid memory pb->f(); // undefined behavior: lifetime of *pb has ended} â *end example*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3978)
|
||||
|
||||
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[.](#8.sentence-1)
|
||||
|
||||
For an object under construction or destruction, see [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")[.](#8.sentence-2)
|
||||
|
||||
Otherwise, such
|
||||
a glvalue refers to
|
||||
allocated storage ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")), and using the
|
||||
properties of the glvalue that do not depend on its value is
|
||||
well-defined[.](#8.sentence-3)
|
||||
|
||||
The program has undefined behavior if
|
||||
|
||||
- [(8.1)](#8.1)
|
||||
|
||||
the glvalue is used to access the object, or
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
the glvalue is used to call a non-static member function of the object, or
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
the glvalue is bound to a reference to a virtual base class ([[dcl.init.ref]](dcl.init.ref "9.5.4 References")), or
|
||||
|
||||
- [(8.4)](#8.4)
|
||||
|
||||
the glvalue is used as the operand of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")) or as the operand oftypeid[.](#8.sentence-4)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
Therefore, undefined behavior results
|
||||
if an object that is being constructed in one thread is referenced from another
|
||||
thread without adequate synchronization[.](#8.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4005)
|
||||
|
||||
An object o1 is [*transparently replaceable*](#def:transparently_replaceable "6.8.4 Lifetime [basic.life]") by an object o2 if
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
the storage that o2 occupies exactly overlays
|
||||
the storage that o1 occupied, and
|
||||
|
||||
- [(9.2)](#9.2)
|
||||
|
||||
o1 and o2 are of the same type
|
||||
(ignoring the top-level cv-qualifiers), and
|
||||
|
||||
- [(9.3)](#9.3)
|
||||
|
||||
o1 is not a const, complete object, and
|
||||
|
||||
- [(9.4)](#9.4)
|
||||
|
||||
neither o1 nor o2 is a potentially-overlapping subobject ([[intro.object]](intro.object "6.8.2 Object model")), and
|
||||
|
||||
- [(9.5)](#9.5)
|
||||
|
||||
either o1 and o2 are both complete objects, oro1 and o2 are direct subobjects of objects p1 and p2, respectively,
|
||||
and p1 is transparently replaceable by p2[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4024)
|
||||
|
||||
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[.](#10.sentence-1)
|
||||
|
||||
[*Example [3](#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 endsnew (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](#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]](ptr.launder "17.6.5 Pointer optimization barrier"))[.](#10.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4064)
|
||||
|
||||
If a program ends the lifetime of an object of type T with
|
||||
static ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")), thread ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")),
|
||||
or automatic ([[basic.stc.auto]](basic.stc.auto "6.8.6.4 Automatic storage duration"))
|
||||
storage duration and if T has a non-trivial destructor,[22](#footnote-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.") 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[.](#11.sentence-1)
|
||||
|
||||
This is true
|
||||
even if the block is exited with an exception[.](#11.sentence-2)
|
||||
|
||||
[*Example [4](#example-4)*: class T { };struct B {~B();};
|
||||
|
||||
void h() { B b; new (&b) T;} // undefined behavior at block exit â *end example*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4095)
|
||||
|
||||
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[.](#12.sentence-1)
|
||||
|
||||
[*Example [5](#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)](#footnote-21)[21)](#footnoteref-21)
|
||||
|
||||
For example, before the dynamic initialization of
|
||||
an object with static storage duration ([[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"))[.](#footnote-21.sentence-1)
|
||||
|
||||
[22)](#footnote-22)[22)](#footnoteref-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[.](#footnote-22.sentence-1)
|
||||
524
cppdraft/basic/link.md
Normal file
524
cppdraft/basic/link.md
Normal file
@@ -0,0 +1,524 @@
|
||||
[basic.link]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.7 Program and linkage [basic.link]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2876)
|
||||
|
||||
A [*program*](#def:program "6.7 Program and linkage [basic.link]") consists of one or more [translation units](lex.separate#def:translation_unit "5.1 Separate translation [lex.separate]") linked together[.](#1.sentence-1)
|
||||
|
||||
A translation unit consists
|
||||
of a sequence of declarations[.](#1.sentence-2)
|
||||
|
||||
[translation-unit:](#nt:translation-unit "6.7 Program and linkage [basic.link]")
|
||||
[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]")opt
|
||||
[*global-module-fragment*](module.global.frag#nt:global-module-fragment "10.4 Global module fragment [module.global.frag]")opt [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]") [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]")opt [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]")opt
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2889)
|
||||
|
||||
A name has[*external linkage*](#def:linkage,external "6.7 Program and linkage [basic.link]"),[*module linkage*](#def:linkage,module "6.7 Program and linkage [basic.link]"),[*internal linkage*](#def:linkage,internal "6.7 Program and linkage [basic.link]"), or[*no linkage*](#def:linkage,no "6.7 Program and linkage [basic.link]"),
|
||||
as determined by the rules below[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
All declarations of an entity with a name with internal linkage
|
||||
appear in the same translation unit[.](#2.sentence-2)
|
||||
|
||||
All declarations of an entity with module linkage
|
||||
are attached to the same module[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2904)
|
||||
|
||||
The name of an entity
|
||||
that belongs to a [namespace scope](basic.scope.namespace "6.4.6 Namespace scope [basic.scope.namespace]") has internal linkage if it is the name of
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
a variable, variable template, function, or function template that is
|
||||
explicitly declared static; or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
a non-template variable of non-volatile const-qualified type, unless
|
||||
* [(3.2.1)](#3.2.1)
|
||||
|
||||
it is declared in the purview of a module interface unit
|
||||
(outside the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]"), if any) or
|
||||
module partition, or
|
||||
|
||||
* [(3.2.2)](#3.2.2)
|
||||
|
||||
it is explicitly declared extern, or
|
||||
|
||||
* [(3.2.3)](#3.2.3)
|
||||
|
||||
it is inline, or
|
||||
|
||||
* [(3.2.4)](#3.2.4)
|
||||
|
||||
it was previously declared and the prior declaration did
|
||||
not have internal linkage; or
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
a data member of an anonymous union[.](#3.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
An instantiated variable template that has const-qualified type
|
||||
can have external or module linkage, even if not declared extern[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2937)
|
||||
|
||||
An unnamed namespace or a namespace declared directly or indirectly within an
|
||||
unnamed namespace has internal linkage[.](#4.sentence-1)
|
||||
|
||||
All other namespaces have external linkage[.](#4.sentence-2)
|
||||
|
||||
The name of an entity that belongs to a namespace scope,
|
||||
that has not been given internal linkage above,
|
||||
and that is the name of
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
a variable; or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
a function; or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
a named class ([[class.pre]](class.pre "11.1 Preamble")), or an unnamed class defined in a
|
||||
typedef declaration in which the class has the typedef name for linkage
|
||||
purposes ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")); or
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
a named [enumeration](dcl.enum "9.8.1 Enumeration declarations [dcl.enum]"), or an unnamed enumeration defined
|
||||
in a typedef declaration in which the enumeration has the typedef name
|
||||
for linkage purposes ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")); or
|
||||
|
||||
- [(4.5)](#4.5)
|
||||
|
||||
an unnamed enumeration
|
||||
that has an enumerator as a name for linkage purposes ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")); or
|
||||
|
||||
- [(4.6)](#4.6)
|
||||
|
||||
a template
|
||||
|
||||
has its linkage determined as follows:
|
||||
|
||||
- [(4.7)](#4.7)
|
||||
|
||||
if the entity is a function or function template
|
||||
first declared in a friend declaration and
|
||||
that declaration is a definition and
|
||||
the enclosing class is defined within an [*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]"),
|
||||
the name has the same linkage, if any,
|
||||
as the name of the enclosing class ([[class.friend]](class.friend "11.8.4 Friends"));
|
||||
|
||||
- [(4.8)](#4.8)
|
||||
|
||||
otherwise,if the entity is a function or function template
|
||||
declared in a friend declaration and
|
||||
a corresponding non-friend declaration is reachable,
|
||||
the name has the linkage determined from that prior declaration,
|
||||
|
||||
- [(4.9)](#4.9)
|
||||
|
||||
otherwise,
|
||||
if the enclosing namespace has internal linkage,
|
||||
the name has internal linkage;
|
||||
|
||||
- [(4.10)](#4.10)
|
||||
|
||||
otherwise,
|
||||
if the declaration of the name is
|
||||
attached to a named module ([[module.unit]](module.unit "10.1 Module units and purviews"))
|
||||
and is not exported ([[module.interface]](module.interface "10.2 Export declaration")),
|
||||
the name has module linkage;
|
||||
|
||||
- [(4.11)](#4.11)
|
||||
|
||||
otherwise,
|
||||
the name has external linkage[.](#4.sentence-3)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2994)
|
||||
|
||||
In addition,
|
||||
a member function,
|
||||
a static data member,
|
||||
a named class or enumeration that inhabits a class scope, or
|
||||
an unnamed class or enumeration defined in a typedef declaration
|
||||
that inhabits a class scope
|
||||
such that the class or enumeration
|
||||
has the typedef name for linkage purposes ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),
|
||||
has the same linkage, if any, as the name of the class of which it is a member[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3005)
|
||||
|
||||
[*Example [1](#example-1)*: static void f();extern "C" void h();static int i = 0; // #1void q() {extern void f(); // internal linkageextern void g(); // ::g, external linkageextern void h(); // C language linkageint i; // #2: i has no linkage{extern void f(); // internal linkageextern int i; // #3: internal linkage}}
|
||||
|
||||
Even though the declaration at line #2 hides the declaration at line #1,
|
||||
the declaration at line #3 still redeclares #1 and receives internal linkage[.](#6.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3026)
|
||||
|
||||
Names not covered by these rules have no linkage[.](#7.sentence-1)
|
||||
|
||||
Moreover, except as
|
||||
noted, a name declared at [block scope](basic.scope.block#def:scope,block "6.4.3 Block scope [basic.scope.block]") has no
|
||||
linkage[.](#7.sentence-2)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3032)
|
||||
|
||||
Two declarations of entities declare the same entity
|
||||
if, considering declarations of unnamed types to introduce their names
|
||||
for linkage purposes, if any ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
they correspond ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")),
|
||||
have the same target scope that is not a function or template parameter scope,
|
||||
neither is a name-independent declaration,
|
||||
and either
|
||||
|
||||
- [(8.1)](#8.1)
|
||||
|
||||
they appear in the same translation unit, or
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
they both declare type aliases or namespace aliases that have the same underlying entity, or
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
they both declare names with module linkage and are attached to the same module, or
|
||||
|
||||
- [(8.4)](#8.4)
|
||||
|
||||
they both declare names with external linkage[.](#8.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
There are other circumstances in which declarations declare
|
||||
the same entity ([[dcl.link]](dcl.link "9.12 Linkage specifications"), [[temp.type]](temp.type "13.6 Type equivalence"), [[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization"))[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3055)
|
||||
|
||||
If a declaration H that declares a name with internal linkage
|
||||
precedes a declaration D in another translation unit U and
|
||||
would declare the same entity as D if it appeared in U,
|
||||
the program is ill-formed[.](#9.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Such an H can appear only in a header unit[.](#9.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3064)
|
||||
|
||||
If two declarations of an entity are
|
||||
attached to different modules, the program is ill-formed;
|
||||
no diagnostic is required if neither is reachable from the other[.](#10.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
"decls.h":int f(); // #1, attached to the global moduleint g(); // #2, attached to the global module
|
||||
|
||||
Module interface of M:module;#include "decls.h"export module M;export using ::f; // OK, does not declare an entity, exports #1int g(); // error: matches #2, but attached to Mexport int h(); // #3export int k(); // #4
|
||||
|
||||
Other translation unit:import M;static int h(); // error: matches #3int k(); // error: matches #4 â *end example*]
|
||||
|
||||
As a consequence of these rules,
|
||||
all declarations of an entity are attached to the same module;
|
||||
the entity is said to be [*attached*](#def:attached,entity "6.7 Program and linkage [basic.link]") to that module[.](#10.sentence-2)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3094)
|
||||
|
||||
For any two declarations of an entity E:
|
||||
|
||||
- [(11.1)](#11.1)
|
||||
|
||||
If one declares E to be a variable or function,
|
||||
the other shall declare E as one of the same type[.](#11.1.sentence-1)
|
||||
|
||||
- [(11.2)](#11.2)
|
||||
|
||||
If one declares E to be an enumerator, the other shall do so[.](#11.2.sentence-1)
|
||||
|
||||
- [(11.3)](#11.3)
|
||||
|
||||
If one declares E to be a namespace, the other shall do so[.](#11.3.sentence-1)
|
||||
|
||||
- [(11.4)](#11.4)
|
||||
|
||||
If one declares E to be a type,
|
||||
the other shall declare E to be a type of the same kind ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))[.](#11.4.sentence-1)
|
||||
|
||||
- [(11.5)](#11.5)
|
||||
|
||||
If one declares E to be a class template,
|
||||
the other shall do so with the same kind and
|
||||
an equivalent [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#11.5.sentence-1)
|
||||
[*Note [5](#note-5)*:
|
||||
The declarations can supply different default template arguments[.](#11.5.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
- [(11.6)](#11.6)
|
||||
|
||||
If one declares E to be a function template or
|
||||
a (partial specialization of a) variable template,
|
||||
the other shall declare E to be one
|
||||
with an equivalent [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") and type[.](#11.6.sentence-1)
|
||||
|
||||
- [(11.7)](#11.7)
|
||||
|
||||
If one declares E to be an alias template,
|
||||
the other shall declare E to be one with
|
||||
an equivalent [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") and [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]")[.](#11.7.sentence-1)
|
||||
|
||||
- [(11.8)](#11.8)
|
||||
|
||||
If one declares E to be a concept, the other shall do so[.](#11.8.sentence-1)
|
||||
|
||||
Types are compared after all adjustments of types (during which
|
||||
typedefs ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")) are replaced by their definitions);
|
||||
declarations for an array
|
||||
object can specify array types that differ by the presence or absence of
|
||||
a major array bound ([[dcl.array]](dcl.array "9.3.4.5 Arrays"))[.](#11.sentence-2)
|
||||
|
||||
No diagnostic is required if neither declaration is reachable from the other[.](#11.sentence-3)
|
||||
|
||||
[*Example [3](#example-3)*: int f(int x, int x); // error: different entities for xvoid g(); // #1void g(int); // OK, different entity from #1int g(); // error: same entity as #1 with different typevoid h(); // #2namespace h {} // error: same entity as #2, but not a function â *end example*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3145)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
Linkage to non-C++ declarations can be achieved using a[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]") ([[dcl.link]](dcl.link "9.12 Linkage specifications"))[.](#12.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3152)
|
||||
|
||||
A declaration D [*names*](#def:name "6.7 Program and linkage [basic.link]") an entity E if
|
||||
|
||||
- [(13.1)](#13.1)
|
||||
|
||||
D contains a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") whose closure type is E,
|
||||
|
||||
- [(13.2)](#13.2)
|
||||
|
||||
D contains
|
||||
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") or a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") that, respectively, represents or designates E,
|
||||
|
||||
- [(13.3)](#13.3)
|
||||
|
||||
D is an injected declaration ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||||
whose characteristic sequence contains a reflection
|
||||
that represents
|
||||
a data member description (T, N, A, W, NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))
|
||||
for which T is E,
|
||||
|
||||
- [(13.4)](#13.4)
|
||||
|
||||
E is not a function or function template and D contains an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"),[*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]"), or[*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") denoting E, or
|
||||
|
||||
- [(13.5)](#13.5)
|
||||
|
||||
E is a function or function template andD contains an expression that names E ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")) or
|
||||
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") that refers to a set of overloads that contains E[.](#13.sentence-1)
|
||||
[*Note [7](#note-7)*:
|
||||
Non-dependent names in an instantiated declaration
|
||||
do not refer to a set of overloads ([[temp.res]](temp.res "13.8 Name resolution"))[.](#13.5.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3186)
|
||||
|
||||
A declaration is an [*exposure*](#def:exposure "6.7 Program and linkage [basic.link]") if it either names a TU-local entity (defined below), ignoring
|
||||
|
||||
- [(14.1)](#14.1)
|
||||
|
||||
the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") for a non-inline function or function template
|
||||
(but not the deduced return type
|
||||
for a (possibly instantiated) definition of a function
|
||||
with a declared return type that uses a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))),
|
||||
|
||||
- [(14.2)](#14.2)
|
||||
|
||||
the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") for a variable or variable template (but not the variable's type),
|
||||
|
||||
- [(14.3)](#14.3)
|
||||
|
||||
friend declarations in a class definition, and
|
||||
|
||||
- [(14.4)](#14.4)
|
||||
|
||||
any reference to a non-volatile const object or reference
|
||||
with internal or no linkage initialized with a constant expression
|
||||
that is not an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")),
|
||||
|
||||
or defines a constexpr variable initialized to a TU-local value (defined below)[.](#14.sentence-1)
|
||||
|
||||
[*Note [8](#note-8)*:
|
||||
|
||||
An inline function template can be an exposure even though
|
||||
certain explicit specializations of it would be usable in other translation units[.](#14.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3212)
|
||||
|
||||
An entity is [*TU-local*](#def:TU-local,entity "6.7 Program and linkage [basic.link]") if it is
|
||||
|
||||
- [(15.1)](#15.1)
|
||||
|
||||
a type, type alias, namespace, namespace alias, function, variable, or template that
|
||||
* [(15.1.1)](#15.1.1)
|
||||
|
||||
has a name with internal linkage, or
|
||||
|
||||
* [(15.1.2)](#15.1.2)
|
||||
|
||||
does not have a name with linkage and is declared,
|
||||
or introduced by a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
within the definition of a TU-local entity,
|
||||
|
||||
- [(15.2)](#15.2)
|
||||
|
||||
a type with no name that is defined outside a[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]"),
|
||||
function body, or[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") or is introduced by a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") that is used to declare only TU-local entities,
|
||||
|
||||
- [(15.3)](#15.3)
|
||||
|
||||
a specialization of a TU-local template,
|
||||
|
||||
- [(15.4)](#15.4)
|
||||
|
||||
a specialization of a template with any TU-local template argument, or
|
||||
|
||||
- [(15.5)](#15.5)
|
||||
|
||||
a specialization of a template
|
||||
whose (possibly instantiated) declaration is an exposure[.](#15.sentence-1)
|
||||
[*Note [9](#note-9)*:
|
||||
A specialization can be produced by implicit or explicit instantiation[.](#15.5.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3244)
|
||||
|
||||
A value or object is [*TU-local*](#def:TU-local,value_or_object "6.7 Program and linkage [basic.link]") if either
|
||||
|
||||
- [(16.1)](#16.1)
|
||||
|
||||
it is of TU-local type,
|
||||
|
||||
- [(16.2)](#16.2)
|
||||
|
||||
it is, or is a pointer to,
|
||||
a TU-local function or the object associated with a TU-local variable,
|
||||
|
||||
- [(16.3)](#16.3)
|
||||
|
||||
it is an object of class or array type and
|
||||
any of its subobjects or
|
||||
any of the objects or functions
|
||||
to which its non-static data members of reference type refer
|
||||
is TU-local and is usable in constant expressions, or
|
||||
|
||||
- [(16.4)](#16.4)
|
||||
|
||||
it is a reflection value ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")) that represents
|
||||
* [(16.4.1)](#16.4.1)
|
||||
|
||||
an entity, value, or object that is TU-local,
|
||||
|
||||
* [(16.4.2)](#16.4.2)
|
||||
|
||||
a direct base class relationship (D, B) ([[class.derived.general]](class.derived.general "11.7.1 General"))
|
||||
for which either D or B is TU-local, or
|
||||
|
||||
* [(16.4.3)](#16.4.3)
|
||||
|
||||
a data member description (T, N, A, W, NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))
|
||||
for which T is TU-local[.](#16.sentence-1)
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3272)
|
||||
|
||||
If a (possibly instantiated) declaration of, or a deduction guide for,
|
||||
a non-TU-local entity in a module interface unit
|
||||
(outside the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]"), if any) or
|
||||
module partition ([[module.unit]](module.unit "10.1 Module units and purviews")) is an exposure,
|
||||
the program is ill-formed[.](#17.sentence-1)
|
||||
|
||||
Such a declaration in any other context is deprecated ([[depr.local]](depr.local "D.2 Non-local use of TU-local entities"))[.](#17.sentence-2)
|
||||
|
||||
[18](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3280)
|
||||
|
||||
If a declaration that appears in one translation unit
|
||||
names a TU-local entity declared
|
||||
in another translation unit that is not a header unit,
|
||||
the program is ill-formed[.](#18.sentence-1)
|
||||
|
||||
A declaration instantiated for a template specialization ([[temp.spec]](temp.spec "13.9 Template instantiation and specialization"))
|
||||
appears at the point of instantiation of the specialization ([[temp.point]](temp.point "13.8.4.1 Point of instantiation"))[.](#18.sentence-2)
|
||||
|
||||
[19](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L3288)
|
||||
|
||||
[*Example [4](#example-4)*:
|
||||
|
||||
Translation unit #1:export module A;static void f() {}inline void it() { f(); } // error: is an exposure of fstatic inline void its() { f(); } // OKtemplate<int> void g() { its(); } // OKtemplate void g<0>();
|
||||
|
||||
decltype(f) *fp; // error: f (though not its type) is TU-localauto &fr = f; // OKconstexpr auto &fr2 = fr; // error: is an exposure of fconstexpr static auto fp2 = fr; // OKstruct S { void (&ref)(); } s{f}; // OK, value is TU-localconstexpr extern struct W { S &s; } wrap{s}; // OK, value is not TU-localstatic auto x = []{f();}; // OKauto x2 = x; // error: the closure type is TU-localint y = ([]{f();}(),0); // error: the closure type is not TU-localint y2 = (x,0); // OKnamespace N {struct A {}; void adl(A); static void adl(int);}void adl(double);
|
||||
|
||||
inline void h(auto x) { adl(x); } // OK, but certain specializations are exposuresconstexpr std::meta::info r1 = ^^g<0>; // OKnamespace N2 {static constexpr std::meta::info r2 = ^^g<1>; // OK, r2 is TU-local}constexpr std::meta::info r3 = ^^f; // error: r3 is an exposure of fconstexpr auto ctx = std::meta::access_context::current();constexpr std::meta::info r4 = std::meta::members_of(^^N2, ctx)[0]; // error: r4 is an exposure of N2::r2
|
||||
|
||||
Translation unit #2:module A;void other() { g<0>(); // OK, specialization is explicitly instantiated g<1>(); // error: instantiation uses TU-local its h(N::A{}); // error: overload set contains TU-local N::adl(int) h(0); // OK, calls adl(double) adl(N::A{}); // OK; N::adl(int) not found, calls N::adl(N::A) fr(); // OK, calls fconstexpr auto ptr = fr; // error: fr is not usable in constant expressions here} â *end example*]
|
||||
948
cppdraft/basic/lookup.md
Normal file
948
cppdraft/basic/lookup.md
Normal file
@@ -0,0 +1,948 @@
|
||||
[basic.lookup]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [basic.lookup]
|
||||
|
||||
### [6.5.1](#general) General [[basic.lookup.general]](basic.lookup.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1624)
|
||||
|
||||
[*Name lookup*](#def:lookup,name "6.5.1 General [basic.lookup.general]") associates the use of a name
|
||||
with a set of declarations ([[basic.def]](basic.def "6.2 Declarations and definitions")) of that name[.](#general-1.sentence-1)
|
||||
|
||||
The name lookup rules apply uniformly to all names (including[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]")*s* ([[basic.namespace]](basic.namespace "9.9 Namespaces")), and[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")*s* ([[class.name]](class.name "11.3 Class names"))) wherever the grammar allows
|
||||
such names in the context discussed by a particular rule[.](#general-1.sentence-2)
|
||||
|
||||
Unless otherwise specified,
|
||||
the program is ill-formed if no declarations are found[.](#general-1.sentence-3)
|
||||
|
||||
If the declarations found by name lookup
|
||||
all denote functions or function templates,
|
||||
the declarations are said to form an [*overload set*](#def:overload_set "6.5.1 General [basic.lookup.general]")[.](#general-1.sentence-4)
|
||||
|
||||
Otherwise,
|
||||
if the declarations found by name lookup do not all denote the same entity,they are [*ambiguous*](#def:ambiguous "6.5.1 General [basic.lookup.general]") and the program is ill-formed[.](#general-1.sentence-5)
|
||||
|
||||
Overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address of an overload set"))
|
||||
takes place after name lookup has succeeded[.](#general-1.sentence-6)
|
||||
|
||||
The access rules ([[class.access]](class.access "11.8 Member access control"))
|
||||
are considered only once name lookup and
|
||||
function overload resolution (if applicable) have succeeded[.](#general-1.sentence-7)
|
||||
|
||||
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[.](#general-1.sentence-8)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1650)
|
||||
|
||||
A program point P is said to follow
|
||||
any declaration in the same translation unit
|
||||
whose locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2 Point of declaration")) is before P[.](#general-2.sentence-1)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
The declaration might appear in a scope that does not contain P[.](#general-2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A declaration X [*precedes*](#def:declaration,precede "6.5.1 General [basic.lookup.general]") 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
|
||||
|
||||
- [(2.1)](#general-2.1)
|
||||
|
||||
P follows
|
||||
a [*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]") or [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]") that imports D (directly or indirectly), and
|
||||
|
||||
- [(2.2)](#general-2.2)
|
||||
|
||||
X appears after the [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]") in D (if any) and
|
||||
before the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") in D (if any), and
|
||||
|
||||
- [(2.3)](#general-2.3)
|
||||
|
||||
either X is exported or else D and L are part of the same module andX does not inhabit a namespace with internal linkage or
|
||||
declare a name with internal linkage[.](#general-2.sentence-3)
|
||||
[*Note [2](#general-note-2)*:
|
||||
Names declared by a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") have no linkage[.](#general-2.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[*Note [3](#general-note-3)*:
|
||||
|
||||
A [*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]") imports both
|
||||
the named translation unit(s) and
|
||||
any modules named by exported[*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]")*s* within them,
|
||||
recursively[.](#general-2.sentence-4)
|
||||
|
||||
[*Example [1](#general-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*]
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1702)
|
||||
|
||||
A [*single search*](#def:search,single "6.5.1 General [basic.lookup.general]") 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]](basic.pre "6.1 Preamble")) is bound in S[.](#general-3.sentence-1)
|
||||
|
||||
If any such declaration is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names"))
|
||||
is not dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent types")),
|
||||
it is replaced by the declarations named by
|
||||
the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#general-3.sentence-2)
|
||||
|
||||
[4](#general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1714)
|
||||
|
||||
In certain contexts, only certain kinds of declarations are included[.](#general-4.sentence-1)
|
||||
|
||||
After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found[.](#general-4.sentence-2)
|
||||
|
||||
[*Note [4](#general-note-4)*:
|
||||
|
||||
A type (but not a type alias or template)
|
||||
is therefore hidden by any other entity in its scope[.](#general-4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
However, if a lookup is [*type-only*](#def:lookup,type-only "6.5.1 General [basic.lookup.general]"),
|
||||
only declarations of
|
||||
types and templates whose specializations are types are considered;
|
||||
furthermore, if declarations
|
||||
of a type alias and of its underlying entity are found,
|
||||
the declaration of the type alias is discarded
|
||||
instead of the type declaration[.](#general-4.sentence-4)
|
||||
|
||||
### [6.5.2](#class.member.lookup) Member name lookup [[class.member.lookup]](class.member.lookup)
|
||||
|
||||
[1](#class.member.lookup-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1735)
|
||||
|
||||
A [*search*](#def:search "6.5.2 Member name lookup [class.member.lookup]") 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[.](#class.member.lookup-1.sentence-1)
|
||||
|
||||
[*Note [1](#class.member.lookup-note-1)*:
|
||||
|
||||
The result differs only
|
||||
if M is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") or
|
||||
if the single search would find nothing[.](#class.member.lookup-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#class.member.lookup-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1747)
|
||||
|
||||
The [*lookup set*](#def:lookup_set "6.5.2 Member name lookup [class.member.lookup]") for a name N in a class or class template C, called S(N,C),
|
||||
consists of two component sets:
|
||||
the [*declaration set*](#def:declaration_set), a set of members named N; and
|
||||
the [*subobject set*](#def:subobject_set),
|
||||
a set of subobjects where declarations of these members were found
|
||||
(possibly via [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s*)[.](#class.member.lookup-2.sentence-1)
|
||||
|
||||
In the declaration set, type declarations (including injected-class-names)
|
||||
are replaced by the types they designate[.](#class.member.lookup-2.sentence-2)
|
||||
|
||||
S(N,C) is calculated as follows:
|
||||
|
||||
[3](#class.member.lookup-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1757)
|
||||
|
||||
The declaration set is the result of
|
||||
a single search in the scope of C for N from immediately after the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") of C if P is in a complete-class context of C or
|
||||
from P otherwise[.](#class.member.lookup-3.sentence-1)
|
||||
|
||||
If the resulting declaration set is not empty, the subobject set
|
||||
contains C itself, and calculation is complete[.](#class.member.lookup-3.sentence-2)
|
||||
|
||||
[4](#class.member.lookup-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1766)
|
||||
|
||||
Otherwise (i.e., C does not contain a declaration of N or the resulting declaration set is empty), S(N,C) is initially empty[.](#class.member.lookup-4.sentence-1)
|
||||
|
||||
Calculate the lookup set for N in each direct non-dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent types")) base class subobject Bi, and
|
||||
merge each such lookup set S(N,Bi) in turn into S(N,C)[.](#class.member.lookup-4.sentence-2)
|
||||
|
||||
[*Note [2](#class.member.lookup-note-2)*:
|
||||
|
||||
If C is incomplete,
|
||||
only base classes whose [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]") appears before P are considered[.](#class.member.lookup-4.sentence-3)
|
||||
|
||||
If C is an instantiated class, its base classes are not dependent[.](#class.member.lookup-4.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#class.member.lookup-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1779)
|
||||
|
||||
The following steps define the result of merging lookup set S(N,Bi) into the intermediate S(N,C):
|
||||
|
||||
- [(5.1)](#class.member.lookup-5.1)
|
||||
|
||||
If each of the subobject members of S(N,Bi) is a base class
|
||||
subobject of at least one of the subobject members of S(N,C), or ifS(N,Bi) is empty, S(N,C) is unchanged and the merge is complete[.](#class.member.lookup-5.1.sentence-1)
|
||||
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 S(N,Bi), or ifS(N,C) is empty, the new S(N,C) is a copy of S(N,Bi)[.](#class.member.lookup-5.1.sentence-2)
|
||||
|
||||
- [(5.2)](#class.member.lookup-5.2)
|
||||
|
||||
Otherwise, if the declaration sets of S(N,Bi) 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[.](#class.member.lookup-5.2.sentence-1)
|
||||
In
|
||||
subsequent merges, an invalid declaration set is considered different
|
||||
from any other[.](#class.member.lookup-5.2.sentence-2)
|
||||
|
||||
- [(5.3)](#class.member.lookup-5.3)
|
||||
|
||||
Otherwise, the new S(N,C) is a lookup set with the shared set of
|
||||
declarations and the union of the subobject sets[.](#class.member.lookup-5.3.sentence-1)
|
||||
|
||||
[6](#class.member.lookup-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1801)
|
||||
|
||||
The result of the search is the declaration set of S(M,T)[.](#class.member.lookup-6.sentence-1)
|
||||
|
||||
If it is an invalid set, the program is ill-formed[.](#class.member.lookup-6.sentence-2)
|
||||
|
||||
If it differs from the result of a search in T for M in a complete-class context ([[class.mem]](class.mem "11.4 Class members")) of T,
|
||||
the program is ill-formed, no diagnostic required[.](#class.member.lookup-6.sentence-3)
|
||||
|
||||
[*Example [1](#class.member.lookup-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, soS(x,D) is discarded in the first merge step[.](#class.member.lookup-6.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[7](#class.member.lookup-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1826)
|
||||
|
||||
If M is a non-dependent [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]"),
|
||||
conversion function templates that are members of T are considered[.](#class.member.lookup-7.sentence-1)
|
||||
|
||||
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]](basic.scope.scope "6.4.1 General"))[.](#class.member.lookup-7.sentence-2)
|
||||
|
||||
The members of the declaration set of each such lookup set,
|
||||
which shall not be an invalid set, are included in the result[.](#class.member.lookup-7.sentence-3)
|
||||
|
||||
[*Note [3](#class.member.lookup-note-3)*:
|
||||
|
||||
Overload resolution will discard those
|
||||
that cannot convert to the type specified by M ([[temp.over]](temp.over "13.10.4 Overload resolution"))[.](#class.member.lookup-7.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#class.member.lookup-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1839)
|
||||
|
||||
[*Note [4](#class.member.lookup-note-4)*:
|
||||
|
||||
A static member, a nested type or an enumerator defined in a base classT can unambiguously be found even if an object has more than one
|
||||
base class subobject of type T[.](#class.member.lookup-8.sentence-1)
|
||||
|
||||
Two base class subobjects share
|
||||
the non-static member subobjects of their common virtual base classes[.](#class.member.lookup-8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#class.member.lookup-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*]
|
||||
|
||||
[9](#class.member.lookup-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1869)
|
||||
|
||||
[*Note [5](#class.member.lookup-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[.](#class.member.lookup-9.sentence-1)
|
||||
|
||||
This is not an ambiguity[.](#class.member.lookup-9.sentence-2)
|
||||
|
||||
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[.](#class.member.lookup-9.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#class.member.lookup-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(); };
|
||||
|
||||

|
||||
Figure [1](#fig:class.lookup) — Name lookup [[fig:class.lookup]](./fig:class.lookup)
|
||||
|
||||
As illustrated in Figure [1](#fig:class.lookup),
|
||||
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[.](#class.member.lookup-9.sentence-4)
|
||||
|
||||
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*]
|
||||
|
||||
[10](#class.member.lookup-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1912)
|
||||
|
||||
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[.](#class.member.lookup-10.sentence-1)
|
||||
|
||||
[*Example [4](#class.member.lookup-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*]
|
||||
|
||||
[11](#class.member.lookup-11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1935)
|
||||
|
||||
[*Note [6](#class.member.lookup-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]](conv.mem "7.3.13 Pointer-to-member conversions"), [[expr.ref]](expr.ref "7.6.1.5 Class member access"), [[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members"))[.](#class.member.lookup-11.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [5](#class.member.lookup-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; // Unambiguousint D::* mpD = &D::i; // Ambiguous conversion}}; â *end example*]
|
||||
|
||||
### [6.5.3](#unqual) Unqualified name lookup [[basic.lookup.unqual]](basic.lookup.unqual)
|
||||
|
||||
[1](#unqual-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1972)
|
||||
|
||||
A [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") is[*active*](#def: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*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that is active in S at P[.](#unqual-1.sentence-1)
|
||||
|
||||
[2](#unqual-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1979)
|
||||
|
||||
An [*unqualified search*](#def:unqualified_search) in a scope S from a program point P includes the results of searches from P in
|
||||
|
||||
- [(2.1)](#unqual-2.1)
|
||||
|
||||
S, and
|
||||
|
||||
- [(2.2)](#unqual-2.2)
|
||||
|
||||
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*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that is active in U at P[.](#unqual-2.sentence-1)
|
||||
|
||||
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[.](#unqual-2.sentence-2)
|
||||
|
||||
[*Note [1](#unqual-note-1)*:
|
||||
|
||||
When a class scope is searched,
|
||||
the scopes of its base classes are also searched ([[class.member.lookup]](#class.member.lookup "6.5.2 Member name lookup"))[.](#unqual-2.sentence-3)
|
||||
|
||||
If it inherits from a single base,
|
||||
it is as if the scope of the base immediately contains
|
||||
the scope of the derived class[.](#unqual-2.sentence-4)
|
||||
|
||||
Template parameter scopes
|
||||
that are associated with one scope in the chain of parents
|
||||
are also considered ([[temp.local]](temp.local "13.8.2 Locally declared names"))[.](#unqual-2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#unqual-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2005)
|
||||
|
||||
[*Unqualified name lookup*](#def:lookup,unqualified_name "6.5.3 Unqualified name lookup [basic.lookup.unqual]") from a program point performs an unqualified search in its immediate scope[.](#unqual-3.sentence-1)
|
||||
|
||||
[4](#unqual-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2009)
|
||||
|
||||
An [*unqualified name*](#def:name,unqualified "6.5.3 Unqualified name lookup [basic.lookup.unqual]") is a name
|
||||
that does not immediately follow a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") or
|
||||
the . or -> in a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")),
|
||||
possibly after a template keyword or ~[.](#unqual-4.sentence-1)
|
||||
|
||||
Unless otherwise specified,
|
||||
such a name undergoes unqualified name lookup from the point where it appears[.](#unqual-4.sentence-2)
|
||||
|
||||
[5](#unqual-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2017)
|
||||
|
||||
An unqualified name that is a component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
|
||||
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") or [*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") of
|
||||
a [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]") is looked up in the same fashion
|
||||
as the [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") in which it appears[.](#unqual-5.sentence-1)
|
||||
|
||||
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[.](#unqual-5.sentence-2)
|
||||
|
||||
[*Example [1](#unqual-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())::*(); // #2return 0;}int x = g<B, T2>(); // #1 calls B::operator U1 T1::*// #2 calls B::operator U1 T2::* â *end example*]
|
||||
|
||||
[6](#unqual-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2053)
|
||||
|
||||
In a friend declaration [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose lookup context ([[basic.lookup.qual]](#qual "6.5.5 Qualified name lookup")) is a class or namespace S,
|
||||
lookup for an unqualified name
|
||||
that appears after the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") performs a search in the scope associated with S[.](#unqual-6.sentence-1)
|
||||
|
||||
If that lookup finds nothing, it undergoes unqualified name lookup[.](#unqual-6.sentence-2)
|
||||
|
||||
[*Example [2](#unqual-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); // OKfriend void A::f(C); // error: A::N::C not foundfriend void A::f(F); // OKfriend void W::X::g(I); // error: no void X::g(short)friend void W::X::g(D); // OKfriend void W::X::g(F); // OK};} â *end example*]
|
||||
|
||||
### [6.5.4](#argdep) Argument-dependent name lookup [[basic.lookup.argdep]](basic.lookup.argdep)
|
||||
|
||||
[1](#argdep-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2100)
|
||||
|
||||
When the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") in
|
||||
a function call ([[expr.call]](expr.call "7.6.1.3 Function call")) is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]"),
|
||||
and unqualified lookup ([[basic.lookup.unqual]](#unqual "6.5.3 Unqualified name lookup"))
|
||||
for the name in the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") does not find any
|
||||
|
||||
- [(1.1)](#argdep-1.1)
|
||||
|
||||
declaration of a class member, or
|
||||
|
||||
- [(1.2)](#argdep-1.2)
|
||||
|
||||
function declaration inhabiting a block scope, or
|
||||
|
||||
- [(1.3)](#argdep-1.3)
|
||||
|
||||
declaration not of a function or function template
|
||||
|
||||
then lookup for the name also includes the result of[*argument-dependent lookup*](#def:lookup,argument-dependent "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") 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[.](#argdep-1.sentence-1)
|
||||
|
||||
[*Example [1](#argdep-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*]
|
||||
|
||||
[2](#argdep-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2133)
|
||||
|
||||
[*Note [1](#argdep-note-1)*:
|
||||
|
||||
For purposes of determining
|
||||
(during parsing) whether an expression is a[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") for a function call, the usual name lookup
|
||||
rules apply[.](#argdep-2.sentence-1)
|
||||
|
||||
In some cases
|
||||
a name followed by < is treated as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") even though name lookup did not find a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") (see [[temp.names]](temp.names "13.3 Names of template specializations"))[.](#argdep-2.sentence-2)
|
||||
|
||||
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 nameint y = g<N::A>(N::A()); // OK, lookup of g finds a function, g treated as template nameint z = h<N::A>(N::A()); // error: h< does not begin a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
The rules have no effect on the syntactic interpretation of an expression[.](#argdep-2.sentence-4)
|
||||
|
||||
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[.](#argdep-2.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#argdep-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2178)
|
||||
|
||||
For each argument type T in the function call,
|
||||
there is a set of zero or more [*associated entities*](#def:entity,associated "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") to be considered[.](#argdep-3.sentence-1)
|
||||
|
||||
The set of entities is determined entirely by
|
||||
the types of the function arguments
|
||||
(and any type template template arguments)[.](#argdep-3.sentence-2)
|
||||
|
||||
Any [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* and [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* used to specify the types
|
||||
do not contribute to this set[.](#argdep-3.sentence-3)
|
||||
|
||||
The set of entities
|
||||
is determined in the following way:
|
||||
|
||||
- [(3.1)](#argdep-3.1)
|
||||
|
||||
If T is std::meta::info ([[meta.syn]](meta.syn "21.4.1 Header <meta> synopsis")),
|
||||
its associated set of entities is the singleton containing
|
||||
the enumeration type std::meta::operators ([[meta.reflection.operators]](meta.reflection.operators "21.4.5 Operator representations"))[.](#argdep-3.1.sentence-1)
|
||||
[*Note [2](#argdep-note-2)*:
|
||||
The std::meta::info type is a type alias,
|
||||
so an explicit rule is needed to associate calls
|
||||
whose arguments are reflections with the namespace std::meta[.](#argdep-3.1.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
- [(3.2)](#argdep-3.2)
|
||||
|
||||
If T is any other fundamental type, its associated set of
|
||||
entities is empty[.](#argdep-3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#argdep-3.3)
|
||||
|
||||
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[.](#argdep-3.3.sentence-1)
|
||||
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[.](#argdep-3.3.sentence-2)
|
||||
[*Note [3](#argdep-note-3)*:
|
||||
Constant template arguments,
|
||||
variable template template arguments, and
|
||||
concept template arguments
|
||||
do not
|
||||
contribute to the set of associated entities[.](#argdep-3.3.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(3.4)](#argdep-3.4)
|
||||
|
||||
If T is an enumeration type,
|
||||
its associated entities are T and, if it is a class member, the member's class[.](#argdep-3.4.sentence-1)
|
||||
|
||||
- [(3.5)](#argdep-3.5)
|
||||
|
||||
If T is a pointer to U or an array of U,
|
||||
its associated entities are those associated with U[.](#argdep-3.5.sentence-1)
|
||||
|
||||
- [(3.6)](#argdep-3.6)
|
||||
|
||||
If T is a function type, its associated
|
||||
entities are those associated with the function parameter types and those
|
||||
associated with the return type[.](#argdep-3.6.sentence-1)
|
||||
|
||||
- [(3.7)](#argdep-3.7)
|
||||
|
||||
If T is a pointer to a member function of a classX, its associated entities are those associated
|
||||
with the function parameter types and return type, together with those
|
||||
associated with X[.](#argdep-3.7.sentence-1)
|
||||
|
||||
- [(3.8)](#argdep-3.8)
|
||||
|
||||
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[.](#argdep-3.8.sentence-1)
|
||||
|
||||
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[.](#argdep-3.sentence-5)
|
||||
|
||||
Additionally, if the aforementioned overload set is named with
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"), its associated entities also include
|
||||
its template template arguments and
|
||||
those associated with its type template arguments[.](#argdep-3.sentence-6)
|
||||
|
||||
[4](#argdep-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2254)
|
||||
|
||||
The [*associated namespaces*](#def: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]](namespace.def "9.9.2 Namespace definition"))
|
||||
of those namespaces[.](#argdep-4.sentence-1)
|
||||
|
||||
Argument-dependent lookup finds
|
||||
all declarations of functions and function templates that
|
||||
|
||||
- [(4.1)](#argdep-4.1)
|
||||
|
||||
are found by a search of any associated namespace, or
|
||||
|
||||
- [(4.2)](#argdep-4.2)
|
||||
|
||||
are declared as a friend ([[class.friend]](class.friend "11.8.4 Friends")) of any class
|
||||
with a reachable definition in the set of associated entities, or
|
||||
|
||||
- [(4.3)](#argdep-4.3)
|
||||
|
||||
are exported,
|
||||
are attached to a named module M ([[module.interface]](module.interface "10.2 Export declaration")),
|
||||
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]](basic.link "6.7 Program and linkage"))[.](#argdep-4.sentence-2)
|
||||
|
||||
If the lookup is for a dependent name ([[temp.dep]](temp.dep "13.8.3 Dependent names"), [[temp.dep.candidate]](temp.dep.candidate "13.8.4.2 Candidate functions")),
|
||||
the above lookup is also performed
|
||||
from each point in the instantiation context ([[module.context]](module.context "10.6 Instantiation 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]](module.global.frag "10.4 Global module fragment")) or has internal linkage[.](#argdep-4.sentence-3)
|
||||
|
||||
[5](#argdep-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2282)
|
||||
|
||||
[*Example [2](#argdep-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*]
|
||||
|
||||
[6](#argdep-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2324)
|
||||
|
||||
[*Note [4](#argdep-note-4)*:
|
||||
|
||||
The associated namespace can include namespaces
|
||||
already considered by ordinary unqualified lookup[.](#argdep-6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#argdep-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::fextern void g(NS::T, float);
|
||||
g(parm, 1); // OK, calls g(NS::T, float)} â *end example*]
|
||||
|
||||
### [6.5.5](#qual) Qualified name lookup [[basic.lookup.qual]](basic.lookup.qual)
|
||||
|
||||
#### [6.5.5.1](#qual.general) General [[basic.lookup.qual.general]](basic.lookup.qual.general)
|
||||
|
||||
[1](#qual.general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2350)
|
||||
|
||||
Lookup of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") followed by a :: scope resolution operator
|
||||
considers only
|
||||
namespaces, types, and templates whose specializations are types[.](#qual.general-1.sentence-1)
|
||||
|
||||
If a
|
||||
name,[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),[*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), or[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") is followed by a ::,
|
||||
it shall either be
|
||||
a dependent [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers")) or
|
||||
it shall designate a namespace, class, enumeration, or dependent type,
|
||||
and the :: is never interpreted as
|
||||
a complete [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#qual.general-1.sentence-2)
|
||||
|
||||
[*Example [1](#qual.general-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*]
|
||||
|
||||
[2](#qual.general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2393)
|
||||
|
||||
A member-qualified name is
|
||||
the (unique) component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")), if any, of
|
||||
|
||||
- [(2.1)](#qual.general-2.1)
|
||||
|
||||
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") or
|
||||
|
||||
- [(2.2)](#qual.general-2.2)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of the form[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") :: or [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ::
|
||||
|
||||
in the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))[.](#qual.general-2.sentence-1)
|
||||
|
||||
A [*qualified name*](#def:name,qualified "6.5.5.1 General [basic.lookup.qual.general]") is
|
||||
|
||||
- [(2.3)](#qual.general-2.3)
|
||||
|
||||
a member-qualified name or
|
||||
|
||||
- [(2.4)](#qual.general-2.4)
|
||||
|
||||
the terminal name of
|
||||
* [(2.4.1)](#qual.general-2.4.1)
|
||||
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
|
||||
* [(2.4.2)](#qual.general-2.4.2)
|
||||
|
||||
a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),
|
||||
|
||||
* [(2.4.3)](#qual.general-2.4.3)
|
||||
|
||||
a [*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||||
|
||||
* [(2.4.4)](#qual.general-2.4.4)
|
||||
|
||||
a [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]"), or
|
||||
|
||||
* [(2.4.5)](#qual.general-2.4.5)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]") that has a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"))[.](#qual.general-2.sentence-2)
|
||||
|
||||
The [*lookup context*](#def:lookup_context "6.5.5.1 General [basic.lookup.qual.general]") of a member-qualified name is
|
||||
the type of its associated object expression
|
||||
(considered dependent if the object expression is type-dependent)[.](#qual.general-2.sentence-3)
|
||||
|
||||
The lookup context of any other qualified name is
|
||||
the type, template, or namespace
|
||||
nominated by the preceding [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#qual.general-2.sentence-4)
|
||||
|
||||
[*Note [1](#qual.general-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[.](#qual.general-2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#qual.general-example-2)*:
|
||||
|
||||
In N::C::m.Base::f()Base is a member-qualified name;
|
||||
the other qualified names are C, m, and f[.](#qual.general-2.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#qual.general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2440)
|
||||
|
||||
[*Qualified name lookup*](#def:lookup,qualified_name "6.5.5.1 General [basic.lookup.qual.general]") in a class, namespace, or enumeration performs
|
||||
a search of the scope associated with it ([[class.member.lookup]](#class.member.lookup "6.5.2 Member name lookup"))
|
||||
except as specified below[.](#qual.general-3.sentence-1)
|
||||
|
||||
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]](temp.dep.type "13.8.3.2 Dependent types")) or
|
||||
is not a class or class template[.](#qual.general-3.sentence-2)
|
||||
|
||||
If nothing is found by qualified lookup for a member-qualified name
|
||||
that is the terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
|
||||
is not dependent, it undergoes unqualified lookup[.](#qual.general-3.sentence-3)
|
||||
|
||||
[*Note [2](#qual.general-note-2)*:
|
||||
|
||||
During lookup for a template specialization, no names are dependent[.](#qual.general-3.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#qual.general-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*]
|
||||
|
||||
[4](#qual.general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2485)
|
||||
|
||||
If a qualified name Q follows a ~:
|
||||
|
||||
- [(4.1)](#qual.general-4.1)
|
||||
|
||||
If Q is a member-qualified name,
|
||||
it undergoes unqualified lookup as well as qualified lookup[.](#qual.general-4.1.sentence-1)
|
||||
|
||||
- [(4.2)](#qual.general-4.2)
|
||||
|
||||
Otherwise, its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") N shall nominate a type[.](#qual.general-4.2.sentence-1)
|
||||
If N has another [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") S,Q is looked up as if its lookup context were that nominated by S[.](#qual.general-4.2.sentence-2)
|
||||
|
||||
- [(4.3)](#qual.general-4.3)
|
||||
|
||||
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)[.](#qual.general-4.3.sentence-1)
|
||||
|
||||
- [(4.4)](#qual.general-4.4)
|
||||
|
||||
Otherwise, Q undergoes unqualified lookup[.](#qual.general-4.4.sentence-1)
|
||||
|
||||
- [(4.5)](#qual.general-4.5)
|
||||
|
||||
Each lookup for Q considers only
|
||||
types (if Q is not followed by a <) and
|
||||
templates whose specializations are types[.](#qual.general-4.5.sentence-1)
|
||||
If it finds nothing or is ambiguous, it is discarded[.](#qual.general-4.5.sentence-2)
|
||||
|
||||
- [(4.6)](#qual.general-4.6)
|
||||
|
||||
The [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") 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[.](#qual.general-4.6.sentence-1)
|
||||
|
||||
[*Example [4](#qual.general-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.qual) Class members [[class.qual]](class.qual)
|
||||
|
||||
[1](#class.qual-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2537)
|
||||
|
||||
In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored,[18](#footnote-18 "Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.")
|
||||
|
||||
- [(1.1)](#class.qual-1.1)
|
||||
|
||||
if the search finds the injected-class-name of C ([[class.pre]](class.pre "11.1 Preamble")), or
|
||||
|
||||
- [(1.2)](#class.qual-1.2)
|
||||
|
||||
if N is dependent and
|
||||
is the terminal name of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))
|
||||
that names a constructor,
|
||||
|
||||
N is instead considered to name the constructor of class C[.](#class.qual-1.sentence-1)
|
||||
|
||||
Such a constructor name shall be used only
|
||||
in the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of a (friend) declaration of a constructor or
|
||||
in a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")[.](#class.qual-1.sentence-2)
|
||||
|
||||
[*Example [1](#class.qual-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 namestruct A::A a2; // object of type A â *end example*]
|
||||
|
||||
[18)](#footnote-18)[18)](#footnoteref-18)
|
||||
|
||||
Lookups in which
|
||||
function names are ignored include names appearing in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")[.](#footnote-18.sentence-1)
|
||||
|
||||
#### [6.5.5.3](#namespace.qual) Namespace members [[namespace.qual]](namespace.qual)
|
||||
|
||||
[1](#namespace.qual-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2574)
|
||||
|
||||
Qualified name lookup in a namespace N additionally searches
|
||||
every element of the inline namespace set of N ([[namespace.def]](namespace.def "9.9.2 Namespace definition"))[.](#namespace.qual-1.sentence-1)
|
||||
|
||||
If nothing is found,
|
||||
the results of the lookup are the results of qualified name lookup
|
||||
in each namespace nominated by a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that precedes the point of the lookup and
|
||||
inhabits N or an element of N's inline namespace set[.](#namespace.qual-1.sentence-2)
|
||||
|
||||
[*Note [1](#namespace.qual-note-1)*:
|
||||
|
||||
If a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") refers to a namespace
|
||||
that has already been considered, it does not affect the result[.](#namespace.qual-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#namespace.qual-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*]
|
||||
|
||||
[2](#namespace.qual-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2640)
|
||||
|
||||
[*Note [2](#namespace.qual-note-2)*:
|
||||
|
||||
The same declaration found more than once is not an ambiguity (because
|
||||
it is still a unique declaration)[.](#namespace.qual-2.sentence-1)
|
||||
|
||||
[*Example [2](#namespace.qual-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*]
|
||||
|
||||
[3](#namespace.qual-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2685)
|
||||
|
||||
[*Example [3](#namespace.qual-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*]
|
||||
|
||||
[4](#namespace.qual-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2713)
|
||||
|
||||
[*Note [3](#namespace.qual-note-3)*:
|
||||
|
||||
Class and enumeration declarations are not discarded
|
||||
because of other declarations found in other searches[.](#namespace.qual-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [4](#namespace.qual-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](#elab) Elaborated type specifiers [[basic.lookup.elab]](basic.lookup.elab)
|
||||
|
||||
[1](#elab-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2745)
|
||||
|
||||
If the [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") or enum keyword
|
||||
in an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is followed by an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") that is not followed by ::,
|
||||
lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is type-only ([[basic.lookup.general]](#general "6.5.1 General"))[.](#elab-1.sentence-1)
|
||||
|
||||
[*Note [1](#elab-note-1)*:
|
||||
|
||||
In general, the recognition of an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") depends on the following tokens[.](#elab-1.sentence-2)
|
||||
|
||||
If the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is followed by ::,
|
||||
see [[basic.lookup.qual]](#qual "6.5.5 Qualified name lookup")[.](#elab-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#elab-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2758)
|
||||
|
||||
If the terminal name of the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is a qualified name,
|
||||
lookup for it is type-only[.](#elab-2.sentence-1)
|
||||
|
||||
If the name lookup does not find a previously declared [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),
|
||||
the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is ill-formed[.](#elab-2.sentence-2)
|
||||
|
||||
[3](#elab-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2765)
|
||||
|
||||
[*Example [1](#elab-example-1)*: struct Node {struct Node* Next; // OK, refers to injected-class-name Nodestruct Data* Data; // OK, declares type Data at global scope and member Data};
|
||||
|
||||
struct Data {struct Node* Node; // OK, refers to Node at global scopefriend struct ::Glob; // error: Glob is not declared, cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))friend struct Glob; // OK, refers to (as yet) undeclared Glob at global scope./* ... */};
|
||||
|
||||
struct Base {struct Data; // OK, declares nested Datastruct ::Data* thatData; // OK, refers to ::Datastruct Base::Data* thisData; // OK, refers to nested Datafriend class ::Data; // OK, global Data is a friendfriend class Data; // OK, nested Data is a friendstruct Data { /* ... */ }; // Defines nested Data};
|
||||
|
||||
struct Data; // OK, redeclares Data at global scopestruct ::Data; // error: cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))struct Base::Data; // error: cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))struct Base::Datum; // error: Datum undefinedstruct Base::Data* pBase; // OK, refers to nested Data â *end example*]
|
||||
|
||||
### [6.5.7](#udir) Using-directives and namespace aliases [[basic.lookup.udir]](basic.lookup.udir)
|
||||
|
||||
[1](#udir-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2800)
|
||||
|
||||
In a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") or [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]"),
|
||||
during the lookup for a [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") or for a name in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") only namespace names are considered[.](#udir-1.sentence-1)
|
||||
220
cppdraft/basic/lookup/argdep.md
Normal file
220
cppdraft/basic/lookup/argdep.md
Normal file
@@ -0,0 +1,220 @@
|
||||
[basic.lookup.argdep]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#argdep)
|
||||
|
||||
### 6.5.4 Argument-dependent name lookup [basic.lookup.argdep]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2100)
|
||||
|
||||
When the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") in
|
||||
a function call ([[expr.call]](expr.call "7.6.1.3 Function call")) is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]"),
|
||||
and unqualified lookup ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified name lookup"))
|
||||
for the name in the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") does not find any
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
declaration of a class member, or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
function declaration inhabiting a block scope, or
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
declaration not of a function or function template
|
||||
|
||||
then lookup for the name also includes the result of[*argument-dependent lookup*](#def:lookup,argument-dependent "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") 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[.](#1.sentence-1)
|
||||
|
||||
[*Example [1](#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*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2133)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
For purposes of determining
|
||||
(during parsing) whether an expression is a[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") for a function call, the usual name lookup
|
||||
rules apply[.](#2.sentence-1)
|
||||
|
||||
In some cases
|
||||
a name followed by < is treated as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") even though name lookup did not find a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") (see [[temp.names]](temp.names "13.3 Names of template specializations"))[.](#2.sentence-2)
|
||||
|
||||
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 nameint y = g<N::A>(N::A()); // OK, lookup of g finds a function, g treated as template nameint z = h<N::A>(N::A()); // error: h< does not begin a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
The rules have no effect on the syntactic interpretation of an expression[.](#2.sentence-4)
|
||||
|
||||
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[.](#2.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2178)
|
||||
|
||||
For each argument type T in the function call,
|
||||
there is a set of zero or more [*associated entities*](#def:entity,associated "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") to be considered[.](#3.sentence-1)
|
||||
|
||||
The set of entities is determined entirely by
|
||||
the types of the function arguments
|
||||
(and any type template template arguments)[.](#3.sentence-2)
|
||||
|
||||
Any [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* and [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* used to specify the types
|
||||
do not contribute to this set[.](#3.sentence-3)
|
||||
|
||||
The set of entities
|
||||
is determined in the following way:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
If T is std::meta::info ([[meta.syn]](meta.syn "21.4.1 Header <meta> synopsis")),
|
||||
its associated set of entities is the singleton containing
|
||||
the enumeration type std::meta::operators ([[meta.reflection.operators]](meta.reflection.operators "21.4.5 Operator representations"))[.](#3.1.sentence-1)
|
||||
[*Note [2](#note-2)*:
|
||||
The std::meta::info type is a type alias,
|
||||
so an explicit rule is needed to associate calls
|
||||
whose arguments are reflections with the namespace std::meta[.](#3.1.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
If T is any other fundamental type, its associated set of
|
||||
entities is empty[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
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[.](#3.3.sentence-1)
|
||||
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[.](#3.3.sentence-2)
|
||||
[*Note [3](#note-3)*:
|
||||
Constant template arguments,
|
||||
variable template template arguments, and
|
||||
concept template arguments
|
||||
do not
|
||||
contribute to the set of associated entities[.](#3.3.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
If T is an enumeration type,
|
||||
its associated entities are T and, if it is a class member, the member's class[.](#3.4.sentence-1)
|
||||
|
||||
- [(3.5)](#3.5)
|
||||
|
||||
If T is a pointer to U or an array of U,
|
||||
its associated entities are those associated with U[.](#3.5.sentence-1)
|
||||
|
||||
- [(3.6)](#3.6)
|
||||
|
||||
If T is a function type, its associated
|
||||
entities are those associated with the function parameter types and those
|
||||
associated with the return type[.](#3.6.sentence-1)
|
||||
|
||||
- [(3.7)](#3.7)
|
||||
|
||||
If T is a pointer to a member function of a classX, its associated entities are those associated
|
||||
with the function parameter types and return type, together with those
|
||||
associated with X[.](#3.7.sentence-1)
|
||||
|
||||
- [(3.8)](#3.8)
|
||||
|
||||
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[.](#3.8.sentence-1)
|
||||
|
||||
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[.](#3.sentence-5)
|
||||
|
||||
Additionally, if the aforementioned overload set is named with
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"), its associated entities also include
|
||||
its template template arguments and
|
||||
those associated with its type template arguments[.](#3.sentence-6)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2254)
|
||||
|
||||
The [*associated namespaces*](#def: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]](namespace.def "9.9.2 Namespace definition"))
|
||||
of those namespaces[.](#4.sentence-1)
|
||||
|
||||
Argument-dependent lookup finds
|
||||
all declarations of functions and function templates that
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
are found by a search of any associated namespace, or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
are declared as a friend ([[class.friend]](class.friend "11.8.4 Friends")) of any class
|
||||
with a reachable definition in the set of associated entities, or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
are exported,
|
||||
are attached to a named module M ([[module.interface]](module.interface "10.2 Export declaration")),
|
||||
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]](basic.link "6.7 Program and linkage"))[.](#4.sentence-2)
|
||||
|
||||
If the lookup is for a dependent name ([[temp.dep]](temp.dep "13.8.3 Dependent names"), [[temp.dep.candidate]](temp.dep.candidate "13.8.4.2 Candidate functions")),
|
||||
the above lookup is also performed
|
||||
from each point in the instantiation context ([[module.context]](module.context "10.6 Instantiation 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]](module.global.frag "10.4 Global module fragment")) or has internal linkage[.](#4.sentence-3)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2282)
|
||||
|
||||
[*Example [2](#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*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2324)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The associated namespace can include namespaces
|
||||
already considered by ordinary unqualified lookup[.](#6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#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::fextern void g(NS::T, float);
|
||||
g(parm, 1); // OK, calls g(NS::T, float)} â *end example*]
|
||||
46
cppdraft/basic/lookup/elab.md
Normal file
46
cppdraft/basic/lookup/elab.md
Normal file
@@ -0,0 +1,46 @@
|
||||
[basic.lookup.elab]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#elab)
|
||||
|
||||
### 6.5.6 Elaborated type specifiers [basic.lookup.elab]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2745)
|
||||
|
||||
If the [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") or enum keyword
|
||||
in an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is followed by an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") that is not followed by ::,
|
||||
lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is type-only ([[basic.lookup.general]](basic.lookup.general "6.5.1 General"))[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
In general, the recognition of an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") depends on the following tokens[.](#1.sentence-2)
|
||||
|
||||
If the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is followed by ::,
|
||||
see [[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2758)
|
||||
|
||||
If the terminal name of the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is a qualified name,
|
||||
lookup for it is type-only[.](#2.sentence-1)
|
||||
|
||||
If the name lookup does not find a previously declared [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),
|
||||
the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") is ill-formed[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2765)
|
||||
|
||||
[*Example [1](#example-1)*: struct Node {struct Node* Next; // OK, refers to injected-class-name Nodestruct Data* Data; // OK, declares type Data at global scope and member Data};
|
||||
|
||||
struct Data {struct Node* Node; // OK, refers to Node at global scopefriend struct ::Glob; // error: Glob is not declared, cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))friend struct Glob; // OK, refers to (as yet) undeclared Glob at global scope./* ... */};
|
||||
|
||||
struct Base {struct Data; // OK, declares nested Datastruct ::Data* thatData; // OK, refers to ::Datastruct Base::Data* thisData; // OK, refers to nested Datafriend class ::Data; // OK, global Data is a friendfriend class Data; // OK, nested Data is a friendstruct Data { /* ... */ }; // Defines nested Data};
|
||||
|
||||
struct Data; // OK, redeclares Data at global scopestruct ::Data; // error: cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))struct Base::Data; // error: cannot introduce a qualified type ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))struct Base::Datum; // error: Datum undefinedstruct Base::Data* pBase; // OK, refers to nested Data â *end example*]
|
||||
126
cppdraft/basic/lookup/general.md
Normal file
126
cppdraft/basic/lookup/general.md
Normal file
@@ -0,0 +1,126 @@
|
||||
[basic.lookup.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#general)
|
||||
|
||||
### 6.5.1 General [basic.lookup.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1624)
|
||||
|
||||
[*Name lookup*](#def:lookup,name "6.5.1 General [basic.lookup.general]") associates the use of a name
|
||||
with a set of declarations ([[basic.def]](basic.def "6.2 Declarations and definitions")) of that name[.](#1.sentence-1)
|
||||
|
||||
The name lookup rules apply uniformly to all names (including[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]")*s* ([[basic.namespace]](basic.namespace "9.9 Namespaces")), and[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")*s* ([[class.name]](class.name "11.3 Class names"))) wherever the grammar allows
|
||||
such names in the context discussed by a particular rule[.](#1.sentence-2)
|
||||
|
||||
Unless otherwise specified,
|
||||
the program is ill-formed if no declarations are found[.](#1.sentence-3)
|
||||
|
||||
If the declarations found by name lookup
|
||||
all denote functions or function templates,
|
||||
the declarations are said to form an [*overload set*](#def:overload_set "6.5.1 General [basic.lookup.general]")[.](#1.sentence-4)
|
||||
|
||||
Otherwise,
|
||||
if the declarations found by name lookup do not all denote the same entity,they are [*ambiguous*](#def:ambiguous "6.5.1 General [basic.lookup.general]") and the program is ill-formed[.](#1.sentence-5)
|
||||
|
||||
Overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address of an overload set"))
|
||||
takes place after name lookup has succeeded[.](#1.sentence-6)
|
||||
|
||||
The access rules ([[class.access]](class.access "11.8 Member access control"))
|
||||
are considered only once name lookup and
|
||||
function overload resolution (if applicable) have succeeded[.](#1.sentence-7)
|
||||
|
||||
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[.](#1.sentence-8)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1650)
|
||||
|
||||
A program point P is said to follow
|
||||
any declaration in the same translation unit
|
||||
whose locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2 Point of declaration")) is before P[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The declaration might appear in a scope that does not contain P[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A declaration X [*precedes*](#def:declaration,precede "6.5.1 General [basic.lookup.general]") 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
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
P follows
|
||||
a [*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]") or [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]") that imports D (directly or indirectly), and
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
X appears after the [*module-declaration*](module.unit#nt:module-declaration "10.1 Module units and purviews [module.unit]") in D (if any) and
|
||||
before the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") in D (if any), and
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
either X is exported or else D and L are part of the same module andX does not inhabit a namespace with internal linkage or
|
||||
declare a name with internal linkage[.](#2.sentence-3)
|
||||
[*Note [2](#note-2)*:
|
||||
Names declared by a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") have no linkage[.](#2.3.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
A [*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]") imports both
|
||||
the named translation unit(s) and
|
||||
any modules named by exported[*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]")*s* within them,
|
||||
recursively[.](#2.sentence-4)
|
||||
|
||||
[*Example [1](#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*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1702)
|
||||
|
||||
A [*single search*](#def:search,single "6.5.1 General [basic.lookup.general]") 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]](basic.pre "6.1 Preamble")) is bound in S[.](#3.sentence-1)
|
||||
|
||||
If any such declaration is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names"))
|
||||
is not dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent types")),
|
||||
it is replaced by the declarations named by
|
||||
the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1714)
|
||||
|
||||
In certain contexts, only certain kinds of declarations are included[.](#4.sentence-1)
|
||||
|
||||
After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found[.](#4.sentence-2)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
A type (but not a type alias or template)
|
||||
is therefore hidden by any other entity in its scope[.](#4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
However, if a lookup is [*type-only*](#def:lookup,type-only "6.5.1 General [basic.lookup.general]"),
|
||||
only declarations of
|
||||
types and templates whose specializations are types are considered;
|
||||
furthermore, if declarations
|
||||
of a type alias and of its underlying entity are found,
|
||||
the declaration of the type alias is discarded
|
||||
instead of the type declaration[.](#4.sentence-4)
|
||||
259
cppdraft/basic/lookup/qual.md
Normal file
259
cppdraft/basic/lookup/qual.md
Normal file
@@ -0,0 +1,259 @@
|
||||
[basic.lookup.qual]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#qual)
|
||||
|
||||
### 6.5.5 Qualified name lookup [basic.lookup.qual]
|
||||
|
||||
#### [6.5.5.1](#general) General [[basic.lookup.qual.general]](basic.lookup.qual.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2350)
|
||||
|
||||
Lookup of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") followed by a :: scope resolution operator
|
||||
considers only
|
||||
namespaces, types, and templates whose specializations are types[.](#general-1.sentence-1)
|
||||
|
||||
If a
|
||||
name,[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),[*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), or[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") is followed by a ::,
|
||||
it shall either be
|
||||
a dependent [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers")) or
|
||||
it shall designate a namespace, class, enumeration, or dependent type,
|
||||
and the :: is never interpreted as
|
||||
a complete [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#general-1.sentence-2)
|
||||
|
||||
[*Example [1](#general-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*]
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2393)
|
||||
|
||||
A member-qualified name is
|
||||
the (unique) component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")), if any, of
|
||||
|
||||
- [(2.1)](#general-2.1)
|
||||
|
||||
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") or
|
||||
|
||||
- [(2.2)](#general-2.2)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of the form[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") :: or [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ::
|
||||
|
||||
in the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))[.](#general-2.sentence-1)
|
||||
|
||||
A [*qualified name*](#def:name,qualified "6.5.5.1 General [basic.lookup.qual.general]") is
|
||||
|
||||
- [(2.3)](#general-2.3)
|
||||
|
||||
a member-qualified name or
|
||||
|
||||
- [(2.4)](#general-2.4)
|
||||
|
||||
the terminal name of
|
||||
* [(2.4.1)](#general-2.4.1)
|
||||
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
|
||||
* [(2.4.2)](#general-2.4.2)
|
||||
|
||||
a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),
|
||||
|
||||
* [(2.4.3)](#general-2.4.3)
|
||||
|
||||
a [*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||||
|
||||
* [(2.4.4)](#general-2.4.4)
|
||||
|
||||
a [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]"), or
|
||||
|
||||
* [(2.4.5)](#general-2.4.5)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]") that has a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"))[.](#general-2.sentence-2)
|
||||
|
||||
The [*lookup context*](#def:lookup_context "6.5.5.1 General [basic.lookup.qual.general]") of a member-qualified name is
|
||||
the type of its associated object expression
|
||||
(considered dependent if the object expression is type-dependent)[.](#general-2.sentence-3)
|
||||
|
||||
The lookup context of any other qualified name is
|
||||
the type, template, or namespace
|
||||
nominated by the preceding [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#general-2.sentence-4)
|
||||
|
||||
[*Note [1](#general-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[.](#general-2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#general-example-2)*:
|
||||
|
||||
In N::C::m.Base::f()Base is a member-qualified name;
|
||||
the other qualified names are C, m, and f[.](#general-2.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2440)
|
||||
|
||||
[*Qualified name lookup*](#def:lookup,qualified_name "6.5.5.1 General [basic.lookup.qual.general]") in a class, namespace, or enumeration performs
|
||||
a search of the scope associated with it ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))
|
||||
except as specified below[.](#general-3.sentence-1)
|
||||
|
||||
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]](temp.dep.type "13.8.3.2 Dependent types")) or
|
||||
is not a class or class template[.](#general-3.sentence-2)
|
||||
|
||||
If nothing is found by qualified lookup for a member-qualified name
|
||||
that is the terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
|
||||
is not dependent, it undergoes unqualified lookup[.](#general-3.sentence-3)
|
||||
|
||||
[*Note [2](#general-note-2)*:
|
||||
|
||||
During lookup for a template specialization, no names are dependent[.](#general-3.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#general-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*]
|
||||
|
||||
[4](#general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2485)
|
||||
|
||||
If a qualified name Q follows a ~:
|
||||
|
||||
- [(4.1)](#general-4.1)
|
||||
|
||||
If Q is a member-qualified name,
|
||||
it undergoes unqualified lookup as well as qualified lookup[.](#general-4.1.sentence-1)
|
||||
|
||||
- [(4.2)](#general-4.2)
|
||||
|
||||
Otherwise, its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") N shall nominate a type[.](#general-4.2.sentence-1)
|
||||
If N has another [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") S,Q is looked up as if its lookup context were that nominated by S[.](#general-4.2.sentence-2)
|
||||
|
||||
- [(4.3)](#general-4.3)
|
||||
|
||||
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)[.](#general-4.3.sentence-1)
|
||||
|
||||
- [(4.4)](#general-4.4)
|
||||
|
||||
Otherwise, Q undergoes unqualified lookup[.](#general-4.4.sentence-1)
|
||||
|
||||
- [(4.5)](#general-4.5)
|
||||
|
||||
Each lookup for Q considers only
|
||||
types (if Q is not followed by a <) and
|
||||
templates whose specializations are types[.](#general-4.5.sentence-1)
|
||||
If it finds nothing or is ambiguous, it is discarded[.](#general-4.5.sentence-2)
|
||||
|
||||
- [(4.6)](#general-4.6)
|
||||
|
||||
The [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") 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[.](#general-4.6.sentence-1)
|
||||
|
||||
[*Example [4](#general-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.qual) Class members [[class.qual]](class.qual)
|
||||
|
||||
[1](#class.qual-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2537)
|
||||
|
||||
In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored,[18](#footnote-18 "Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.")
|
||||
|
||||
- [(1.1)](#class.qual-1.1)
|
||||
|
||||
if the search finds the injected-class-name of C ([[class.pre]](class.pre "11.1 Preamble")), or
|
||||
|
||||
- [(1.2)](#class.qual-1.2)
|
||||
|
||||
if N is dependent and
|
||||
is the terminal name of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))
|
||||
that names a constructor,
|
||||
|
||||
N is instead considered to name the constructor of class C[.](#class.qual-1.sentence-1)
|
||||
|
||||
Such a constructor name shall be used only
|
||||
in the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of a (friend) declaration of a constructor or
|
||||
in a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")[.](#class.qual-1.sentence-2)
|
||||
|
||||
[*Example [1](#class.qual-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 namestruct A::A a2; // object of type A â *end example*]
|
||||
|
||||
[18)](#footnote-18)[18)](#footnoteref-18)
|
||||
|
||||
Lookups in which
|
||||
function names are ignored include names appearing in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")[.](#footnote-18.sentence-1)
|
||||
|
||||
#### [6.5.5.3](#namespace.qual) Namespace members [[namespace.qual]](namespace.qual)
|
||||
|
||||
[1](#namespace.qual-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2574)
|
||||
|
||||
Qualified name lookup in a namespace N additionally searches
|
||||
every element of the inline namespace set of N ([[namespace.def]](namespace.def "9.9.2 Namespace definition"))[.](#namespace.qual-1.sentence-1)
|
||||
|
||||
If nothing is found,
|
||||
the results of the lookup are the results of qualified name lookup
|
||||
in each namespace nominated by a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that precedes the point of the lookup and
|
||||
inhabits N or an element of N's inline namespace set[.](#namespace.qual-1.sentence-2)
|
||||
|
||||
[*Note [1](#namespace.qual-note-1)*:
|
||||
|
||||
If a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") refers to a namespace
|
||||
that has already been considered, it does not affect the result[.](#namespace.qual-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#namespace.qual-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*]
|
||||
|
||||
[2](#namespace.qual-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2640)
|
||||
|
||||
[*Note [2](#namespace.qual-note-2)*:
|
||||
|
||||
The same declaration found more than once is not an ambiguity (because
|
||||
it is still a unique declaration)[.](#namespace.qual-2.sentence-1)
|
||||
|
||||
[*Example [2](#namespace.qual-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*]
|
||||
|
||||
[3](#namespace.qual-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2685)
|
||||
|
||||
[*Example [3](#namespace.qual-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*]
|
||||
|
||||
[4](#namespace.qual-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2713)
|
||||
|
||||
[*Note [3](#namespace.qual-note-3)*:
|
||||
|
||||
Class and enumeration declarations are not discarded
|
||||
because of other declarations found in other searches[.](#namespace.qual-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [4](#namespace.qual-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*]
|
||||
166
cppdraft/basic/lookup/qual/general.md
Normal file
166
cppdraft/basic/lookup/qual/general.md
Normal file
@@ -0,0 +1,166 @@
|
||||
[basic.lookup.qual.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#qual.general)
|
||||
|
||||
### 6.5.5 Qualified name lookup [[basic.lookup.qual]](basic.lookup.qual#general)
|
||||
|
||||
#### 6.5.5.1 General [basic.lookup.qual.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2350)
|
||||
|
||||
Lookup of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") followed by a :: scope resolution operator
|
||||
considers only
|
||||
namespaces, types, and templates whose specializations are types[.](#1.sentence-1)
|
||||
|
||||
If a
|
||||
name,[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),[*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), or[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") is followed by a ::,
|
||||
it shall either be
|
||||
a dependent [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers")) or
|
||||
it shall designate a namespace, class, enumeration, or dependent type,
|
||||
and the :: is never interpreted as
|
||||
a complete [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#1.sentence-2)
|
||||
|
||||
[*Example [1](#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*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2393)
|
||||
|
||||
A member-qualified name is
|
||||
the (unique) component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")), if any, of
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of the form[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") :: or [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ::
|
||||
|
||||
in the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))[.](#2.sentence-1)
|
||||
|
||||
A [*qualified name*](#def:name,qualified "6.5.5.1 General [basic.lookup.qual.general]") is
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
a member-qualified name or
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
the terminal name of
|
||||
* [(2.4.1)](#2.4.1)
|
||||
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
|
||||
* [(2.4.2)](#2.4.2)
|
||||
|
||||
a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),
|
||||
|
||||
* [(2.4.3)](#2.4.3)
|
||||
|
||||
a [*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||||
|
||||
* [(2.4.4)](#2.4.4)
|
||||
|
||||
a [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]"), or
|
||||
|
||||
* [(2.4.5)](#2.4.5)
|
||||
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]") that has a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"))[.](#2.sentence-2)
|
||||
|
||||
The [*lookup context*](#def:lookup_context "6.5.5.1 General [basic.lookup.qual.general]") of a member-qualified name is
|
||||
the type of its associated object expression
|
||||
(considered dependent if the object expression is type-dependent)[.](#2.sentence-3)
|
||||
|
||||
The lookup context of any other qualified name is
|
||||
the type, template, or namespace
|
||||
nominated by the preceding [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#2.sentence-4)
|
||||
|
||||
[*Note [1](#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[.](#2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
In N::C::m.Base::f()Base is a member-qualified name;
|
||||
the other qualified names are C, m, and f[.](#2.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2440)
|
||||
|
||||
[*Qualified name lookup*](#def:lookup,qualified_name "6.5.5.1 General [basic.lookup.qual.general]") in a class, namespace, or enumeration performs
|
||||
a search of the scope associated with it ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))
|
||||
except as specified below[.](#3.sentence-1)
|
||||
|
||||
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]](temp.dep.type "13.8.3.2 Dependent types")) or
|
||||
is not a class or class template[.](#3.sentence-2)
|
||||
|
||||
If nothing is found by qualified lookup for a member-qualified name
|
||||
that is the terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
|
||||
is not dependent, it undergoes unqualified lookup[.](#3.sentence-3)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
During lookup for a template specialization, no names are dependent[.](#3.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#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*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2485)
|
||||
|
||||
If a qualified name Q follows a ~:
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
If Q is a member-qualified name,
|
||||
it undergoes unqualified lookup as well as qualified lookup[.](#4.1.sentence-1)
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
Otherwise, its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") N shall nominate a type[.](#4.2.sentence-1)
|
||||
If N has another [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") S,Q is looked up as if its lookup context were that nominated by S[.](#4.2.sentence-2)
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
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)[.](#4.3.sentence-1)
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
Otherwise, Q undergoes unqualified lookup[.](#4.4.sentence-1)
|
||||
|
||||
- [(4.5)](#4.5)
|
||||
|
||||
Each lookup for Q considers only
|
||||
types (if Q is not followed by a <) and
|
||||
templates whose specializations are types[.](#4.5.sentence-1)
|
||||
If it finds nothing or is ambiguous, it is discarded[.](#4.5.sentence-2)
|
||||
|
||||
- [(4.6)](#4.6)
|
||||
|
||||
The [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") 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[.](#4.6.sentence-1)
|
||||
|
||||
[*Example [4](#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*]
|
||||
14
cppdraft/basic/lookup/udir.md
Normal file
14
cppdraft/basic/lookup/udir.md
Normal file
@@ -0,0 +1,14 @@
|
||||
[basic.lookup.udir]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#udir)
|
||||
|
||||
### 6.5.7 Using-directives and namespace aliases [basic.lookup.udir]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2800)
|
||||
|
||||
In a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") or [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]"),
|
||||
during the lookup for a [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") or for a name in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") only namespace names are considered[.](#1.sentence-1)
|
||||
100
cppdraft/basic/lookup/unqual.md
Normal file
100
cppdraft/basic/lookup/unqual.md
Normal file
@@ -0,0 +1,100 @@
|
||||
[basic.lookup.unqual]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.5 Name lookup [[basic.lookup]](basic.lookup#unqual)
|
||||
|
||||
### 6.5.3 Unqualified name lookup [basic.lookup.unqual]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1972)
|
||||
|
||||
A [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") is[*active*](#def: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*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that is active in S at P[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1979)
|
||||
|
||||
An [*unqualified search*](#def:unqualified_search) in a scope S from a program point P includes the results of searches from P in
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
S, and
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
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*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that is active in U at P[.](#2.sentence-1)
|
||||
|
||||
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[.](#2.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
When a class scope is searched,
|
||||
the scopes of its base classes are also searched ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#2.sentence-3)
|
||||
|
||||
If it inherits from a single base,
|
||||
it is as if the scope of the base immediately contains
|
||||
the scope of the derived class[.](#2.sentence-4)
|
||||
|
||||
Template parameter scopes
|
||||
that are associated with one scope in the chain of parents
|
||||
are also considered ([[temp.local]](temp.local "13.8.2 Locally declared names"))[.](#2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2005)
|
||||
|
||||
[*Unqualified name lookup*](#def:lookup,unqualified_name "6.5.3 Unqualified name lookup [basic.lookup.unqual]") from a program point performs an unqualified search in its immediate scope[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2009)
|
||||
|
||||
An [*unqualified name*](#def:name,unqualified "6.5.3 Unqualified name lookup [basic.lookup.unqual]") is a name
|
||||
that does not immediately follow a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") or
|
||||
the . or -> in a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")),
|
||||
possibly after a template keyword or ~[.](#4.sentence-1)
|
||||
|
||||
Unless otherwise specified,
|
||||
such a name undergoes unqualified name lookup from the point where it appears[.](#4.sentence-2)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2017)
|
||||
|
||||
An unqualified name that is a component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
|
||||
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") or [*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") of
|
||||
a [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]") is looked up in the same fashion
|
||||
as the [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") in which it appears[.](#5.sentence-1)
|
||||
|
||||
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[.](#5.sentence-2)
|
||||
|
||||
[*Example [1](#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())::*(); // #2return 0;}int x = g<B, T2>(); // #1 calls B::operator U1 T1::*// #2 calls B::operator U1 T2::* â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2053)
|
||||
|
||||
In a friend declaration [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose lookup context ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")) is a class or namespace S,
|
||||
lookup for an unqualified name
|
||||
that appears after the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") performs a search in the scope associated with S[.](#6.sentence-1)
|
||||
|
||||
If that lookup finds nothing, it undergoes unqualified name lookup[.](#6.sentence-2)
|
||||
|
||||
[*Example [2](#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); // OKfriend void A::f(C); // error: A::N::C not foundfriend void A::f(F); // OKfriend void W::X::g(I); // error: no void X::g(short)friend void W::X::g(D); // OKfriend void W::X::g(F); // OK};} â *end example*]
|
||||
298
cppdraft/basic/lval.md
Normal file
298
cppdraft/basic/lval.md
Normal file
@@ -0,0 +1,298 @@
|
||||
[basic.lval]
|
||||
|
||||
# 7 Expressions [[expr]](./#expr)
|
||||
|
||||
## 7.2 Properties of expressions [[expr.prop]](expr.prop#basic.lval)
|
||||
|
||||
### 7.2.1 Value category [basic.lval]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L140)
|
||||
|
||||
Expressions are categorized according to the taxonomy in Figure [2](#fig:basic.lval)[.](#1.sentence-1)
|
||||
|
||||

|
||||
Figure [2](#fig:basic.lval) — Expression category taxonomy [[fig:basic.lval]](./fig:basic.lval)
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
A [*glvalue*](#def:glvalue "7.2.1 Value category [basic.lval]") is an expression whose evaluation determines the identity of an object, function, or non-static data member[.](#1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
A [*prvalue*](#def:prvalue "7.2.1 Value category [basic.lval]") 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[.](#1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
An [*xvalue*](#def:xvalue "7.2.1 Value category [basic.lval]") is a glvalue that denotes an object whose resources can be reused (usually because it is near the end of its lifetime)[.](#1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
An [*lvalue*](#def:lvalue "7.2.1 Value category [basic.lval]") is a glvalue that is not an xvalue[.](#1.4.sentence-1)
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
An [*rvalue*](#def:rvalue "7.2.1 Value category [basic.lval]") is a prvalue or an xvalue[.](#1.5.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L160)
|
||||
|
||||
Every expression belongs to exactly one of the fundamental categories in this
|
||||
taxonomy: lvalue, xvalue, or prvalue[.](#2.sentence-1)
|
||||
|
||||
This property of an expression is called
|
||||
its [*value category*](#def:value_category "7.2.1 Value category [basic.lval]")[.](#2.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The discussion of each built-in operator in[[expr.compound]](expr.compound "7.6 Compound expressions") indicates the category of the value it yields and the value categories
|
||||
of the operands it expects[.](#2.sentence-3)
|
||||
|
||||
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[.](#2.sentence-4)
|
||||
|
||||
User-defined operators are functions, and the categories of
|
||||
values they expect and yield are determined by their parameter and return types[.](#2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L173)
|
||||
|
||||
[*Note [2](#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[.](#3.sentence-1)
|
||||
|
||||
Despite their names, these terms apply to expressions, not values[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L184)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An expression is an xvalue if it is:
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
a move-eligible [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names"))
|
||||
or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](expr.prim.splice "7.5.9 Expression splicing")),
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
the result of calling a function, whether implicitly or explicitly,
|
||||
whose return type is an rvalue reference to object type ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
a cast to an rvalue reference to
|
||||
object type ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")),
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
a subscripting operation with an xvalue array operand ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")),
|
||||
|
||||
- [(4.5)](#4.5)
|
||||
|
||||
a class member access expression designating a non-static data member
|
||||
of non-reference type
|
||||
in which the object expression is an xvalue ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), or
|
||||
|
||||
- [(4.6)](#4.6)
|
||||
|
||||
a .* pointer-to-member expression in which the first operand is
|
||||
an xvalue and the second operand is a pointer to data member ([[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-to-member operators"))[.](#4.sentence-1)
|
||||
|
||||
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[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#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[.](#4.sentence-3)
|
||||
|
||||
The expression ar is an lvalue[.](#4.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L229)
|
||||
|
||||
The [*result*](#def:result,glvalue "7.2.1 Value category [basic.lval]") of a glvalue is the entity denoted by the expression[.](#5.sentence-1)
|
||||
|
||||
The [*result*](#def:result,prvalue "7.2.1 Value category [basic.lval]") of a prvalue
|
||||
is the value that the expression stores into its context;
|
||||
a prvalue that has type cv void has no result[.](#5.sentence-2)
|
||||
|
||||
A prvalue whose result is the value *V* is sometimes said to have or name the value *V*[.](#5.sentence-3)
|
||||
|
||||
The [*result object*](#def:result_object "7.2.1 Value category [basic.lval]") of a prvalue is the object initialized by the prvalue;
|
||||
a prvalue that has type cv void has no result object[.](#5.sentence-4)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Except when the prvalue is the operand of a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]"),
|
||||
a prvalue of object type always has a result object[.](#5.sentence-5)
|
||||
|
||||
For a discarded prvalue that has type other than cv void,
|
||||
a temporary object is materialized; see [[expr.context]](expr.context "7.2.3 Context dependence")[.](#5.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L246)
|
||||
|
||||
Whenever a glvalue appears as an operand of an operator that
|
||||
requires a prvalue for that operand, the
|
||||
lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")), array-to-pointer ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")),
|
||||
or function-to-pointer ([[conv.func]](conv.func "7.3.4 Function-to-pointer conversion")) standard conversions are
|
||||
applied to convert the expression to a prvalue[.](#6.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
An attempt to bind an rvalue reference to an lvalue is not such a context; see [[dcl.init.ref]](dcl.init.ref "9.5.4 References")[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [6](#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[.](#6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
There are no prvalue bit-fields; if a bit-field is converted to a
|
||||
prvalue ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion")), a prvalue of the type of the bit-field is
|
||||
created, which might then be promoted ([[conv.prom]](conv.prom "7.3.7 Integral promotions"))[.](#6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L267)
|
||||
|
||||
Unless otherwise specified ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")),
|
||||
whenever a prvalue
|
||||
that is not the result of the lvalue-to-rvalue conversion ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion"))
|
||||
appears as an operand of an operator,
|
||||
the [temporary materialization conversion](conv.rval "7.3.5 Temporary materialization conversion [conv.rval]") is
|
||||
applied to convert the expression to an xvalue[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L275)
|
||||
|
||||
[*Note [8](#note-8)*:
|
||||
|
||||
The discussion of reference initialization in [[dcl.init.ref]](dcl.init.ref "9.5.4 References") and of
|
||||
temporaries in [[class.temporary]](class.temporary "6.8.7 Temporary objects") indicates the behavior of lvalues
|
||||
and rvalues in other significant contexts[.](#8.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L282)
|
||||
|
||||
Unless otherwise indicated ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")),
|
||||
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]](class.abstract "11.7.4 Abstract classes"))[.](#9.sentence-1)
|
||||
|
||||
A glvalue shall not have type cv void[.](#9.sentence-2)
|
||||
|
||||
[*Note [9](#note-9)*:
|
||||
|
||||
A glvalue can have complete or incomplete non-void type[.](#9.sentence-3)
|
||||
|
||||
Class and array prvalues can have cv-qualified types; other prvalues
|
||||
always have cv-unqualified types[.](#9.sentence-4)
|
||||
|
||||
See [[expr.type]](expr.type "7.2.2 Type")[.](#9.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L294)
|
||||
|
||||
An lvalue is [*modifiable*](#def:modifiable "7.2.1 Value category [basic.lval]") unless its type is const-qualified
|
||||
or is a function type[.](#10.sentence-1)
|
||||
|
||||
[*Note [10](#note-10)*:
|
||||
|
||||
A program that attempts
|
||||
to modify an object through a nonmodifiable lvalue or through an rvalue
|
||||
is ill-formed ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"), [[expr.post.incr]](expr.post.incr "7.6.1.6 Increment and decrement"), [[expr.pre.incr]](expr.pre.incr "7.6.2.3 Increment and decrement"))[.](#10.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L303)
|
||||
|
||||
An object of dynamic type Tobj is[*type-accessible*](#def:type-accessible "7.2.1 Value category [basic.lval]") through a glvalue of type Tref if Tref is similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to:
|
||||
|
||||
- [(11.1)](#11.1)
|
||||
|
||||
Tobj,
|
||||
|
||||
- [(11.2)](#11.2)
|
||||
|
||||
a type that is the signed or unsigned type corresponding to Tobj, or
|
||||
|
||||
- [(11.3)](#11.3)
|
||||
|
||||
a char, unsigned char, or std::byte type[.](#11.sentence-1)
|
||||
|
||||
If a program attempts to access ([[defns.access]](defns.access "3.1 access"))
|
||||
the stored value of an object through a glvalue
|
||||
through which it is not type-accessible,
|
||||
the behavior is undefined[.](#11.sentence-2)[42](#footnote-42 "The intent of this list is to specify those circumstances in which an object can or cannot be aliased.")
|
||||
|
||||
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[.](#11.sentence-3)
|
||||
|
||||
[*Note [11](#note-11)*:
|
||||
|
||||
In C, an entire object of structure type can be accessed, e.g., using assignment[.](#11.sentence-4)
|
||||
|
||||
By contrast, C++ has no notion of accessing an object of class type
|
||||
through an lvalue of class type[.](#11.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[42)](#footnote-42)[42)](#footnoteref-42)
|
||||
|
||||
The intent of this list is to specify those circumstances in which an
|
||||
object can or cannot be aliased[.](#footnote-42.sentence-1)
|
||||
1955
cppdraft/basic/memobj.md
Normal file
1955
cppdraft/basic/memobj.md
Normal file
File diff suppressed because it is too large
Load Diff
384
cppdraft/basic/namespace.md
Normal file
384
cppdraft/basic/namespace.md
Normal file
@@ -0,0 +1,384 @@
|
||||
[basic.namespace]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.9 Namespaces [basic.namespace]
|
||||
|
||||
### [9.9.1](#general) General [[basic.namespace.general]](basic.namespace.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8189)
|
||||
|
||||
A namespace is an optionally-named entity
|
||||
whose scope can contain declarations of any kind of entity[.](#general-1.sentence-1)
|
||||
|
||||
The name of a
|
||||
namespace can be used to access entities that belong to that namespace;
|
||||
that is, the [*members*](#def:member,namespace "9.9.1 General [basic.namespace.general]") of the namespace[.](#general-1.sentence-2)
|
||||
|
||||
Unlike other entities,
|
||||
the definition of a namespace can be split over several parts of one or
|
||||
more translation units and modules[.](#general-1.sentence-3)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8199)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
A [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") is exported
|
||||
if it contains any[*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")*s* ([[module.interface]](module.interface "10.2 Export declaration"))[.](#general-2.sentence-1)
|
||||
|
||||
A namespace is never attached to a named module
|
||||
and never has a name with module linkage[.](#general-2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#general-example-1)*: export module M;namespace N1 {} // N1 is not exportedexport namespace N2 {} // N2 is exportednamespace N3 { export int n; } // N3 is exported â *end example*]
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8216)
|
||||
|
||||
There is a [*global namespace*](#def:namespace,global "9.9.1 General [basic.namespace.general]") with no declaration;
|
||||
see [[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace scope")[.](#general-3.sentence-1)
|
||||
|
||||
The global namespace belongs to the global scope;
|
||||
it is not an unnamed namespace ([[namespace.unnamed]](#namespace.unnamed "9.9.2.2 Unnamed namespaces"))[.](#general-3.sentence-2)
|
||||
|
||||
[*Note [2](#general-note-2)*:
|
||||
|
||||
Lacking a declaration, it cannot be found by name lookup[.](#general-3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [9.9.2](#namespace.def) Namespace definition [[namespace.def]](namespace.def)
|
||||
|
||||
#### [9.9.2.1](#namespace.def.general) General [[namespace.def.general]](namespace.def.general)
|
||||
|
||||
[namespace-name:](#nt:namespace-name "9.9.2.1 General [namespace.def.general]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*namespace-alias*](#nt:namespace-alias "9.9.3 Namespace alias [namespace.alias]")
|
||||
|
||||
[namespace-definition:](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
[*named-namespace-definition*](#nt:named-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
[*unnamed-namespace-definition*](#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
[*nested-namespace-definition*](#nt:nested-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
|
||||
[named-namespace-definition:](#nt:named-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
inlineopt namespace [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") { [*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") }
|
||||
|
||||
[unnamed-namespace-definition:](#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
inlineopt namespace [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt { [*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") }
|
||||
|
||||
[nested-namespace-definition:](#nt:nested-namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
namespace [*enclosing-namespace-specifier*](#nt:enclosing-namespace-specifier "9.9.2.1 General [namespace.def.general]") :: inlineopt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") { [*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") }
|
||||
|
||||
[enclosing-namespace-specifier:](#nt:enclosing-namespace-specifier "9.9.2.1 General [namespace.def.general]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*enclosing-namespace-specifier*](#nt:enclosing-namespace-specifier "9.9.2.1 General [namespace.def.general]") :: inlineopt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[namespace-body:](#nt:namespace-body "9.9.2.1 General [namespace.def.general]")
|
||||
[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]")opt
|
||||
|
||||
[1](#namespace.def.general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8270)
|
||||
|
||||
Every [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") shall inhabit a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace scope"))[.](#namespace.def.general-1.sentence-1)
|
||||
|
||||
[2](#namespace.def.general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8273)
|
||||
|
||||
In a [*named-namespace-definition*](#nt:named-namespace-definition "9.9.2.1 General [namespace.def.general]") D,
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is the name of the namespace[.](#namespace.def.general-2.sentence-1)
|
||||
|
||||
The [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") 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[.](#namespace.def.general-2.sentence-2)
|
||||
|
||||
If the lookup finds a [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for a namespace N,D [*extends*](#def:namespace,extend "9.9.2.1 General [namespace.def.general]") N,
|
||||
and the target scope of D is the scope to which N belongs[.](#namespace.def.general-2.sentence-3)
|
||||
|
||||
If the lookup finds nothing, the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is introduced
|
||||
as a [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]") into A[.](#namespace.def.general-2.sentence-4)
|
||||
|
||||
[3](#namespace.def.general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8287)
|
||||
|
||||
Because a [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") contains[*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")*s* in its [*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") and a[*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") is itself a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]"), it
|
||||
follows that [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]")*s* can be nested[.](#namespace.def.general-3.sentence-1)
|
||||
|
||||
[*Example [1](#namespace.def.general-example-1)*: namespace Outer {int i; namespace Inner {void f() { i++; } // Outer::iint i; void g() { i++; } // Inner::i}} â *end example*]
|
||||
|
||||
[4](#namespace.def.general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8305)
|
||||
|
||||
If the optional initial inline keyword appears in a[*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for a particular namespace, that namespace is
|
||||
declared to be an [*inline namespace*](#def:namespace,inline "9.9.2.1 General [namespace.def.general]")[.](#namespace.def.general-4.sentence-1)
|
||||
|
||||
The inline keyword may be
|
||||
used on a [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") that extends a namespace
|
||||
only if it was previously used on the [*namespace-definition*](#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") that initially declared the [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]") for that namespace[.](#namespace.def.general-4.sentence-2)
|
||||
|
||||
[5](#namespace.def.general-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8313)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*named-namespace-definition*](#nt:named-namespace-definition "9.9.2.1 General [namespace.def.general]") appertains to the namespace being defined or extended[.](#namespace.def.general-5.sentence-1)
|
||||
|
||||
[6](#namespace.def.general-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8318)
|
||||
|
||||
Members of an inline namespace can be used in most respects as though they were members
|
||||
of the innermost enclosing namespace[.](#namespace.def.general-6.sentence-1)
|
||||
|
||||
Specifically, the inline namespace and its enclosing
|
||||
namespace are both added to the set of associated namespaces used in[argument-dependent lookup](basic.lookup.argdep "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") whenever one of them is,
|
||||
and a [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") ([[namespace.udir]](#namespace.udir "9.9.4 Using namespace directive")) that names the inline
|
||||
namespace is implicitly inserted into the enclosing namespace as for an unnamed
|
||||
namespace ([[namespace.unnamed]](#namespace.unnamed "9.9.2.2 Unnamed namespaces"))[.](#namespace.def.general-6.sentence-2)
|
||||
|
||||
Furthermore, each
|
||||
member of the inline namespace can subsequently be partially
|
||||
specialized ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")), explicitly
|
||||
instantiated ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")), or explicitly specialized ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) as
|
||||
though it were a member of the enclosing namespace[.](#namespace.def.general-6.sentence-3)
|
||||
|
||||
Finally, looking up a name in the
|
||||
enclosing namespace via explicit qualification ([[namespace.qual]](namespace.qual "6.5.5.3 Namespace members")) will include
|
||||
members of the inline namespace even if
|
||||
there are declarations of that name in the enclosing namespace[.](#namespace.def.general-6.sentence-4)
|
||||
|
||||
[7](#namespace.def.general-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8334)
|
||||
|
||||
These properties are transitive: if a namespace N contains an inline namespaceM, which in turn contains an inline namespace O, then the members ofO can be used as though they were members of M or N[.](#namespace.def.general-7.sentence-1)
|
||||
|
||||
The [*inline namespace set*](#def:inline_namespace_set "9.9.2.1 General [namespace.def.general]") of N is the transitive closure of all
|
||||
inline namespaces in N[.](#namespace.def.general-7.sentence-2)
|
||||
|
||||
[8](#namespace.def.general-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8341)
|
||||
|
||||
A [*nested-namespace-definition*](#nt:nested-namespace-definition "9.9.2.1 General [namespace.def.general]") with an[*enclosing-namespace-specifier*](#nt:enclosing-namespace-specifier "9.9.2.1 General [namespace.def.general]") E,[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") I and[*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") B is equivalent tonamespace E { inlineopt namespace I { B } } where the optional inline is present if and only if
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") I is preceded by inline[.](#namespace.def.general-8.sentence-1)
|
||||
|
||||
[*Example [2](#namespace.def.general-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](#namespace.unnamed) Unnamed namespaces [[namespace.unnamed]](namespace.unnamed)
|
||||
|
||||
[1](#namespace.unnamed-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8373)
|
||||
|
||||
An [*unnamed-namespace-definition*](#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]") behaves as if it were
|
||||
replaced by
|
||||
|
||||
inlineopt namespace *unique* { /* empty body */ }
|
||||
using namespace *unique* ;
|
||||
namespace *unique* { [*namespace-body*](#nt:namespace-body "9.9.2.1 General [namespace.def.general]") }
|
||||
|
||||
whereinline appears if and only if it appears in the[*unnamed-namespace-definition*](#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]") 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 program[.](#namespace.unnamed-1.sentence-1)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in the [*unnamed-namespace-definition*](#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]") appertains to *unique*[.](#namespace.unnamed-1.sentence-2)
|
||||
|
||||
[*Example [1](#namespace.unnamed-example-1)*: namespace { int i; } // *unique*::ivoid f() { i++; } // *unique*::i++namespace A {namespace {int i; // A::*unique*::iint 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 [[namespace.alias]](namespace.alias)
|
||||
|
||||
[1](#namespace.alias-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8417)
|
||||
|
||||
A [*namespace-alias-definition*](#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]") declares a [*namespace alias*](#def:alias,namespace "9.9.3 Namespace alias [namespace.alias]") according to the following grammar:
|
||||
|
||||
[namespace-alias:](#nt:namespace-alias "9.9.3 Namespace alias [namespace.alias]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[namespace-alias-definition:](#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]")
|
||||
namespace [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") = [*qualified-namespace-specifier*](#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]") ;
|
||||
namespace [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") = [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") ;
|
||||
|
||||
[qualified-namespace-specifier:](#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]")
|
||||
|
||||
[2](#namespace.alias-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8436)
|
||||
|
||||
The [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") (if any)
|
||||
shall designate a namespace that is not the global namespace[.](#namespace.alias-2.sentence-1)
|
||||
|
||||
[3](#namespace.alias-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8440)
|
||||
|
||||
The [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in a [*namespace-alias-definition*](#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]") becomes a [*namespace-alias*](#nt:namespace-alias "9.9.3 Namespace alias [namespace.alias]")[.](#namespace.alias-3.sentence-1)
|
||||
|
||||
[4](#namespace.alias-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8444)
|
||||
|
||||
The underlying entity ([[basic.pre]](basic.pre "6.1 Preamble")) of the namespace alias is
|
||||
the namespace either
|
||||
denoted by the [*qualified-namespace-specifier*](#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]") or
|
||||
designated by the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")[.](#namespace.alias-4.sentence-1)
|
||||
|
||||
[*Note [1](#namespace.alias-note-1)*:
|
||||
|
||||
When looking up a [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]") in a[*namespace-alias-definition*](#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]"), only namespace names are
|
||||
considered, see [[basic.lookup.udir]](basic.lookup.udir "6.5.7 Using-directives and namespace aliases")[.](#namespace.alias-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [9.9.4](#namespace.udir) Using namespace directive [[namespace.udir]](namespace.udir)
|
||||
|
||||
[using-directive:](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt using namespace [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ;
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt using namespace [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") ;
|
||||
|
||||
[1](#namespace.udir-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8464)
|
||||
|
||||
The [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") (if any) shall designate a namespace
|
||||
that is not the global namespace[.](#namespace.udir-1.sentence-1)
|
||||
|
||||
The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]"), and[*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") shall not be dependent[.](#namespace.udir-1.sentence-2)
|
||||
|
||||
[2](#namespace.udir-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8472)
|
||||
|
||||
A [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") shall not appear in class scope, but may
|
||||
appear in namespace scope or in block scope[.](#namespace.udir-2.sentence-1)
|
||||
|
||||
[*Note [1](#namespace.udir-note-1)*:
|
||||
|
||||
When looking up a [*namespace-name*](#nt:namespace-name "9.9.2.1 General [namespace.def.general]") in a[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]"), only namespace names are considered,
|
||||
see [[basic.lookup.udir]](basic.lookup.udir "6.5.7 Using-directives and namespace aliases")[.](#namespace.udir-2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")[.](#namespace.udir-2.sentence-3)
|
||||
|
||||
[3](#namespace.udir-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8482)
|
||||
|
||||
[*Note [2](#namespace.udir-note-2)*:
|
||||
|
||||
A [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") makes the names in the designated
|
||||
namespace usable in the scope in which the[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") appears after
|
||||
the [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified name lookup"), [[namespace.qual]](namespace.qual "6.5.5.3 Namespace members"))[.](#namespace.udir-3.sentence-1)
|
||||
|
||||
During unqualified name lookup, the names
|
||||
appear as if they were declared in the nearest enclosing namespace which
|
||||
contains both the [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") and the designated
|
||||
namespace[.](#namespace.udir-3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#namespace.udir-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8494)
|
||||
|
||||
[*Note [3](#namespace.udir-note-3)*:
|
||||
|
||||
A [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") does not introduce any names[.](#namespace.udir-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#namespace.udir-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*]
|
||||
|
||||
[5](#namespace.udir-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8528)
|
||||
|
||||
[*Note [4](#namespace.udir-note-4)*:
|
||||
|
||||
A [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") is transitive: if a scope contains a[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that designates a namespace that itself
|
||||
contains [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s*, the namespaces designated by those[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* are also eligible to be considered[.](#namespace.udir-5.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#namespace.udir-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 yetint l = k; // ambiguous: C::k or D::kint m = i; // B::i hides A::iint n = j; // D::j hides B::j}}
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#namespace.udir-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8578)
|
||||
|
||||
[*Note [5](#namespace.udir-note-5)*:
|
||||
|
||||
Declarations in a namespace
|
||||
that appear after a [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") for that namespace
|
||||
can be found through that [*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") after they appear[.](#namespace.udir-6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#namespace.udir-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8585)
|
||||
|
||||
[*Note [6](#namespace.udir-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]](basic.lookup "6.5 Name lookup"))[.](#namespace.udir-7.sentence-1)
|
||||
|
||||
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[.](#namespace.udir-7.sentence-2)
|
||||
|
||||
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*]
|
||||
|
||||
[8](#namespace.udir-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8615)
|
||||
|
||||
[*Note [7](#namespace.udir-note-7)*:
|
||||
|
||||
The order in which namespaces are considered and the
|
||||
relationships among the namespaces implied by the[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* do not affect overload resolution[.](#namespace.udir-8.sentence-1)
|
||||
|
||||
Neither is any function excluded because another has the same
|
||||
signature, even if one is in a namespace reachable through[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* in the namespace of the other[.](#namespace.udir-8.sentence-2)[83](#footnote-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.")
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#namespace.udir-example-3)*: namespace D {int d1; void f(char);}using namespace D;
|
||||
|
||||
int d1; // OK, no conflict with D::d1namespace E {int e; void f(int);}namespace D { // namespace extensionint 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)](#footnote-83)[83)](#footnoteref-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]](class.member.lookup "6.5.2 Member name lookup"))[.](#footnote-83.sentence-1)
|
||||
|
||||
There is no such disambiguation when
|
||||
considering the set of names found as a result of following[*using-directive*](#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s*[.](#footnote-83.sentence-2)
|
||||
54
cppdraft/basic/namespace/general.md
Normal file
54
cppdraft/basic/namespace/general.md
Normal file
@@ -0,0 +1,54 @@
|
||||
[basic.namespace.general]
|
||||
|
||||
# 9 Declarations [[dcl]](./#dcl)
|
||||
|
||||
## 9.9 Namespaces [[basic.namespace]](basic.namespace#general)
|
||||
|
||||
### 9.9.1 General [basic.namespace.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8189)
|
||||
|
||||
A namespace is an optionally-named entity
|
||||
whose scope can contain declarations of any kind of entity[.](#1.sentence-1)
|
||||
|
||||
The name of a
|
||||
namespace can be used to access entities that belong to that namespace;
|
||||
that is, the [*members*](#def:member,namespace "9.9.1 General [basic.namespace.general]") of the namespace[.](#1.sentence-2)
|
||||
|
||||
Unlike other entities,
|
||||
the definition of a namespace can be split over several parts of one or
|
||||
more translation units and modules[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8199)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") is exported
|
||||
if it contains any[*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")*s* ([[module.interface]](module.interface "10.2 Export declaration"))[.](#2.sentence-1)
|
||||
|
||||
A namespace is never attached to a named module
|
||||
and never has a name with module linkage[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: export module M;namespace N1 {} // N1 is not exportedexport namespace N2 {} // N2 is exportednamespace N3 { export int n; } // N3 is exported â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8216)
|
||||
|
||||
There is a [*global namespace*](#def:namespace,global "9.9.1 General [basic.namespace.general]") with no declaration;
|
||||
see [[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace scope")[.](#3.sentence-1)
|
||||
|
||||
The global namespace belongs to the global scope;
|
||||
it is not an unnamed namespace ([[namespace.unnamed]](namespace.unnamed "9.9.2.2 Unnamed namespaces"))[.](#3.sentence-2)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Lacking a declaration, it cannot be found by name lookup[.](#3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
242
cppdraft/basic/pre.md
Normal file
242
cppdraft/basic/pre.md
Normal file
@@ -0,0 +1,242 @@
|
||||
[basic.pre]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.1 Preamble [basic.pre]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L13)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
This Clause presents the basic concepts of the C++ language[.](#1.sentence-1)
|
||||
|
||||
It explains the difference between an object and a
|
||||
name and how they relate to the value categories for expressions[.](#1.sentence-2)
|
||||
|
||||
It introduces the concepts of a
|
||||
declaration and a definition and presents C++'s
|
||||
notion of type, scope, linkage, and
|
||||
storage duration[.](#1.sentence-3)
|
||||
|
||||
The mechanisms for starting and
|
||||
terminating a program are discussed[.](#1.sentence-4)
|
||||
|
||||
Finally, this Clause presents the
|
||||
fundamental types of the language and lists the ways of constructing
|
||||
compound types from these[.](#1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L27)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This Clause does not cover concepts that affect only a single
|
||||
part of the language[.](#2.sentence-1)
|
||||
|
||||
Such concepts are discussed in the relevant
|
||||
Clauses[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L34)
|
||||
|
||||
A [*name*](basic.link#def:name "6.7 Program and linkage [basic.link]") is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ([[lex.name]](lex.name "5.11 Identifiers")),[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")),[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]") ([[over.oper]](over.oper "12.4 Overloaded operators")), or[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]") ([[over.literal]](over.literal "12.6 User-defined literals"))[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L40)
|
||||
|
||||
Two names are [*the same*](#def:name,same "6.1 Preamble [basic.pre]") if
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
they are [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* composed of the same character sequence, or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
they are [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]")*s* formed with
|
||||
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) types, or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
they are [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")*s* formed with
|
||||
the same operator, or
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
they are [*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")*s* formed with
|
||||
the same literal suffix identifier[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L52)
|
||||
|
||||
Every name is introduced by a [*declaration*](#def:declaration "6.1 Preamble [basic.pre]"), which is a
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
[*name-declaration*](dcl.pre#nt:name-declaration "9.1 Preamble [dcl.pre]"),[*block-declaration*](dcl.pre#nt:block-declaration "9.1 Preamble [dcl.pre]"), or[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") ([[dcl.pre]](dcl.pre "9.1 Preamble"), [[class.mem]](class.mem "11.4 Class members")),
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3 Declarators")),
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")),
|
||||
|
||||
- [(5.4)](#5.4)
|
||||
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") in a postcondition assertion ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
|
||||
|
||||
- [(5.5)](#5.5)
|
||||
|
||||
[*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")),
|
||||
|
||||
- [(5.6)](#5.6)
|
||||
|
||||
[*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") with a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ([[stmt.pre]](stmt.pre "8.1 Preamble")),
|
||||
|
||||
- [(5.7)](#5.7)
|
||||
|
||||
[*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class members")),
|
||||
|
||||
- [(5.8)](#5.8)
|
||||
|
||||
[*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")),
|
||||
|
||||
- [(5.9)](#5.9)
|
||||
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"), [[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(5.10)](#5.10)
|
||||
|
||||
[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(5.11)](#5.11)
|
||||
|
||||
[*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(5.12)](#5.12)
|
||||
|
||||
[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(5.13)](#5.13)
|
||||
|
||||
[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(5.14)](#5.14)
|
||||
|
||||
[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") that introduces a name ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")),
|
||||
|
||||
- [(5.15)](#5.15)
|
||||
|
||||
[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") ([[class.pre]](class.pre "11.1 Preamble")),
|
||||
|
||||
- [(5.16)](#5.16)
|
||||
|
||||
[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") or[*enumerator-definition*](dcl.enum#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),
|
||||
|
||||
- [(5.17)](#5.17)
|
||||
|
||||
[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble")), or
|
||||
|
||||
- [(5.18)](#5.18)
|
||||
|
||||
implicit declaration of an injected-class-name ([[class.pre]](class.pre "11.1 Preamble"))[.](#5.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The term declaration is not a synonym for the grammar non-terminal [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble"))[.](#5.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The interpretation of a [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") produces
|
||||
one or more of the above ([[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement"))[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L107)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
Some names denote types or templates[.](#6.sentence-1)
|
||||
|
||||
In general, whenever a name is encountered
|
||||
it is necessary to look it up ([[basic.lookup]](basic.lookup "6.5 Name lookup"))
|
||||
to determine whether that name denotes one of these entities
|
||||
before continuing to parse the program that contains it[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L116)
|
||||
|
||||
A [*variable*](#def:variable "6.1 Preamble [basic.pre]") is introduced by the
|
||||
declaration of
|
||||
a reference other than a non-static data member or of
|
||||
an object[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L122)
|
||||
|
||||
An [*entity*](#def:entity "6.1 Preamble [basic.pre]") is a
|
||||
variable,
|
||||
structured binding,
|
||||
result binding,
|
||||
function,
|
||||
enumerator,
|
||||
type,
|
||||
type alias,
|
||||
non-static data member,
|
||||
bit-field,
|
||||
template,
|
||||
namespace,
|
||||
namespace alias,
|
||||
template parameter,
|
||||
function parameter, or[*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")[.](#8.sentence-1)
|
||||
|
||||
The [*underlying entity*](#def:entity,underlying "6.1 Preamble [basic.pre]") of an entity is that entity
|
||||
unless otherwise specified[.](#8.sentence-2)
|
||||
|
||||
A name [*denotes*](#def:denote "6.1 Preamble [basic.pre]") the underlying entity of
|
||||
the entity declared by each declaration that introduces the name[.](#8.sentence-3)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
Type aliases and namespace aliases have underlying entities
|
||||
that are distinct from themselves[.](#8.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L148)
|
||||
|
||||
A [*local entity*](#def:entity,local "6.1 Preamble [basic.pre]") is a variable with
|
||||
automatic storage duration ([[basic.stc.auto]](basic.stc.auto "6.8.6.4 Automatic storage duration")),
|
||||
a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))
|
||||
whose corresponding variable is such an entity,
|
||||
a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
|
||||
or the *this object ([[expr.prim.this]](expr.prim.this "7.5.3 This"))[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L156)
|
||||
|
||||
A name used in more than one translation unit can potentially
|
||||
refer to the same entity in these translation units depending on the[linkage](basic.link "6.7 Program and linkage [basic.link]") of the name specified in each
|
||||
translation unit[.](#10.sentence-1)
|
||||
711
cppdraft/basic/scope.md
Normal file
711
cppdraft/basic/scope.md
Normal file
@@ -0,0 +1,711 @@
|
||||
[basic.scope]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [basic.scope]
|
||||
|
||||
### [6.4.1](#scope) General [[basic.scope.scope]](basic.scope.scope)
|
||||
|
||||
[1](#scope-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L939)
|
||||
|
||||
The declarations in a program appear in a number of [*scopes*](#def:scope "6.4.1 General [basic.scope.scope]") that are in general discontiguous[.](#scope-1.sentence-1)
|
||||
|
||||
The [*global scope*](#def:scope,global "6.4.1 General [basic.scope.scope]") contains the entire program;
|
||||
every other scope S is introduced by a
|
||||
declaration,[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),[*statement*](stmt.pre#nt:statement "8.1 Preamble [stmt.pre]"),[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]"), or
|
||||
contract assertion
|
||||
(as described in the following subclauses of [basic.scope])
|
||||
appearing in another scope, which thereby contains S[.](#scope-1.sentence-2)
|
||||
|
||||
An [*enclosing scope*](#def:scope,enclosing "6.4.1 General [basic.scope.scope]") at a program point is any scope that contains it;
|
||||
the smallest such scope is said to be the [*immediate scope*](#def:scope,immediate "6.4.1 General [basic.scope.scope]") at that point[.](#scope-1.sentence-3)
|
||||
|
||||
A scope [*intervenes*](#def:scope,intervene "6.4.1 General [basic.scope.scope]") 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[.](#scope-1.sentence-4)
|
||||
|
||||
[2](#scope-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L958)
|
||||
|
||||
Unless otherwise specified:
|
||||
|
||||
- [(2.1)](#scope-2.1)
|
||||
|
||||
The smallest scope that contains a scope S is
|
||||
the [*parent scope*](#def:scope,parent "6.4.1 General [basic.scope.scope]") of S[.](#scope-2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#scope-2.2)
|
||||
|
||||
No two declarations (re)introduce the same entity[.](#scope-2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#scope-2.3)
|
||||
|
||||
A declaration [*inhabits*](#def:scope,inhabit "6.4.1 General [basic.scope.scope]") the immediate scope at its locus ([[basic.scope.pdecl]](#pdecl "6.4.2 Point of declaration"))[.](#scope-2.3.sentence-1)
|
||||
|
||||
- [(2.4)](#scope-2.4)
|
||||
|
||||
A declaration's [*target scope*](#def:scope,target "6.4.1 General [basic.scope.scope]") is the scope it inhabits[.](#scope-2.4.sentence-1)
|
||||
|
||||
- [(2.5)](#scope-2.5)
|
||||
|
||||
Any names (re)introduced by a declaration are [*bound*](#def:name,bound "6.4.1 General [basic.scope.scope]") to it
|
||||
in its target scope[.](#scope-2.5.sentence-1)
|
||||
|
||||
The [*host scope*](#def:scope,host "6.4.1 General [basic.scope.scope]") of a declaration is
|
||||
the inhabited scope if that scope is a block scope and
|
||||
the target scope otherwise[.](#scope-2.sentence-2)
|
||||
|
||||
An entity [*belongs*](#def:entity,belong "6.4.1 General [basic.scope.scope]") to a scope S if S is the target scope of a declaration of the entity[.](#scope-2.sentence-3)
|
||||
|
||||
[*Note [1](#scope-note-1)*:
|
||||
|
||||
Special cases include that:
|
||||
|
||||
- [(2.6)](#scope-2.6)
|
||||
|
||||
Template parameter scopes are parents
|
||||
only to other template parameter scopes ([[basic.scope.temp]](#temp "6.4.9 Template parameter scope"))[.](#scope-2.6.sentence-1)
|
||||
|
||||
- [(2.7)](#scope-2.7)
|
||||
|
||||
Corresponding declarations with appropriate linkage
|
||||
declare the same entity ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#scope-2.7.sentence-1)
|
||||
|
||||
- [(2.8)](#scope-2.8)
|
||||
|
||||
The declaration in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") inhabits the same scope as the [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")[.](#scope-2.8.sentence-1)
|
||||
|
||||
- [(2.9)](#scope-2.9)
|
||||
|
||||
Friend declarations and
|
||||
declarations of template specializations do not bind names ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"));
|
||||
those with qualified names target a specified scope, and
|
||||
other friend declarations and
|
||||
certain [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")*s* ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))
|
||||
target a larger enclosing scope[.](#scope-2.9.sentence-1)
|
||||
|
||||
- [(2.10)](#scope-2.10)
|
||||
|
||||
Block-scope extern or function declarations target a larger enclosing scope
|
||||
but bind a name in their immediate scope ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1 General"))[.](#scope-2.10.sentence-1)
|
||||
|
||||
- [(2.11)](#scope-2.11)
|
||||
|
||||
The names of unscoped enumerators are bound
|
||||
in the two innermost enclosing scopes ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))[.](#scope-2.11.sentence-1)
|
||||
|
||||
- [(2.12)](#scope-2.12)
|
||||
|
||||
A class's name is also bound in its own scope ([[class.pre]](class.pre "11.1 Preamble"))[.](#scope-2.12.sentence-1)
|
||||
|
||||
- [(2.13)](#scope-2.13)
|
||||
|
||||
The names of the members of an anonymous union are bound in
|
||||
the union's parent scope ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#scope-2.13.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#scope-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1013)
|
||||
|
||||
Two non-static member functions have[*corresponding object parameters*](#def:object_parameter,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(3.1)](#scope-3.1)
|
||||
|
||||
exactly one is an implicit object member function
|
||||
with no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") and
|
||||
the types of their object parameters ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
after removing references,
|
||||
are the same, or
|
||||
|
||||
- [(3.2)](#scope-3.2)
|
||||
|
||||
their object parameters have the same type[.](#scope-3.sentence-1)
|
||||
|
||||
Two non-static member function templates have[*corresponding object parameters*](#def:object_parameter,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(3.3)](#scope-3.3)
|
||||
|
||||
exactly one is an implicit object member function
|
||||
with no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") and
|
||||
the types of their object parameters,
|
||||
after removing any references,
|
||||
are equivalent, or
|
||||
|
||||
- [(3.4)](#scope-3.4)
|
||||
|
||||
the types of their object parameters are equivalent[.](#scope-3.sentence-2)
|
||||
|
||||
Two function templates have[*corresponding signatures*](#def:signature,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||||
their corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* 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[.](#scope-3.sentence-3)
|
||||
|
||||
[4](#scope-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1048)
|
||||
|
||||
Two declarations [*correspond*](#def:correspond "6.4.1 General [basic.scope.scope]") if they (re)introduce the same name,
|
||||
both declare constructors, or
|
||||
both declare destructors,
|
||||
unless
|
||||
|
||||
- [(4.1)](#scope-4.1)
|
||||
|
||||
either is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"), or
|
||||
|
||||
- [(4.2)](#scope-4.2)
|
||||
|
||||
one declares a type (not a type alias) and the other declares a
|
||||
variable,
|
||||
non-static data member other than of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")),
|
||||
enumerator,
|
||||
function, or
|
||||
function template, or
|
||||
|
||||
- [(4.3)](#scope-4.3)
|
||||
|
||||
each declares a function or function template
|
||||
and they do not declare corresponding overloads[.](#scope-4.sentence-1)
|
||||
|
||||
Two function or function template declarations declare[*corresponding overloads*](#def:corresponding_overloads "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(4.4)](#scope-4.4)
|
||||
|
||||
both declare functions with the same non-object-parameter-type-list,[17](#footnote-17 "An implicit object parameter ([over.match.funcs]) is not part of the parameter-type-list.") equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* (if any, except as specified in [[temp.friend]](temp.friend "13.7.5 Friends")), and,
|
||||
if both are non-static members,
|
||||
they have corresponding object parameters, or
|
||||
|
||||
- [(4.5)](#scope-4.5)
|
||||
|
||||
both declare function templates with corresponding signatures and equivalent[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* and
|
||||
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* (if any)[.](#scope-4.sentence-2)
|
||||
|
||||
[*Note [2](#scope-note-2)*:
|
||||
|
||||
Declarations can correspond even if neither binds a name[.](#scope-4.sentence-3)
|
||||
|
||||
[*Example [1](#scope-example-1)*: struct A {friend void f(); // #1};struct B {friend void f() {} // corresponds to, and defines, #1}; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#scope-example-2)*: typedef int Int;enum E : int { a };void f(int); // #1void f(Int) {} // defines #1void f(E) {} // OK, another overloadstruct X {static void f(); void f() const; // error: redeclarationvoid g(); void g() const; // OKvoid g() &; // error: redeclarationvoid h(this X&, int); void h(int) &&; // OK, another overloadvoid j(this const X&); void j() const &; // error: redeclarationvoid k(); void k(this X&); // error: redeclaration}; â *end example*]
|
||||
|
||||
[5](#scope-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1124)
|
||||
|
||||
A declaration is [*name-independent*](#def:declaration,name-independent "6.4.1 General [basic.scope.scope]") if its name is _ (U+005f low line) and it declares
|
||||
|
||||
- [(5.1)](#scope-5.1)
|
||||
|
||||
a variable with automatic storage duration,
|
||||
|
||||
- [(5.2)](#scope-5.2)
|
||||
|
||||
a structured binding
|
||||
with no [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") and
|
||||
not inhabiting a namespace scope,
|
||||
|
||||
- [(5.3)](#scope-5.3)
|
||||
|
||||
a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
|
||||
|
||||
- [(5.4)](#scope-5.4)
|
||||
|
||||
the variable introduced by an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]"), or
|
||||
|
||||
- [(5.5)](#scope-5.5)
|
||||
|
||||
a non-static data member of other than an anonymous union[.](#scope-5.sentence-1)
|
||||
|
||||
*Recommended practice*: Implementations should not emit a warning
|
||||
that a name-independent declaration is used or unused[.](#scope-5.sentence-2)
|
||||
|
||||
[6](#scope-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1150)
|
||||
|
||||
Two declarations [*potentially conflict*](#def:potentially_conflict "6.4.1 General [basic.scope.scope]") if they correspond and
|
||||
cause their shared name to denote different entities ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#scope-6.sentence-1)
|
||||
|
||||
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]](basic.lookup "6.5 Name lookup")),
|
||||
unless B is name-independent[.](#scope-6.sentence-2)
|
||||
|
||||
[*Note [3](#scope-note-3)*:
|
||||
|
||||
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") 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]](basic.lookup.general "6.5.1 General"))[.](#scope-6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [4](#scope-note-4)*:
|
||||
|
||||
Overload resolution can consider potentially conflicting declarations
|
||||
found in multiple scopes
|
||||
(e.g., via [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* or for operator functions),
|
||||
in which case it is often ambiguous[.](#scope-6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#scope-example-3)*: void f() {int x,y; void x(); // error: different entity for xint y; // error: redefinition}enum { f }; // error: different entity for ::fnamespace A {}namespace B = A;namespace B = A; // OK, no effectnamespace B = B; // OK, no effectnamespace A = B; // OK, no effectnamespace B {} // error: different entity for Bvoid g() {int _;
|
||||
_ = 0; // OKint _; // OK, name-independent declaration _ = 0; // error: two non-function declarations in the lookup set}void h () {int _; // #1 _ ++; // OKstatic int _; // error: conflicts with #1 because static variables are not name-independent} â *end example*]
|
||||
|
||||
[7](#scope-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1199)
|
||||
|
||||
A declaration is [*nominable*](#def:nominable "6.4.1 General [basic.scope.scope]") 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]](namespace.def "9.9.2 Namespace definition"))[.](#scope-7.sentence-1)
|
||||
|
||||
[*Example [4](#scope-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[.](#scope-7.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[8](#scope-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1225)
|
||||
|
||||
When instantiating a templated entity ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||||
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[.](#scope-8.sentence-1)
|
||||
|
||||
[17)](#footnote-17)[17)](#footnoteref-17)
|
||||
|
||||
An implicit object parameter ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists"))
|
||||
is not part of the parameter-type-list[.](#footnote-17.sentence-1)
|
||||
|
||||
### [6.4.2](#pdecl) Point of declaration [[basic.scope.pdecl]](basic.scope.pdecl)
|
||||
|
||||
[1](#pdecl-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1237)
|
||||
|
||||
The [*locus*](#def:locus "6.4.2 Point of declaration [basic.scope.pdecl]") of a declaration ([[basic.pre]](basic.pre "6.1 Preamble")) that is a declarator
|
||||
is immediately after the complete declarator ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#pdecl-1.sentence-1)
|
||||
|
||||
[*Example [1](#pdecl-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]](basic.life "6.8.4 Lifetime"))[.](#pdecl-1.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#pdecl-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1251)
|
||||
|
||||
[*Note [1](#pdecl-note-1)*:
|
||||
|
||||
A name from an outer scope remains visible up to
|
||||
the locus of the declaration that hides it[.](#pdecl-2.sentence-1)
|
||||
|
||||
[*Example [2](#pdecl-example-2)*:
|
||||
|
||||
const int i = 2;{ int i[i]; } declares a block-scope array of two integers[.](#pdecl-2.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#pdecl-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1265)
|
||||
|
||||
The locus of a [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") is immediately after
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)
|
||||
in its [*class-head*](class.pre#nt:class-head "11.1 Preamble [class.pre]") ([[class.pre]](class.pre "11.1 Preamble"))[.](#pdecl-3.sentence-1)
|
||||
|
||||
The locus of an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") is immediately after
|
||||
its [*enum-head*](dcl.enum#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]");
|
||||
the locus of an [*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]") is immediately after it ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))[.](#pdecl-3.sentence-2)
|
||||
|
||||
The locus of an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") is immediately after it[.](#pdecl-3.sentence-3)
|
||||
|
||||
[4](#pdecl-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1277)
|
||||
|
||||
The locus of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that does not name a constructor
|
||||
is immediately after the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#pdecl-4.sentence-1)
|
||||
|
||||
[5](#pdecl-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1282)
|
||||
|
||||
The locus of an [*enumerator-definition*](dcl.enum#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") is immediately after it[.](#pdecl-5.sentence-1)
|
||||
|
||||
[*Example [3](#pdecl-example-3)*: const int x = 12;{ enum { x = x }; }
|
||||
|
||||
Here, the enumerator x is initialized with the value of the
|
||||
constant x, namely 12[.](#pdecl-5.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#pdecl-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1293)
|
||||
|
||||
[*Note [2](#pdecl-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[.](#pdecl-6.sentence-1)
|
||||
|
||||
[*Example [4](#pdecl-example-4)*: struct X {enum E { z = 16 }; int b[X::z]; // OK}; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#pdecl-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1309)
|
||||
|
||||
The locus of an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") that is a declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) is immediately after it[.](#pdecl-7.sentence-1)
|
||||
|
||||
[8](#pdecl-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1313)
|
||||
|
||||
The locus of an injected-class-name declaration ([[class.pre]](class.pre "11.1 Preamble"))
|
||||
is immediately following the opening brace of the class definition[.](#pdecl-8.sentence-1)
|
||||
|
||||
[9](#pdecl-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1317)
|
||||
|
||||
The locus of the implicit declaration of
|
||||
a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General"))
|
||||
is immediately before
|
||||
the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") of its function's definition[.](#pdecl-9.sentence-1)
|
||||
|
||||
[10](#pdecl-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1323)
|
||||
|
||||
The locus of the declaration of a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))
|
||||
is immediately after
|
||||
the [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") of the structured binding declaration[.](#pdecl-10.sentence-1)
|
||||
|
||||
[11](#pdecl-11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1328)
|
||||
|
||||
The locus of a [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of a range-based for statement ([[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement"))
|
||||
is immediately after the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]")[.](#pdecl-11.sentence-1)
|
||||
|
||||
The locus of a [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion statements"))
|
||||
is immediately after the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]")[.](#pdecl-11.sentence-2)
|
||||
|
||||
[12](#pdecl-12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1336)
|
||||
|
||||
The locus of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is immediately after it[.](#pdecl-12.sentence-1)
|
||||
|
||||
[*Example [5](#pdecl-example-5)*: typedef unsigned char T;template<class T = T // lookup finds the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") , T // lookup finds the template parameter N = 0> struct A { }; â *end example*]
|
||||
|
||||
[13](#pdecl-13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1348)
|
||||
|
||||
The locus of a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
|
||||
is immediately after it[.](#pdecl-13.sentence-1)
|
||||
|
||||
[14](#pdecl-14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1352)
|
||||
|
||||
The locus of a [*concept-definition*](temp.concept#nt:concept-definition "13.7.9 Concept definitions [temp.concept]") is immediately after its [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") ([[temp.concept]](temp.concept "13.7.9 Concept definitions"))[.](#pdecl-14.sentence-1)
|
||||
|
||||
[*Note [3](#pdecl-note-3)*:
|
||||
|
||||
The [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") cannot use
|
||||
the [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]")[.](#pdecl-14.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#pdecl-15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1360)
|
||||
|
||||
The locus of a [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") with an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is immediately after the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#pdecl-15.sentence-1)
|
||||
|
||||
[*Note [4](#pdecl-note-4)*:
|
||||
|
||||
An identifier is invented
|
||||
for an [*unnamed-namespace-definition*](namespace.def.general#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]") ([[namespace.unnamed]](namespace.unnamed "9.9.2.2 Unnamed namespaces"))[.](#pdecl-15.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[16](#pdecl-16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1369)
|
||||
|
||||
[*Note [5](#pdecl-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]](class.friend "11.8.4 Friends"))[.](#pdecl-16.sentence-1)
|
||||
|
||||
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[.](#pdecl-16.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[17](#pdecl-17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1381)
|
||||
|
||||
[*Note [6](#pdecl-note-6)*:
|
||||
|
||||
For point of instantiation of a template, see [[temp.point]](temp.point "13.8.4.1 Point of instantiation")[.](#pdecl-17.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [6.4.3](#block) Block scope [[basic.scope.block]](basic.scope.block)
|
||||
|
||||
[1](#block-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1391)
|
||||
|
||||
Each
|
||||
|
||||
- [(1.1)](#block-1.1)
|
||||
|
||||
selection, iteration, or expansion statement ([[stmt.select]](stmt.select "8.5 Selection statements"), [[stmt.iter]](stmt.iter "8.6 Iteration statements"), [[stmt.expand]](stmt.expand "8.7 Expansion statements")),
|
||||
|
||||
- [(1.2)](#block-1.2)
|
||||
|
||||
substatement of such a statement,
|
||||
|
||||
- [(1.3)](#block-1.3)
|
||||
|
||||
[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble")), or
|
||||
|
||||
- [(1.4)](#block-1.4)
|
||||
|
||||
compound statement ([[stmt.block]](stmt.block "8.4 Compound statement or block"))
|
||||
that is not the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]")
|
||||
|
||||
introduces a [*block scope*](#def:scope,block "6.4.3 Block scope [basic.scope.block]") that includes that statement or [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]")[.](#block-1.sentence-1)
|
||||
|
||||
[*Note [1](#block-note-1)*:
|
||||
|
||||
A substatement that is also a block has only one scope[.](#block-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A variable that belongs to a block scope is a [*block variable*](#def:block_variable "6.4.3 Block scope [basic.scope.block]")[.](#block-1.sentence-3)
|
||||
|
||||
[*Example [1](#block-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*]
|
||||
|
||||
[2](#block-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1423)
|
||||
|
||||
If a declaration
|
||||
that is not a name-independent declaration and
|
||||
that binds a name in the block scope S of a
|
||||
|
||||
- [(2.1)](#block-2.1)
|
||||
|
||||
[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]"), or [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]"),
|
||||
|
||||
- [(2.2)](#block-2.2)
|
||||
|
||||
substatement of a selection or iteration statement
|
||||
that is not itself a selection or iteration statement, or
|
||||
|
||||
- [(2.3)](#block-2.3)
|
||||
|
||||
[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") of a [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")
|
||||
|
||||
potentially conflicts with a declaration
|
||||
whose target scope is the parent scope of S,
|
||||
the program is ill-formed[.](#block-2.sentence-1)
|
||||
|
||||
[*Example [2](#block-example-2)*: if (int x = f()) {int x; // error: redeclaration of x}else {int x; // error: redeclaration of x} â *end example*]
|
||||
|
||||
### [6.4.4](#param) Function parameter scope [[basic.scope.param]](basic.scope.param)
|
||||
|
||||
[1](#param-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1456)
|
||||
|
||||
A [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") P introduces
|
||||
a [*function parameter scope*](#def:scope,function_parameter "6.4.4 Function parameter scope [basic.scope.param]") that includes P[.](#param-1.sentence-1)
|
||||
|
||||
[*Note [1](#param-note-1)*:
|
||||
|
||||
A function parameter cannot be used for its value
|
||||
within the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#param-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
- [(1.1)](#param-1.1)
|
||||
|
||||
If P is associated with a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") and
|
||||
is preceded by a (possibly-parenthesized) [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") of
|
||||
the form[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt,
|
||||
its scope extends to the end of the nearest enclosing[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]"),[*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]"),[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") or
|
||||
a [*nodeclspec-function-declaration*](dcl.pre#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]"), or[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]"),
|
||||
but does not include the locus of the associated [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")[.](#param-1.1.sentence-1)
|
||||
[*Note [2](#param-note-2)*:
|
||||
In this case, P declares the parameters of a function
|
||||
(or a function or template parameter declared with function type)[.](#param-1.1.sentence-2)
|
||||
A member function's parameter scope is nested within its class's scope[.](#param-1.1.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(1.2)](#param-1.2)
|
||||
|
||||
If P is associated with a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
its scope extends to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") in the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")[.](#param-1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#param-1.3)
|
||||
|
||||
If P is associated with a [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]"),
|
||||
its scope extends to the end of the [*requirement-body*](expr.prim.req.general#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]") of the [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")[.](#param-1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#param-1.4)
|
||||
|
||||
If P is associated with a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]"),
|
||||
its scope extends to the end of the [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")[.](#param-1.4.sentence-1)
|
||||
|
||||
### [6.4.5](#lambda) Lambda scope [[basic.scope.lambda]](basic.scope.lambda)
|
||||
|
||||
A [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") E introduces a [*lambda scope*](#def:scope,lambda "6.4.5 Lambda scope [basic.scope.lambda]") that starts immediately after the [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") of E and extends to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of E[.](#lambda-sentence-1)
|
||||
|
||||
### [6.4.6](#namespace) Namespace scope [[basic.scope.namespace]](basic.scope.namespace)
|
||||
|
||||
[1](#namespace-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1501)
|
||||
|
||||
Any [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for a namespace N introduces
|
||||
a [*namespace scope*](#def:scope,namespace "6.4.6 Namespace scope [basic.scope.namespace]") that includes the [*namespace-body*](namespace.def.general#nt:namespace-body "9.9.2.1 General [namespace.def.general]") for every [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for N[.](#namespace-1.sentence-1)
|
||||
|
||||
For each non-friend redeclaration or specialization
|
||||
whose target scope is or is contained by the scope,
|
||||
the portion after the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"),[*class-head-name*](class.pre#nt:class-head-name "11.1 Preamble [class.pre]"), or[*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") is also included in the scope[.](#namespace-1.sentence-2)
|
||||
|
||||
The global scope is
|
||||
the namespace scope of the global namespace ([[basic.namespace]](basic.namespace "9.9 Namespaces"))[.](#namespace-1.sentence-3)
|
||||
|
||||
[*Example [1](#namespace-example-1)*: namespace Q {namespace V { void f(); }void V::f() { // in the scope of Vvoid h(); // declares Q::V::h}} â *end example*]
|
||||
|
||||
### [6.4.7](#class) Class scope [[basic.scope.class]](basic.scope.class)
|
||||
|
||||
[1](#class-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1528)
|
||||
|
||||
Any declaration of a class or class template C introduces
|
||||
a [*class scope*](#def:scope,class "6.4.7 Class scope [basic.scope.class]") that includes the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of
|
||||
the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") for C (if any)[.](#class-1.sentence-1)
|
||||
|
||||
For each non-friend redeclaration or specialization
|
||||
whose target scope is or is contained by the scope,
|
||||
the portion after the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"),[*class-head-name*](class.pre#nt:class-head-name "11.1 Preamble [class.pre]"), or[*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") is also included in the scope[.](#class-1.sentence-2)
|
||||
|
||||
[*Note [1](#class-note-1)*:
|
||||
|
||||
Lookup from a program point
|
||||
before the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") of a class
|
||||
will find no bindings in the class scope[.](#class-1.sentence-3)
|
||||
|
||||
[*Example [1](#class-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](#enum) Enumeration scope [[basic.scope.enum]](basic.scope.enum)
|
||||
|
||||
[1](#enum-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1558)
|
||||
|
||||
Any declaration of an enumeration E introduces
|
||||
an [*enumeration scope*](#def:scope,enumeration "6.4.8 Enumeration scope [basic.scope.enum]") that includes the [*enumerator-list*](dcl.enum#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]") of
|
||||
the [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") for E (if any)[.](#enum-1.sentence-1)
|
||||
|
||||
### [6.4.9](#temp) Template parameter scope [[basic.scope.temp]](basic.scope.temp)
|
||||
|
||||
[1](#temp-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1566)
|
||||
|
||||
Each[*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2 Template parameters [temp.param]"),[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"), and[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template parameters [temp.param]") introduces
|
||||
a [*template parameter scope*](#def:scope,template_parameter "6.4.9 Template parameter scope [basic.scope.temp]") that includes the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of
|
||||
the [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")[.](#temp-1.sentence-1)
|
||||
|
||||
[2](#temp-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1576)
|
||||
|
||||
Each [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") D introduces
|
||||
a template parameter scope
|
||||
that extends from the beginning of its [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") to the end of the [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")[.](#temp-2.sentence-1)
|
||||
|
||||
Any declaration outside the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") that would inhabit that scope instead inhabits the same scope as D[.](#temp-2.sentence-2)
|
||||
|
||||
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[.](#temp-2.sentence-3)
|
||||
|
||||
[*Note [1](#temp-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[.](#temp-2.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [6.4.10](#contract) Contract-assertion scope [[basic.scope.contract]](basic.scope.contract)
|
||||
|
||||
[1](#contract-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1593)
|
||||
|
||||
Each contract assertion ([[basic.contract]](basic.contract "6.11 Contract assertions"))C introduces a [*contract-assertion scope*](#def:scope,contract-assertion "6.4.10 Contract-assertion scope [basic.scope.contract]") that includes C[.](#contract-1.sentence-1)
|
||||
|
||||
[2](#contract-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1598)
|
||||
|
||||
If a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
|
||||
that is not name-independent ([[basic.scope.scope]](#scope "6.4.1 General"))
|
||||
and whose enclosing postcondition assertion
|
||||
is associated with a function F potentially conflicts with
|
||||
a declaration whose target scope is
|
||||
|
||||
- [(2.1)](#contract-2.1)
|
||||
|
||||
the function parameter scope of F or
|
||||
|
||||
- [(2.2)](#contract-2.2)
|
||||
|
||||
if associated with a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
the nearest enclosing lambda scope
|
||||
of the precondition assertion ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions")),
|
||||
|
||||
the program is ill-formed[.](#contract-2.sentence-1)
|
||||
73
cppdraft/basic/scope/block.md
Normal file
73
cppdraft/basic/scope/block.md
Normal file
@@ -0,0 +1,73 @@
|
||||
[basic.scope.block]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#block)
|
||||
|
||||
### 6.4.3 Block scope [basic.scope.block]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1391)
|
||||
|
||||
Each
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
selection, iteration, or expansion statement ([[stmt.select]](stmt.select "8.5 Selection statements"), [[stmt.iter]](stmt.iter "8.6 Iteration statements"), [[stmt.expand]](stmt.expand "8.7 Expansion statements")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
substatement of such a statement,
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.pre]](except.pre "14.1 Preamble")), or
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
compound statement ([[stmt.block]](stmt.block "8.4 Compound statement or block"))
|
||||
that is not the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]")
|
||||
|
||||
introduces a [*block scope*](#def:scope,block "6.4.3 Block scope [basic.scope.block]") that includes that statement or [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]")[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A substatement that is also a block has only one scope[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A variable that belongs to a block scope is a [*block variable*](#def:block_variable "6.4.3 Block scope [basic.scope.block]")[.](#1.sentence-3)
|
||||
|
||||
[*Example [1](#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*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1423)
|
||||
|
||||
If a declaration
|
||||
that is not a name-independent declaration and
|
||||
that binds a name in the block scope S of a
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]"), or [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]"),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
substatement of a selection or iteration statement
|
||||
that is not itself a selection or iteration statement, or
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") of a [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")
|
||||
|
||||
potentially conflicts with a declaration
|
||||
whose target scope is the parent scope of S,
|
||||
the program is ill-formed[.](#2.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*: if (int x = f()) {int x; // error: redeclaration of x}else {int x; // error: redeclaration of x} â *end example*]
|
||||
31
cppdraft/basic/scope/class.md
Normal file
31
cppdraft/basic/scope/class.md
Normal file
@@ -0,0 +1,31 @@
|
||||
[basic.scope.class]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#class)
|
||||
|
||||
### 6.4.7 Class scope [basic.scope.class]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1528)
|
||||
|
||||
Any declaration of a class or class template C introduces
|
||||
a [*class scope*](#def:scope,class "6.4.7 Class scope [basic.scope.class]") that includes the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of
|
||||
the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") for C (if any)[.](#1.sentence-1)
|
||||
|
||||
For each non-friend redeclaration or specialization
|
||||
whose target scope is or is contained by the scope,
|
||||
the portion after the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"),[*class-head-name*](class.pre#nt:class-head-name "11.1 Preamble [class.pre]"), or[*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") is also included in the scope[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Lookup from a program point
|
||||
before the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") of a class
|
||||
will find no bindings in the class scope[.](#1.sentence-3)
|
||||
|
||||
[*Example [1](#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*]
|
||||
35
cppdraft/basic/scope/contract.md
Normal file
35
cppdraft/basic/scope/contract.md
Normal file
@@ -0,0 +1,35 @@
|
||||
[basic.scope.contract]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#contract)
|
||||
|
||||
### 6.4.10 Contract-assertion scope [basic.scope.contract]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1593)
|
||||
|
||||
Each contract assertion ([[basic.contract]](basic.contract "6.11 Contract assertions"))C introduces a [*contract-assertion scope*](#def:scope,contract-assertion "6.4.10 Contract-assertion scope [basic.scope.contract]") that includes C[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1598)
|
||||
|
||||
If a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
|
||||
that is not name-independent ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))
|
||||
and whose enclosing postcondition assertion
|
||||
is associated with a function F potentially conflicts with
|
||||
a declaration whose target scope is
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
the function parameter scope of F or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
if associated with a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
the nearest enclosing lambda scope
|
||||
of the precondition assertion ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions")),
|
||||
|
||||
the program is ill-formed[.](#2.sentence-1)
|
||||
15
cppdraft/basic/scope/enum.md
Normal file
15
cppdraft/basic/scope/enum.md
Normal file
@@ -0,0 +1,15 @@
|
||||
[basic.scope.enum]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#enum)
|
||||
|
||||
### 6.4.8 Enumeration scope [basic.scope.enum]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1558)
|
||||
|
||||
Any declaration of an enumeration E introduces
|
||||
an [*enumeration scope*](#def:scope,enumeration "6.4.8 Enumeration scope [basic.scope.enum]") that includes the [*enumerator-list*](dcl.enum#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]") of
|
||||
the [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") for E (if any)[.](#1.sentence-1)
|
||||
9
cppdraft/basic/scope/lambda.md
Normal file
9
cppdraft/basic/scope/lambda.md
Normal file
@@ -0,0 +1,9 @@
|
||||
[basic.scope.lambda]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#lambda)
|
||||
|
||||
### 6.4.5 Lambda scope [basic.scope.lambda]
|
||||
|
||||
A [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") E introduces a [*lambda scope*](#def:scope,lambda "6.4.5 Lambda scope [basic.scope.lambda]") that starts immediately after the [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") of E and extends to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of E[.](#sentence-1)
|
||||
23
cppdraft/basic/scope/namespace.md
Normal file
23
cppdraft/basic/scope/namespace.md
Normal file
@@ -0,0 +1,23 @@
|
||||
[basic.scope.namespace]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#namespace)
|
||||
|
||||
### 6.4.6 Namespace scope [basic.scope.namespace]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1501)
|
||||
|
||||
Any [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for a namespace N introduces
|
||||
a [*namespace scope*](#def:scope,namespace "6.4.6 Namespace scope [basic.scope.namespace]") that includes the [*namespace-body*](namespace.def.general#nt:namespace-body "9.9.2.1 General [namespace.def.general]") for every [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") for N[.](#1.sentence-1)
|
||||
|
||||
For each non-friend redeclaration or specialization
|
||||
whose target scope is or is contained by the scope,
|
||||
the portion after the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"),[*class-head-name*](class.pre#nt:class-head-name "11.1 Preamble [class.pre]"), or[*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") is also included in the scope[.](#1.sentence-2)
|
||||
|
||||
The global scope is
|
||||
the namespace scope of the global namespace ([[basic.namespace]](basic.namespace "9.9 Namespaces"))[.](#1.sentence-3)
|
||||
|
||||
[*Example [1](#example-1)*: namespace Q {namespace V { void f(); }void V::f() { // in the scope of Vvoid h(); // declares Q::V::h}} â *end example*]
|
||||
50
cppdraft/basic/scope/param.md
Normal file
50
cppdraft/basic/scope/param.md
Normal file
@@ -0,0 +1,50 @@
|
||||
[basic.scope.param]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#param)
|
||||
|
||||
### 6.4.4 Function parameter scope [basic.scope.param]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1456)
|
||||
|
||||
A [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") P introduces
|
||||
a [*function parameter scope*](#def:scope,function_parameter "6.4.4 Function parameter scope [basic.scope.param]") that includes P[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A function parameter cannot be used for its value
|
||||
within the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
If P is associated with a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") and
|
||||
is preceded by a (possibly-parenthesized) [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") of
|
||||
the form[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt,
|
||||
its scope extends to the end of the nearest enclosing[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]"),[*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]"),[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") or
|
||||
a [*nodeclspec-function-declaration*](dcl.pre#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]"), or[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]"),
|
||||
but does not include the locus of the associated [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")[.](#1.1.sentence-1)
|
||||
[*Note [2](#note-2)*:
|
||||
In this case, P declares the parameters of a function
|
||||
(or a function or template parameter declared with function type)[.](#1.1.sentence-2)
|
||||
A member function's parameter scope is nested within its class's scope[.](#1.1.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
If P is associated with a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
its scope extends to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") in the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")[.](#1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
If P is associated with a [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]"),
|
||||
its scope extends to the end of the [*requirement-body*](expr.prim.req.general#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]") of the [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")[.](#1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
If P is associated with a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]"),
|
||||
its scope extends to the end of the [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")[.](#1.4.sentence-1)
|
||||
195
cppdraft/basic/scope/pdecl.md
Normal file
195
cppdraft/basic/scope/pdecl.md
Normal file
@@ -0,0 +1,195 @@
|
||||
[basic.scope.pdecl]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#pdecl)
|
||||
|
||||
### 6.4.2 Point of declaration [basic.scope.pdecl]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1237)
|
||||
|
||||
The [*locus*](#def:locus "6.4.2 Point of declaration [basic.scope.pdecl]") of a declaration ([[basic.pre]](basic.pre "6.1 Preamble")) that is a declarator
|
||||
is immediately after the complete declarator ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#1.sentence-1)
|
||||
|
||||
[*Example [1](#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]](basic.life "6.8.4 Lifetime"))[.](#1.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1251)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A name from an outer scope remains visible up to
|
||||
the locus of the declaration that hides it[.](#2.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
const int i = 2;{ int i[i]; } declares a block-scope array of two integers[.](#2.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1265)
|
||||
|
||||
The locus of a [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") is immediately after
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)
|
||||
in its [*class-head*](class.pre#nt:class-head "11.1 Preamble [class.pre]") ([[class.pre]](class.pre "11.1 Preamble"))[.](#3.sentence-1)
|
||||
|
||||
The locus of an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") is immediately after
|
||||
its [*enum-head*](dcl.enum#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]");
|
||||
the locus of an [*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]") is immediately after it ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))[.](#3.sentence-2)
|
||||
|
||||
The locus of an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") is immediately after it[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1277)
|
||||
|
||||
The locus of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that does not name a constructor
|
||||
is immediately after the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1282)
|
||||
|
||||
The locus of an [*enumerator-definition*](dcl.enum#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") is immediately after it[.](#5.sentence-1)
|
||||
|
||||
[*Example [3](#example-3)*: const int x = 12;{ enum { x = x }; }
|
||||
|
||||
Here, the enumerator x is initialized with the value of the
|
||||
constant x, namely 12[.](#5.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1293)
|
||||
|
||||
[*Note [2](#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[.](#6.sentence-1)
|
||||
|
||||
[*Example [4](#example-4)*: struct X {enum E { z = 16 }; int b[X::z]; // OK}; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1309)
|
||||
|
||||
The locus of an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") that is a declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) is immediately after it[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1313)
|
||||
|
||||
The locus of an injected-class-name declaration ([[class.pre]](class.pre "11.1 Preamble"))
|
||||
is immediately following the opening brace of the class definition[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1317)
|
||||
|
||||
The locus of the implicit declaration of
|
||||
a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General"))
|
||||
is immediately before
|
||||
the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") of its function's definition[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1323)
|
||||
|
||||
The locus of the declaration of a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))
|
||||
is immediately after
|
||||
the [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") of the structured binding declaration[.](#10.sentence-1)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1328)
|
||||
|
||||
The locus of a [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of a range-based for statement ([[stmt.ranged]](stmt.ranged "8.6.5 The range-based for statement"))
|
||||
is immediately after the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]")[.](#11.sentence-1)
|
||||
|
||||
The locus of a [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion statements"))
|
||||
is immediately after the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]")[.](#11.sentence-2)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1336)
|
||||
|
||||
The locus of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is immediately after it[.](#12.sentence-1)
|
||||
|
||||
[*Example [5](#example-5)*: typedef unsigned char T;template<class T = T // lookup finds the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") , T // lookup finds the template parameter N = 0> struct A { }; â *end example*]
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1348)
|
||||
|
||||
The locus of a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
|
||||
is immediately after it[.](#13.sentence-1)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1352)
|
||||
|
||||
The locus of a [*concept-definition*](temp.concept#nt:concept-definition "13.7.9 Concept definitions [temp.concept]") is immediately after its [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") ([[temp.concept]](temp.concept "13.7.9 Concept definitions"))[.](#14.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") cannot use
|
||||
the [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]")[.](#14.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1360)
|
||||
|
||||
The locus of a [*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]") with an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is immediately after the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#15.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
An identifier is invented
|
||||
for an [*unnamed-namespace-definition*](namespace.def.general#nt:unnamed-namespace-definition "9.9.2.1 General [namespace.def.general]") ([[namespace.unnamed]](namespace.unnamed "9.9.2.2 Unnamed namespaces"))[.](#15.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1369)
|
||||
|
||||
[*Note [5](#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]](class.friend "11.8.4 Friends"))[.](#16.sentence-1)
|
||||
|
||||
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[.](#16.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1381)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
For point of instantiation of a template, see [[temp.point]](temp.point "13.8.4.1 Point of instantiation")[.](#17.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
289
cppdraft/basic/scope/scope.md
Normal file
289
cppdraft/basic/scope/scope.md
Normal file
@@ -0,0 +1,289 @@
|
||||
[basic.scope.scope]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#scope)
|
||||
|
||||
### 6.4.1 General [basic.scope.scope]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L939)
|
||||
|
||||
The declarations in a program appear in a number of [*scopes*](#def:scope "6.4.1 General [basic.scope.scope]") that are in general discontiguous[.](#1.sentence-1)
|
||||
|
||||
The [*global scope*](#def:scope,global "6.4.1 General [basic.scope.scope]") contains the entire program;
|
||||
every other scope S is introduced by a
|
||||
declaration,[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),[*statement*](stmt.pre#nt:statement "8.1 Preamble [stmt.pre]"),[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]"), or
|
||||
contract assertion
|
||||
(as described in the following subclauses of [[basic.scope]](basic.scope "6.4 Scope"))
|
||||
appearing in another scope, which thereby contains S[.](#1.sentence-2)
|
||||
|
||||
An [*enclosing scope*](#def:scope,enclosing "6.4.1 General [basic.scope.scope]") at a program point is any scope that contains it;
|
||||
the smallest such scope is said to be the [*immediate scope*](#def:scope,immediate "6.4.1 General [basic.scope.scope]") at that point[.](#1.sentence-3)
|
||||
|
||||
A scope [*intervenes*](#def:scope,intervene "6.4.1 General [basic.scope.scope]") 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[.](#1.sentence-4)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L958)
|
||||
|
||||
Unless otherwise specified:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
The smallest scope that contains a scope S is
|
||||
the [*parent scope*](#def:scope,parent "6.4.1 General [basic.scope.scope]") of S[.](#2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
No two declarations (re)introduce the same entity[.](#2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
A declaration [*inhabits*](#def:scope,inhabit "6.4.1 General [basic.scope.scope]") the immediate scope at its locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2 Point of declaration"))[.](#2.3.sentence-1)
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
A declaration's [*target scope*](#def:scope,target "6.4.1 General [basic.scope.scope]") is the scope it inhabits[.](#2.4.sentence-1)
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
Any names (re)introduced by a declaration are [*bound*](#def:name,bound "6.4.1 General [basic.scope.scope]") to it
|
||||
in its target scope[.](#2.5.sentence-1)
|
||||
|
||||
The [*host scope*](#def:scope,host "6.4.1 General [basic.scope.scope]") of a declaration is
|
||||
the inhabited scope if that scope is a block scope and
|
||||
the target scope otherwise[.](#2.sentence-2)
|
||||
|
||||
An entity [*belongs*](#def:entity,belong "6.4.1 General [basic.scope.scope]") to a scope S if S is the target scope of a declaration of the entity[.](#2.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Special cases include that:
|
||||
|
||||
- [(2.6)](#2.6)
|
||||
|
||||
Template parameter scopes are parents
|
||||
only to other template parameter scopes ([[basic.scope.temp]](basic.scope.temp "6.4.9 Template parameter scope"))[.](#2.6.sentence-1)
|
||||
|
||||
- [(2.7)](#2.7)
|
||||
|
||||
Corresponding declarations with appropriate linkage
|
||||
declare the same entity ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#2.7.sentence-1)
|
||||
|
||||
- [(2.8)](#2.8)
|
||||
|
||||
The declaration in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") inhabits the same scope as the [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")[.](#2.8.sentence-1)
|
||||
|
||||
- [(2.9)](#2.9)
|
||||
|
||||
Friend declarations and
|
||||
declarations of template specializations do not bind names ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"));
|
||||
those with qualified names target a specified scope, and
|
||||
other friend declarations and
|
||||
certain [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")*s* ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))
|
||||
target a larger enclosing scope[.](#2.9.sentence-1)
|
||||
|
||||
- [(2.10)](#2.10)
|
||||
|
||||
Block-scope extern or function declarations target a larger enclosing scope
|
||||
but bind a name in their immediate scope ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1 General"))[.](#2.10.sentence-1)
|
||||
|
||||
- [(2.11)](#2.11)
|
||||
|
||||
The names of unscoped enumerators are bound
|
||||
in the two innermost enclosing scopes ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))[.](#2.11.sentence-1)
|
||||
|
||||
- [(2.12)](#2.12)
|
||||
|
||||
A class's name is also bound in its own scope ([[class.pre]](class.pre "11.1 Preamble"))[.](#2.12.sentence-1)
|
||||
|
||||
- [(2.13)](#2.13)
|
||||
|
||||
The names of the members of an anonymous union are bound in
|
||||
the union's parent scope ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#2.13.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1013)
|
||||
|
||||
Two non-static member functions have[*corresponding object parameters*](#def:object_parameter,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
exactly one is an implicit object member function
|
||||
with no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") and
|
||||
the types of their object parameters ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
after removing references,
|
||||
are the same, or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
their object parameters have the same type[.](#3.sentence-1)
|
||||
|
||||
Two non-static member function templates have[*corresponding object parameters*](#def:object_parameter,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
exactly one is an implicit object member function
|
||||
with no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") and
|
||||
the types of their object parameters,
|
||||
after removing any references,
|
||||
are equivalent, or
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
the types of their object parameters are equivalent[.](#3.sentence-2)
|
||||
|
||||
Two function templates have[*corresponding signatures*](#def:signature,corresponding "6.4.1 General [basic.scope.scope]") if
|
||||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||||
their corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* 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[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1048)
|
||||
|
||||
Two declarations [*correspond*](#def:correspond "6.4.1 General [basic.scope.scope]") if they (re)introduce the same name,
|
||||
both declare constructors, or
|
||||
both declare destructors,
|
||||
unless
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
either is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"), or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
one declares a type (not a type alias) and the other declares a
|
||||
variable,
|
||||
non-static data member other than of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")),
|
||||
enumerator,
|
||||
function, or
|
||||
function template, or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
each declares a function or function template
|
||||
and they do not declare corresponding overloads[.](#4.sentence-1)
|
||||
|
||||
Two function or function template declarations declare[*corresponding overloads*](#def:corresponding_overloads "6.4.1 General [basic.scope.scope]") if
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
both declare functions with the same non-object-parameter-type-list,[17](#footnote-17 "An implicit object parameter ([over.match.funcs]) is not part of the parameter-type-list.") equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* (if any, except as specified in [[temp.friend]](temp.friend "13.7.5 Friends")), and,
|
||||
if both are non-static members,
|
||||
they have corresponding object parameters, or
|
||||
|
||||
- [(4.5)](#4.5)
|
||||
|
||||
both declare function templates with corresponding signatures and equivalent[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* and
|
||||
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* (if any)[.](#4.sentence-2)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Declarations can correspond even if neither binds a name[.](#4.sentence-3)
|
||||
|
||||
[*Example [1](#example-1)*: struct A {friend void f(); // #1};struct B {friend void f() {} // corresponds to, and defines, #1}; â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*: typedef int Int;enum E : int { a };void f(int); // #1void f(Int) {} // defines #1void f(E) {} // OK, another overloadstruct X {static void f(); void f() const; // error: redeclarationvoid g(); void g() const; // OKvoid g() &; // error: redeclarationvoid h(this X&, int); void h(int) &&; // OK, another overloadvoid j(this const X&); void j() const &; // error: redeclarationvoid k(); void k(this X&); // error: redeclaration}; â *end example*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1124)
|
||||
|
||||
A declaration is [*name-independent*](#def:declaration,name-independent "6.4.1 General [basic.scope.scope]") if its name is _ (U+005f low line) and it declares
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
a variable with automatic storage duration,
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
a structured binding
|
||||
with no [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") and
|
||||
not inhabiting a namespace scope,
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
|
||||
|
||||
- [(5.4)](#5.4)
|
||||
|
||||
the variable introduced by an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]"), or
|
||||
|
||||
- [(5.5)](#5.5)
|
||||
|
||||
a non-static data member of other than an anonymous union[.](#5.sentence-1)
|
||||
|
||||
*Recommended practice*: Implementations should not emit a warning
|
||||
that a name-independent declaration is used or unused[.](#5.sentence-2)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1150)
|
||||
|
||||
Two declarations [*potentially conflict*](#def:potentially_conflict "6.4.1 General [basic.scope.scope]") if they correspond and
|
||||
cause their shared name to denote different entities ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#6.sentence-1)
|
||||
|
||||
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]](basic.lookup "6.5 Name lookup")),
|
||||
unless B is name-independent[.](#6.sentence-2)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") 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]](basic.lookup.general "6.5.1 General"))[.](#6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Overload resolution can consider potentially conflicting declarations
|
||||
found in multiple scopes
|
||||
(e.g., via [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* or for operator functions),
|
||||
in which case it is often ambiguous[.](#6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#example-3)*: void f() {int x,y; void x(); // error: different entity for xint y; // error: redefinition}enum { f }; // error: different entity for ::fnamespace A {}namespace B = A;namespace B = A; // OK, no effectnamespace B = B; // OK, no effectnamespace A = B; // OK, no effectnamespace B {} // error: different entity for Bvoid g() {int _;
|
||||
_ = 0; // OKint _; // OK, name-independent declaration _ = 0; // error: two non-function declarations in the lookup set}void h () {int _; // #1 _ ++; // OKstatic int _; // error: conflicts with #1 because static variables are not name-independent} â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1199)
|
||||
|
||||
A declaration is [*nominable*](#def:nominable "6.4.1 General [basic.scope.scope]") 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]](namespace.def "9.9.2 Namespace definition"))[.](#7.sentence-1)
|
||||
|
||||
[*Example [4](#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[.](#7.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1225)
|
||||
|
||||
When instantiating a templated entity ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||||
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[.](#8.sentence-1)
|
||||
|
||||
[17)](#footnote-17)[17)](#footnoteref-17)
|
||||
|
||||
An implicit object parameter ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists"))
|
||||
is not part of the parameter-type-list[.](#footnote-17.sentence-1)
|
||||
36
cppdraft/basic/scope/temp.md
Normal file
36
cppdraft/basic/scope/temp.md
Normal file
@@ -0,0 +1,36 @@
|
||||
[basic.scope.temp]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.4 Scope [[basic.scope]](basic.scope#temp)
|
||||
|
||||
### 6.4.9 Template parameter scope [basic.scope.temp]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1566)
|
||||
|
||||
Each[*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2 Template parameters [temp.param]"),[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"), and[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template parameters [temp.param]") introduces
|
||||
a [*template parameter scope*](#def:scope,template_parameter "6.4.9 Template parameter scope [basic.scope.temp]") that includes the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of
|
||||
the [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1576)
|
||||
|
||||
Each [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") D introduces
|
||||
a template parameter scope
|
||||
that extends from the beginning of its [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") to the end of the [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")[.](#2.sentence-1)
|
||||
|
||||
Any declaration outside the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") that would inhabit that scope instead inhabits the same scope as D[.](#2.sentence-2)
|
||||
|
||||
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[.](#2.sentence-3)
|
||||
|
||||
[*Note [1](#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[.](#2.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
63
cppdraft/basic/splice.md
Normal file
63
cppdraft/basic/splice.md
Normal file
@@ -0,0 +1,63 @@
|
||||
[basic.splice]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.6 Splice specifiers [basic.splice]
|
||||
|
||||
[splice-specifier:](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||||
[: [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") :]
|
||||
|
||||
[splice-specialization-specifier:](#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]")
|
||||
[*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") < [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]")opt >
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2822)
|
||||
|
||||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") shall be a converted constant expression of
|
||||
type std::meta::info ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#1.sentence-1)
|
||||
|
||||
A [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") whose converted [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") represents
|
||||
a construct X is said to [*designate*](#def:designate "6.6 Splice specifiers [basic.splice]") either
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
the underlying entity of X if X is an entity ([[basic.pre]](basic.pre "6.1 Preamble")), or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
X otherwise[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") is dependent
|
||||
if the converted [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is
|
||||
value-dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2839)
|
||||
|
||||
A non-dependent [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of
|
||||
a [*splice-specialization-specifier*](#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") shall designate a template[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2843)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
A < following a [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") is interpreted as
|
||||
the delimiter of a [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") when the [*splice-specifier*](#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") is preceded by
|
||||
the keyword template or the keyword typename, or
|
||||
when it appears in a type-only context ([[temp.names]](temp.names "13.3 Names of template specializations"))[.](#3.sentence-1)
|
||||
|
||||
[*Example [1](#example-1)*: constexpr int v = 1;template<int V> struct TCls {static constexpr int s = V + 1;};
|
||||
|
||||
using alias = [:^^TCls:]<([:^^v:])>; // OK, a [*splice-specialization-specifier*](#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") with a parenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") as a template argumentstatic_assert(alias::s == 2);
|
||||
|
||||
auto o1 = [:^^TCls:]<([:^^v:])>(); // error: < means less thanauto o2 = typename [:^^TCls:]<([:^^v:])>(); // OK, o2 is an object of type TCls<1>consteval int bad_splice(std::meta::info v) {return [:v:]; // error: v is not constant} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
515
cppdraft/basic/start.md
Normal file
515
cppdraft/basic/start.md
Normal file
@@ -0,0 +1,515 @@
|
||||
[basic.start]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.10 Program execution [[basic.exec]](basic.exec#basic.start)
|
||||
|
||||
### 6.10.3 Start and termination [basic.start]
|
||||
|
||||
#### [6.10.3.1](#main) main function [[basic.start.main]](basic.start.main)
|
||||
|
||||
[1](#main-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7129)
|
||||
|
||||
A program shall contain exactly one function called main that belongs to the global scope[.](#main-1.sentence-1)
|
||||
|
||||
Executing a program starts a main thread of execution ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"), [[thread.threads]](thread.threads "32.4 Threads"))
|
||||
in which the main function is invoked[.](#main-1.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
whether a program in a freestanding environment is required to define a main function[.](#main-1.sentence-3)
|
||||
|
||||
[*Note [1](#main-note-1)*:
|
||||
|
||||
In a freestanding environment, startup and termination isimplementation-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[.](#main-1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#main-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7147)
|
||||
|
||||
An implementation shall not predefine the main function[.](#main-2.sentence-1)
|
||||
|
||||
Its type shall have C++ language linkage
|
||||
and it shall have a declared return type of typeint, but otherwise its type is implementation-defined[.](#main-2.sentence-2)
|
||||
|
||||
An implementation shall allow both
|
||||
|
||||
- [(2.1)](#main-2.1)
|
||||
|
||||
a function of () returning int and
|
||||
|
||||
- [(2.2)](#main-2.2)
|
||||
|
||||
a function of (int, pointer to pointer to char) returning int
|
||||
|
||||
as the type of main ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#main-2.sentence-3)
|
||||
|
||||
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[.](#main-2.sentence-4)
|
||||
|
||||
Ifargc is nonzero these arguments shall be supplied inargv[0] through argv[argc - 1] as pointers to the initial
|
||||
characters of null-terminated multibyte strings (ntmbss) ([[multibyte.strings]](multibyte.strings "16.3.3.3.4.3 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 ""[.](#main-2.sentence-5)
|
||||
|
||||
The value of argc shall be
|
||||
non-negative[.](#main-2.sentence-6)
|
||||
|
||||
The value of argv[argc] shall be 0[.](#main-2.sentence-7)
|
||||
|
||||
*Recommended practice*: Any further (optional) parameters should be added after argv[.](#main-2.sentence-8)
|
||||
|
||||
[3](#main-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7179)
|
||||
|
||||
The function main shall not be named by an expression[.](#main-3.sentence-1)
|
||||
|
||||
The linkage ([[basic.link]](basic.link "6.7 Program and linkage")) of main isimplementation-defined[.](#main-3.sentence-2)
|
||||
|
||||
A program that defines main as
|
||||
deleted or that declares main to beinline, static, constexpr, or consteval is ill-formed[.](#main-3.sentence-3)
|
||||
|
||||
The function main shall not be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#main-3.sentence-4)
|
||||
|
||||
The main function shall not be declared with a[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]") ([[dcl.link]](dcl.link "9.12 Linkage specifications")) other than "C++"[.](#main-3.sentence-5)
|
||||
|
||||
A program that declares
|
||||
|
||||
- [(3.1)](#main-3.1)
|
||||
|
||||
a variable main that belongs to the global scope, or
|
||||
|
||||
- [(3.2)](#main-3.2)
|
||||
|
||||
a function main that belongs to the global scope and
|
||||
is attached to a named module, or
|
||||
|
||||
- [(3.3)](#main-3.3)
|
||||
|
||||
a function template main that belongs to the global scope, or
|
||||
|
||||
- [(3.4)](#main-3.4)
|
||||
|
||||
an entity named main with C language linkage (in any namespace)
|
||||
|
||||
is ill-formed[.](#main-3.sentence-6)
|
||||
|
||||
The name main is
|
||||
not otherwise reserved[.](#main-3.sentence-7)
|
||||
|
||||
[*Example [1](#main-example-1)*:
|
||||
|
||||
Member functions, classes, and
|
||||
enumerations can be called main, as can entities in other
|
||||
namespaces[.](#main-3.sentence-8)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#main-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7211)
|
||||
|
||||
Terminating the program
|
||||
without leaving the current block (e.g., by calling the functionstd::exit(int) ([[support.start.term]](support.start.term "17.5 Startup and termination"))) does not destroy any
|
||||
objects with automatic storage duration ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#main-4.sentence-1)
|
||||
|
||||
Ifstd::exit is invoked during the destruction of
|
||||
an object with static or thread storage duration, the program has undefined
|
||||
behavior[.](#main-4.sentence-2)
|
||||
|
||||
[5](#main-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7223)
|
||||
|
||||
A return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) 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[.](#main-5.sentence-1)
|
||||
|
||||
If control flows off the end of
|
||||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of main,
|
||||
the effect is equivalent to a return with operand 0 (see also [[except.handle]](except.handle "14.4 Handling an exception"))[.](#main-5.sentence-2)
|
||||
|
||||
#### [6.10.3.2](#static) Static initialization [[basic.start.static]](basic.start.static)
|
||||
|
||||
[1](#static-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7238)
|
||||
|
||||
Variables with static storage duration
|
||||
are initialized as a consequence of program initiation[.](#static-1.sentence-1)
|
||||
|
||||
Variables with
|
||||
thread storage duration are initialized as a consequence of thread execution[.](#static-1.sentence-2)
|
||||
|
||||
Within each of these phases of initiation, initialization occurs as follows[.](#static-1.sentence-3)
|
||||
|
||||
[2](#static-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7246)
|
||||
|
||||
[*Constant initialization*](#def:constant_initialization "6.10.3.2 Static initialization [basic.start.static]") is performed
|
||||
if a variable with static or thread storage duration
|
||||
is constant-initialized ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#static-2.sentence-1)
|
||||
|
||||
If constant initialization is not performed, a variable with static
|
||||
storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")) or thread storage
|
||||
duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")) is zero-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#static-2.sentence-2)
|
||||
|
||||
Together, zero-initialization and constant initialization are called[*static initialization*](#def:initialization,static "6.10.3.2 Static initialization [basic.start.static]");
|
||||
all other initialization is [*dynamic initialization*](#def:initialization,dynamic "6.10.3.2 Static initialization [basic.start.static]")[.](#static-2.sentence-3)
|
||||
|
||||
All static initialization strongly happens before ([[intro.races]](intro.races "6.10.2.2 Data races"))
|
||||
any dynamic initialization[.](#static-2.sentence-4)
|
||||
|
||||
[*Note [1](#static-note-1)*:
|
||||
|
||||
The dynamic initialization of non-block variables is described
|
||||
in [[basic.start.dynamic]](#dynamic "6.10.3.3 Dynamic initialization of non-block variables"); that of static block variables is described
|
||||
in [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#static-2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#static-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7266)
|
||||
|
||||
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
|
||||
|
||||
- [(3.1)](#static-3.1)
|
||||
|
||||
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
|
||||
|
||||
- [(3.2)](#static-3.2)
|
||||
|
||||
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[.](#static-3.sentence-1)
|
||||
|
||||
[*Note [2](#static-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[.](#static-3.sentence-2)
|
||||
|
||||
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 otherwisedouble d1 = fd(); // either initialized statically or dynamically to 1.0
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [6.10.3.3](#dynamic) Dynamic initialization of non-block variables [[basic.start.dynamic]](basic.start.dynamic)
|
||||
|
||||
[1](#dynamic-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7302)
|
||||
|
||||
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[.](#dynamic-1.sentence-1)
|
||||
|
||||
[*Note [1](#dynamic-note-1)*:
|
||||
|
||||
A non-inline explicit specialization of a templated variable
|
||||
has ordered initialization[.](#dynamic-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#dynamic-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7316)
|
||||
|
||||
A declaration D is[*appearance-ordered*](#def:appearance-ordered "6.10.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]") before a declaration E if
|
||||
|
||||
- [(2.1)](#dynamic-2.1)
|
||||
|
||||
D appears in the same translation unit as E, or
|
||||
|
||||
- [(2.2)](#dynamic-2.2)
|
||||
|
||||
the translation unit containing E has an interface dependency on the translation unit containing D,
|
||||
|
||||
in either case prior to E[.](#dynamic-2.sentence-1)
|
||||
|
||||
[3](#dynamic-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7326)
|
||||
|
||||
Dynamic initialization of non-block variables V and W with static storage duration are ordered as follows:
|
||||
|
||||
- [(3.1)](#dynamic-3.1)
|
||||
|
||||
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
|
||||
* [(3.1.1)](#dynamic-3.1.1)
|
||||
|
||||
if the program does not start a thread ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))
|
||||
other than the main thread ([[basic.start.main]](#main "6.10.3.1 main function"))
|
||||
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;
|
||||
|
||||
* [(3.1.2)](#dynamic-3.1.2)
|
||||
|
||||
otherwise,
|
||||
the initialization of V strongly happens before
|
||||
the initialization of W[.](#dynamic-3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#dynamic-3.2)
|
||||
|
||||
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[.](#dynamic-3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#dynamic-3.3)
|
||||
|
||||
Otherwise, the initializations of V and W are indeterminately sequenced[.](#dynamic-3.3.sentence-1)
|
||||
|
||||
[*Note [2](#dynamic-note-2)*:
|
||||
|
||||
This definition permits initialization of a sequence of
|
||||
ordered variables concurrently with another sequence[.](#dynamic-3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#dynamic-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7371)
|
||||
|
||||
A [*non-initialization odr-use*](#def:odr-use,non-initialization "6.10.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]") is an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) not caused directly or indirectly by
|
||||
the initialization of a non-block static or thread storage duration variable[.](#dynamic-4.sentence-1)
|
||||
|
||||
[5](#dynamic-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7377)
|
||||
|
||||
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[.](#dynamic-5.sentence-1)
|
||||
|
||||
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[.](#dynamic-5.sentence-2)[38](#footnote-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 ([term.odr.use], [basic.stc.static]).")
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#dynamic-5.sentence-3)
|
||||
|
||||
*Recommended practice*: An implementation should choose such points in a way
|
||||
that allows the programmer to avoid deadlocks[.](#dynamic-5.sentence-4)
|
||||
|
||||
[*Example [1](#dynamic-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 inmain[.](#dynamic-5.sentence-5)
|
||||
|
||||
In particular, if a is initialized beforemain 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[.](#dynamic-5.sentence-6)
|
||||
|
||||
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[.](#dynamic-5.sentence-7)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#dynamic-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7437)
|
||||
|
||||
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[.](#dynamic-6.sentence-1)
|
||||
|
||||
If it is deferred, it strongly happens before
|
||||
any non-initialization odr-use
|
||||
of that variable[.](#dynamic-6.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#dynamic-6.sentence-3)
|
||||
|
||||
[7](#dynamic-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7448)
|
||||
|
||||
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[.](#dynamic-7.sentence-1)
|
||||
|
||||
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[.](#dynamic-7.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#dynamic-7.sentence-3)
|
||||
|
||||
[8](#dynamic-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7461)
|
||||
|
||||
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]](except.terminate "14.6.2 The std::terminate function"))[.](#dynamic-8.sentence-1)
|
||||
|
||||
[38)](#footnote-38)[38)](#footnoteref-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.def.odr#term.odr.use "6.3 One-definition rule"), [[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration"))[.](#footnote-38.sentence-1)
|
||||
|
||||
#### [6.10.3.4](#term) Termination [[basic.start.term]](basic.start.term)
|
||||
|
||||
[1](#term-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7470)
|
||||
|
||||
Constructed objects ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
with static storage duration are destroyed
|
||||
and functions registered with std::atexit are called as part of a call tostd::exit ([[support.start.term]](support.start.term "17.5 Startup and termination"))[.](#term-1.sentence-1)
|
||||
|
||||
The call to std::exit is sequenced before
|
||||
the destructions and the registered functions[.](#term-1.sentence-2)
|
||||
|
||||
[*Note [1](#term-note-1)*:
|
||||
|
||||
Returning from main invokes std::exit ([[basic.start.main]](#main "6.10.3.1 main function"))[.](#term-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#term-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7487)
|
||||
|
||||
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[.](#term-2.sentence-1)
|
||||
|
||||
The destruction of all constructed objects with thread storage
|
||||
duration within that thread strongly happens before destroying
|
||||
any object with static storage duration[.](#term-2.sentence-2)
|
||||
|
||||
[3](#term-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7495)
|
||||
|
||||
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[.](#term-3.sentence-1)
|
||||
|
||||
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[.](#term-3.sentence-2)
|
||||
|
||||
If an object is
|
||||
initialized statically, the object is destroyed in the same order as if
|
||||
the object was dynamically initialized[.](#term-3.sentence-3)
|
||||
|
||||
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[.](#term-3.sentence-4)
|
||||
|
||||
If the destruction of an object with static or thread storage duration
|
||||
exits via an exception,
|
||||
the function std::terminate is called ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#term-3.sentence-5)
|
||||
|
||||
[4](#term-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7512)
|
||||
|
||||
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[.](#term-4.sentence-1)
|
||||
|
||||
[*Note [2](#term-note-2)*:
|
||||
|
||||
Likewise, the behavior is undefined
|
||||
if the block variable is used indirectly (e.g., through a pointer)
|
||||
after its destruction[.](#term-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#term-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7523)
|
||||
|
||||
If the completion of the initialization of an object with static storage
|
||||
duration strongly happens before a call to std::atexit (see[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2 Header <cstdlib> synopsis [cstdlib.syn]"), [[support.start.term]](support.start.term "17.5 Startup and termination")), the call to the function passed tostd::atexit is sequenced before the call to the destructor for the object[.](#term-5.sentence-1)
|
||||
|
||||
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[.](#term-5.sentence-2)
|
||||
|
||||
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[.](#term-5.sentence-3)
|
||||
|
||||
[6](#term-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7537)
|
||||
|
||||
If there is a use of a standard library object or function not permitted within signal
|
||||
handlers ([[support.runtime]](support.runtime "17.14 Other runtime support")) that does not happen before ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))
|
||||
completion of destruction of objects with static storage duration and execution ofstd::atexit registered functions ([[support.start.term]](support.start.term "17.5 Startup and termination")), the program has
|
||||
undefined behavior[.](#term-6.sentence-1)
|
||||
|
||||
[*Note [3](#term-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[.](#term-6.sentence-2)
|
||||
|
||||
Terminating every thread before a call to std::exit or the exit frommain is sufficient, but not necessary, to satisfy these requirements[.](#term-6.sentence-3)
|
||||
|
||||
These
|
||||
requirements permit thread managers as static-storage-duration objects[.](#term-6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#term-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7551)
|
||||
|
||||
Calling the function std::abort() declared in[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2 Header <cstdlib> synopsis [cstdlib.syn]") terminates the program without executing any destructors
|
||||
and without calling
|
||||
the functions passed to std::atexit() or std::at_quick_exit()[.](#term-7.sentence-1)
|
||||
187
cppdraft/basic/start/dynamic.md
Normal file
187
cppdraft/basic/start/dynamic.md
Normal file
@@ -0,0 +1,187 @@
|
||||
[basic.start.dynamic]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.10 Program execution [[basic.exec]](basic.exec#basic.start.dynamic)
|
||||
|
||||
### 6.10.3 Start and termination [[basic.start]](basic.start#dynamic)
|
||||
|
||||
#### 6.10.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7302)
|
||||
|
||||
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[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A non-inline explicit specialization of a templated variable
|
||||
has ordered initialization[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7316)
|
||||
|
||||
A declaration D is[*appearance-ordered*](#def:appearance-ordered "6.10.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]") before a declaration E if
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
D appears in the same translation unit as E, or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
the translation unit containing E has an interface dependency on the translation unit containing D,
|
||||
|
||||
in either case prior to E[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7326)
|
||||
|
||||
Dynamic initialization of non-block variables V and W with static storage duration are ordered as follows:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
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
|
||||
* [(3.1.1)](#3.1.1)
|
||||
|
||||
if the program does not start a thread ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))
|
||||
other than the main thread ([[basic.start.main]](basic.start.main "6.10.3.1 main function"))
|
||||
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;
|
||||
|
||||
* [(3.1.2)](#3.1.2)
|
||||
|
||||
otherwise,
|
||||
the initialization of V strongly happens before
|
||||
the initialization of W[.](#3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
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[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
Otherwise, the initializations of V and W are indeterminately sequenced[.](#3.3.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This definition permits initialization of a sequence of
|
||||
ordered variables concurrently with another sequence[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7371)
|
||||
|
||||
A [*non-initialization odr-use*](#def:odr-use,non-initialization "6.10.3.3 Dynamic initialization of non-block variables [basic.start.dynamic]") is an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) not caused directly or indirectly by
|
||||
the initialization of a non-block static or thread storage duration variable[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7377)
|
||||
|
||||
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[.](#5.sentence-1)
|
||||
|
||||
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[.](#5.sentence-2)[38](#footnote-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 ([term.odr.use], [basic.stc.static]).")
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#5.sentence-3)
|
||||
|
||||
*Recommended practice*: An implementation should choose such points in a way
|
||||
that allows the programmer to avoid deadlocks[.](#5.sentence-4)
|
||||
|
||||
[*Example [1](#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 inmain[.](#5.sentence-5)
|
||||
|
||||
In particular, if a is initialized beforemain 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[.](#5.sentence-6)
|
||||
|
||||
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[.](#5.sentence-7)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7437)
|
||||
|
||||
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[.](#6.sentence-1)
|
||||
|
||||
If it is deferred, it strongly happens before
|
||||
any non-initialization odr-use
|
||||
of that variable[.](#6.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#6.sentence-3)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7448)
|
||||
|
||||
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[.](#7.sentence-1)
|
||||
|
||||
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[.](#7.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
in which threads and at which points in the program such deferred dynamic initialization occurs[.](#7.sentence-3)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7461)
|
||||
|
||||
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]](except.terminate "14.6.2 The std::terminate function"))[.](#8.sentence-1)
|
||||
|
||||
[38)](#footnote-38)[38)](#footnoteref-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.def.odr#term.odr.use "6.3 One-definition rule"), [[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration"))[.](#footnote-38.sentence-1)
|
||||
141
cppdraft/basic/start/main.md
Normal file
141
cppdraft/basic/start/main.md
Normal file
@@ -0,0 +1,141 @@
|
||||
[basic.start.main]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.10 Program execution [[basic.exec]](basic.exec#basic.start.main)
|
||||
|
||||
### 6.10.3 Start and termination [[basic.start]](basic.start#main)
|
||||
|
||||
#### 6.10.3.1 main function [basic.start.main]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7129)
|
||||
|
||||
A program shall contain exactly one function called main that belongs to the global scope[.](#1.sentence-1)
|
||||
|
||||
Executing a program starts a main thread of execution ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"), [[thread.threads]](thread.threads "32.4 Threads"))
|
||||
in which the main function is invoked[.](#1.sentence-2)
|
||||
|
||||
It is implementation-defined
|
||||
whether a program in a freestanding environment is required to define a main function[.](#1.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
In a freestanding environment, startup and termination isimplementation-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[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7147)
|
||||
|
||||
An implementation shall not predefine the main function[.](#2.sentence-1)
|
||||
|
||||
Its type shall have C++ language linkage
|
||||
and it shall have a declared return type of typeint, but otherwise its type is implementation-defined[.](#2.sentence-2)
|
||||
|
||||
An implementation shall allow both
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
a function of () returning int and
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
a function of (int, pointer to pointer to char) returning int
|
||||
|
||||
as the type of main ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#2.sentence-3)
|
||||
|
||||
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[.](#2.sentence-4)
|
||||
|
||||
Ifargc is nonzero these arguments shall be supplied inargv[0] through argv[argc - 1] as pointers to the initial
|
||||
characters of null-terminated multibyte strings (ntmbss) ([[multibyte.strings]](multibyte.strings "16.3.3.3.4.3 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 ""[.](#2.sentence-5)
|
||||
|
||||
The value of argc shall be
|
||||
non-negative[.](#2.sentence-6)
|
||||
|
||||
The value of argv[argc] shall be 0[.](#2.sentence-7)
|
||||
|
||||
*Recommended practice*: Any further (optional) parameters should be added after argv[.](#2.sentence-8)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7179)
|
||||
|
||||
The function main shall not be named by an expression[.](#3.sentence-1)
|
||||
|
||||
The linkage ([[basic.link]](basic.link "6.7 Program and linkage")) of main isimplementation-defined[.](#3.sentence-2)
|
||||
|
||||
A program that defines main as
|
||||
deleted or that declares main to beinline, static, constexpr, or consteval is ill-formed[.](#3.sentence-3)
|
||||
|
||||
The function main shall not be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#3.sentence-4)
|
||||
|
||||
The main function shall not be declared with a[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]") ([[dcl.link]](dcl.link "9.12 Linkage specifications")) other than "C++"[.](#3.sentence-5)
|
||||
|
||||
A program that declares
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
a variable main that belongs to the global scope, or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
a function main that belongs to the global scope and
|
||||
is attached to a named module, or
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
a function template main that belongs to the global scope, or
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
an entity named main with C language linkage (in any namespace)
|
||||
|
||||
is ill-formed[.](#3.sentence-6)
|
||||
|
||||
The name main is
|
||||
not otherwise reserved[.](#3.sentence-7)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
Member functions, classes, and
|
||||
enumerations can be called main, as can entities in other
|
||||
namespaces[.](#3.sentence-8)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7211)
|
||||
|
||||
Terminating the program
|
||||
without leaving the current block (e.g., by calling the functionstd::exit(int) ([[support.start.term]](support.start.term "17.5 Startup and termination"))) does not destroy any
|
||||
objects with automatic storage duration ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#4.sentence-1)
|
||||
|
||||
Ifstd::exit is invoked during the destruction of
|
||||
an object with static or thread storage duration, the program has undefined
|
||||
behavior[.](#4.sentence-2)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7223)
|
||||
|
||||
A return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) 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[.](#5.sentence-1)
|
||||
|
||||
If control flows off the end of
|
||||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of main,
|
||||
the effect is equivalent to a return with operand 0 (see also [[except.handle]](except.handle "14.4 Handling an exception"))[.](#5.sentence-2)
|
||||
81
cppdraft/basic/start/static.md
Normal file
81
cppdraft/basic/start/static.md
Normal file
@@ -0,0 +1,81 @@
|
||||
[basic.start.static]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.10 Program execution [[basic.exec]](basic.exec#basic.start.static)
|
||||
|
||||
### 6.10.3 Start and termination [[basic.start]](basic.start#static)
|
||||
|
||||
#### 6.10.3.2 Static initialization [basic.start.static]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7238)
|
||||
|
||||
Variables with static storage duration
|
||||
are initialized as a consequence of program initiation[.](#1.sentence-1)
|
||||
|
||||
Variables with
|
||||
thread storage duration are initialized as a consequence of thread execution[.](#1.sentence-2)
|
||||
|
||||
Within each of these phases of initiation, initialization occurs as follows[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7246)
|
||||
|
||||
[*Constant initialization*](#def:constant_initialization "6.10.3.2 Static initialization [basic.start.static]") is performed
|
||||
if a variable with static or thread storage duration
|
||||
is constant-initialized ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#2.sentence-1)
|
||||
|
||||
If constant initialization is not performed, a variable with static
|
||||
storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")) or thread storage
|
||||
duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")) is zero-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#2.sentence-2)
|
||||
|
||||
Together, zero-initialization and constant initialization are called[*static initialization*](#def:initialization,static "6.10.3.2 Static initialization [basic.start.static]");
|
||||
all other initialization is [*dynamic initialization*](#def:initialization,dynamic "6.10.3.2 Static initialization [basic.start.static]")[.](#2.sentence-3)
|
||||
|
||||
All static initialization strongly happens before ([[intro.races]](intro.races "6.10.2.2 Data races"))
|
||||
any dynamic initialization[.](#2.sentence-4)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The dynamic initialization of non-block variables is described
|
||||
in [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"); that of static block variables is described
|
||||
in [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#2.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7266)
|
||||
|
||||
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
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
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
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
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[.](#3.sentence-1)
|
||||
|
||||
[*Note [2](#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[.](#3.sentence-2)
|
||||
|
||||
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 otherwisedouble d1 = fd(); // either initialized statically or dynamically to 1.0
|
||||
|
||||
â *end note*]
|
||||
127
cppdraft/basic/start/term.md
Normal file
127
cppdraft/basic/start/term.md
Normal file
@@ -0,0 +1,127 @@
|
||||
[basic.start.term]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.10 Program execution [[basic.exec]](basic.exec#basic.start.term)
|
||||
|
||||
### 6.10.3 Start and termination [[basic.start]](basic.start#term)
|
||||
|
||||
#### 6.10.3.4 Termination [basic.start.term]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7470)
|
||||
|
||||
Constructed objects ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
with static storage duration are destroyed
|
||||
and functions registered with std::atexit are called as part of a call tostd::exit ([[support.start.term]](support.start.term "17.5 Startup and termination"))[.](#1.sentence-1)
|
||||
|
||||
The call to std::exit is sequenced before
|
||||
the destructions and the registered functions[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Returning from main invokes std::exit ([[basic.start.main]](basic.start.main "6.10.3.1 main function"))[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7487)
|
||||
|
||||
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[.](#2.sentence-1)
|
||||
|
||||
The destruction of all constructed objects with thread storage
|
||||
duration within that thread strongly happens before destroying
|
||||
any object with static storage duration[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7495)
|
||||
|
||||
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[.](#3.sentence-1)
|
||||
|
||||
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[.](#3.sentence-2)
|
||||
|
||||
If an object is
|
||||
initialized statically, the object is destroyed in the same order as if
|
||||
the object was dynamically initialized[.](#3.sentence-3)
|
||||
|
||||
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[.](#3.sentence-4)
|
||||
|
||||
If the destruction of an object with static or thread storage duration
|
||||
exits via an exception,
|
||||
the function std::terminate is called ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#3.sentence-5)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7512)
|
||||
|
||||
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[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Likewise, the behavior is undefined
|
||||
if the block variable is used indirectly (e.g., through a pointer)
|
||||
after its destruction[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7523)
|
||||
|
||||
If the completion of the initialization of an object with static storage
|
||||
duration strongly happens before a call to std::atexit (see[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2 Header <cstdlib> synopsis [cstdlib.syn]"), [[support.start.term]](support.start.term "17.5 Startup and termination")), the call to the function passed tostd::atexit is sequenced before the call to the destructor for the object[.](#5.sentence-1)
|
||||
|
||||
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[.](#5.sentence-2)
|
||||
|
||||
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[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7537)
|
||||
|
||||
If there is a use of a standard library object or function not permitted within signal
|
||||
handlers ([[support.runtime]](support.runtime "17.14 Other runtime support")) that does not happen before ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))
|
||||
completion of destruction of objects with static storage duration and execution ofstd::atexit registered functions ([[support.start.term]](support.start.term "17.5 Startup and termination")), the program has
|
||||
undefined behavior[.](#6.sentence-1)
|
||||
|
||||
[*Note [3](#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[.](#6.sentence-2)
|
||||
|
||||
Terminating every thread before a call to std::exit or the exit frommain is sufficient, but not necessary, to satisfy these requirements[.](#6.sentence-3)
|
||||
|
||||
These
|
||||
requirements permit thread managers as static-storage-duration objects[.](#6.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L7551)
|
||||
|
||||
Calling the function std::abort() declared in[<cstdlib>](cstdlib.syn#header:%3ccstdlib%3e "17.2.2 Header <cstdlib> synopsis [cstdlib.syn]") terminates the program without executing any destructors
|
||||
and without calling
|
||||
the functions passed to std::atexit() or std::at_quick_exit()[.](#7.sentence-1)
|
||||
494
cppdraft/basic/stc.md
Normal file
494
cppdraft/basic/stc.md
Normal file
@@ -0,0 +1,494 @@
|
||||
[basic.stc]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc)
|
||||
|
||||
### 6.8.6 Storage duration [basic.stc]
|
||||
|
||||
#### [6.8.6.1](#general) General [[basic.stc.general]](basic.stc.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4244)
|
||||
|
||||
The [*storage duration*](#def:storage_duration "6.8.6.1 General [basic.stc.general]") is the property of an object that defines the minimum
|
||||
potential lifetime of the storage containing the object[.](#general-1.sentence-1)
|
||||
|
||||
The storage
|
||||
duration is determined by the construct used to create the object and is
|
||||
one of the following:
|
||||
|
||||
- [(1.1)](#general-1.1)
|
||||
|
||||
static storage duration
|
||||
|
||||
- [(1.2)](#general-1.2)
|
||||
|
||||
thread storage duration
|
||||
|
||||
- [(1.3)](#general-1.3)
|
||||
|
||||
automatic storage duration
|
||||
|
||||
- [(1.4)](#general-1.4)
|
||||
|
||||
dynamic storage duration
|
||||
|
||||
[*Note [1](#general-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]](basic.compound "6.9.4 Compound types"))[.](#general-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4261)
|
||||
|
||||
Static, thread, and automatic storage durations are associated with objects
|
||||
introduced by declarations ([[basic.def]](basic.def "6.2 Declarations and definitions")) and
|
||||
with temporary objects ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#general-2.sentence-1)
|
||||
|
||||
The dynamic storage duration
|
||||
is associated with objects created by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")) or
|
||||
with implicitly created objects ([[intro.object]](intro.object "6.8.2 Object model"))[.](#general-2.sentence-2)
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4274)
|
||||
|
||||
The storage duration categories apply to references as well[.](#general-3.sentence-1)
|
||||
|
||||
[4](#general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4277)
|
||||
|
||||
The storage duration of subobjects and reference members
|
||||
is that of their complete object ([[intro.object]](intro.object "6.8.2 Object model"))[.](#general-4.sentence-1)
|
||||
|
||||
#### [6.8.6.2](#static) Static storage duration [[basic.stc.static]](basic.stc.static)
|
||||
|
||||
[1](#static-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4285)
|
||||
|
||||
All variables which
|
||||
|
||||
- [(1.1)](#static-1.1)
|
||||
|
||||
do not have thread storage duration and
|
||||
|
||||
- [(1.2)](#static-1.2)
|
||||
|
||||
belong to a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace scope")) or
|
||||
are first declared with
|
||||
the static or extern keywords ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers"))
|
||||
|
||||
have [*static storage duration*](#def:storage_duration,static "6.8.6.2 Static storage duration [basic.stc.static]")[.](#static-1.sentence-1)
|
||||
|
||||
The storage for these entities lasts for the duration of the
|
||||
program ([[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.term]](basic.start.term "6.10.3.4 Termination"))[.](#static-1.sentence-2)
|
||||
|
||||
[2](#static-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4299)
|
||||
|
||||
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]](class.copy.elision "11.9.6 Copy/move elision")[.](#static-2.sentence-1)
|
||||
|
||||
[3](#static-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4305)
|
||||
|
||||
[*Note [1](#static-note-1)*:
|
||||
|
||||
The keyword static can be used to declare
|
||||
a block variable ([[basic.scope.block]](basic.scope.block "6.4.3 Block scope")) with static storage duration;[[stmt.dcl]](stmt.dcl "8.10 Declaration statement") and [[basic.start.term]](basic.start.term "6.10.3.4 Termination") describe the
|
||||
initialization and destruction of such variables[.](#static-3.sentence-1)
|
||||
|
||||
The keyword static applied to
|
||||
a class data member in a class definition
|
||||
gives the data member static storage duration ([[class.static.data]](class.static.data "11.4.9.3 Static data members"))[.](#static-3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [6.8.6.3](#thread) Thread storage duration [[basic.stc.thread]](basic.stc.thread)
|
||||
|
||||
[1](#thread-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4320)
|
||||
|
||||
All variables declared with the thread_local keyword have[*thread storage duration*](#def:storage_duration,thread "6.8.6.3 Thread storage duration [basic.stc.thread]")[.](#thread-1.sentence-1)
|
||||
|
||||
The storage for these entities lasts for the duration of
|
||||
the thread in which they are created[.](#thread-1.sentence-2)
|
||||
|
||||
There is a distinct object or reference
|
||||
per thread, and use of the declared name refers to the entity associated with
|
||||
the current thread[.](#thread-1.sentence-3)
|
||||
|
||||
[2](#thread-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4328)
|
||||
|
||||
[*Note [1](#thread-note-1)*:
|
||||
|
||||
A variable with thread storage duration is initialized as specified
|
||||
in [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement") and, if constructed, is destroyed on thread exit ([[basic.start.term]](basic.start.term "6.10.3.4 Termination"))[.](#thread-2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [6.8.6.4](#auto) Automatic storage duration [[basic.stc.auto]](basic.stc.auto)
|
||||
|
||||
[1](#auto-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4337)
|
||||
|
||||
Variables that belong to a block scope and are
|
||||
not explicitly declared static, thread_local, or extern have[*automatic storage duration*](#def:storage_duration,automatic "6.8.6.4 Automatic storage duration [basic.stc.auto]")[.](#auto-1.sentence-1)
|
||||
|
||||
The storage
|
||||
for such variables lasts until the block in which they are created exits[.](#auto-1.sentence-2)
|
||||
|
||||
[*Note [1](#auto-note-1)*:
|
||||
|
||||
These variables are initialized and destroyed as described in [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#auto-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Variables that belong to a parameter scope also have automatic storage duration[.](#auto-1.sentence-4)
|
||||
|
||||
The storage for a function parameter lasts until
|
||||
immediately after its destruction ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#auto-1.sentence-5)
|
||||
|
||||
[2](#auto-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4350)
|
||||
|
||||
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]](class.copy.elision "11.9.6 Copy/move elision")[.](#auto-2.sentence-1)
|
||||
|
||||
#### [6.8.6.5](#dynamic) Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic)
|
||||
|
||||
#### [6.8.6.5.1](#dynamic.general) General [[basic.stc.dynamic.general]](basic.stc.dynamic.general)
|
||||
|
||||
[1](#dynamic.general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4362)
|
||||
|
||||
Objects can be created dynamically during [program
|
||||
execution](intro.execution "6.10.1 Sequential execution [intro.execution]"), using[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), and destroyed using[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]")*s* ([[expr.delete]](expr.delete "7.6.2.9 Delete"))[.](#dynamic.general-1.sentence-1)
|
||||
|
||||
A C++ implementation
|
||||
provides access to, and management of, dynamic storage via
|
||||
the global [*allocation functions*](#def:allocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator new andoperator new[] and
|
||||
the global [*deallocation functions*](#def:deallocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator delete andoperator delete[][.](#dynamic.general-1.sentence-2)
|
||||
|
||||
[*Note [1](#dynamic.general-note-1)*:
|
||||
|
||||
The non-allocating forms described in [[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms") do not perform allocation or deallocation[.](#dynamic.general-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#dynamic.general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4381)
|
||||
|
||||
The library provides default definitions for the global allocation and
|
||||
deallocation functions[.](#dynamic.general-2.sentence-1)
|
||||
|
||||
Some global allocation and deallocation
|
||||
functions are replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5 Replaceable function definitions"))[.](#dynamic.general-2.sentence-2)
|
||||
|
||||
The following allocation and deallocation functions ([[support.dynamic]](support.dynamic "17.6 Dynamic memory management"))
|
||||
are implicitly declared in global scope in each translation unit of a
|
||||
program[.](#dynamic.general-2.sentence-3)
|
||||
|
||||
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 namesoperator new,operator new[],operator delete, andoperator delete[][.](#dynamic.general-2.sentence-4)
|
||||
|
||||
[*Note [2](#dynamic.general-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[.](#dynamic.general-2.sentence-5)
|
||||
|
||||
Thus, a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"),[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]"), or function call that refers to one of
|
||||
these functions without importing or including the header [<new>](support.dynamic.general#header:%3cnew%3e "17.6.1 General [support.dynamic.general]") or importing a C++ library module ([[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
is well-formed[.](#dynamic.general-2.sentence-6)
|
||||
|
||||
However, referring to std or std::size_t or std::align_val_t is ill-formed unless
|
||||
a standard library declaration ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"), [[new.syn]](new.syn "17.6.2 Header <new> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
of that name precedes ([[basic.lookup.general]](basic.lookup.general "6.5.1 General")) the use of that name[.](#dynamic.general-2.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Allocation and/or
|
||||
deallocation functions may also be declared and defined for any
|
||||
class ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#dynamic.general-2.sentence-8)
|
||||
|
||||
[3](#dynamic.general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4433)
|
||||
|
||||
If the behavior of an allocation or deallocation function
|
||||
does not satisfy the semantic constraints
|
||||
specified in [[basic.stc.dynamic.allocation]](#dynamic.allocation "6.8.6.5.2 Allocation functions") and [[basic.stc.dynamic.deallocation]](#dynamic.deallocation "6.8.6.5.3 Deallocation functions"),
|
||||
the behavior is undefined[.](#dynamic.general-3.sentence-1)
|
||||
|
||||
#### [6.8.6.5.2](#dynamic.allocation) Allocation functions [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation)
|
||||
|
||||
[1](#dynamic.allocation-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4444)
|
||||
|
||||
An allocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#dynamic.allocation-1.sentence-1)
|
||||
|
||||
The return type shall be void*[.](#dynamic.allocation-1.sentence-2)
|
||||
|
||||
The first
|
||||
parameter shall have type std::size_t ([[support.types]](support.types "17.2 Common definitions"))[.](#dynamic.allocation-1.sentence-3)
|
||||
|
||||
The
|
||||
first parameter shall not have an associated default
|
||||
argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#dynamic.allocation-1.sentence-4)
|
||||
|
||||
The value of the first parameter
|
||||
is interpreted as the requested size of the allocation[.](#dynamic.allocation-1.sentence-5)
|
||||
|
||||
An allocation
|
||||
function can be a function template[.](#dynamic.allocation-1.sentence-6)
|
||||
|
||||
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)[.](#dynamic.allocation-1.sentence-7)
|
||||
|
||||
Allocation function templates shall have two or more parameters[.](#dynamic.allocation-1.sentence-8)
|
||||
|
||||
[2](#dynamic.allocation-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4458)
|
||||
|
||||
An allocation function attempts to allocate the requested amount of
|
||||
storage[.](#dynamic.allocation-2.sentence-1)
|
||||
|
||||
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[.](#dynamic.allocation-2.sentence-2)
|
||||
|
||||
The order,
|
||||
contiguity, and initial value of storage allocated by successive calls
|
||||
to an allocation function are unspecified[.](#dynamic.allocation-2.sentence-3)
|
||||
|
||||
Even if the size of the space
|
||||
requested is zero, the request can fail[.](#dynamic.allocation-2.sentence-4)
|
||||
|
||||
If the request succeeds, the
|
||||
value returned by a replaceable allocation function
|
||||
is a non-null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types"))p0 different from any previously returned value p1,
|
||||
unless that value p1 was subsequently passed to a
|
||||
replaceable deallocation function[.](#dynamic.allocation-2.sentence-5)
|
||||
|
||||
Furthermore, for the library allocation functions
|
||||
in [[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms") and [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"),p0 represents the address of a block of storage disjoint from the storage
|
||||
for any other object accessible to the caller[.](#dynamic.allocation-2.sentence-6)
|
||||
|
||||
The effect of indirecting through a pointer
|
||||
returned from a request for zero size is undefined[.](#dynamic.allocation-2.sentence-7)[23](#footnote-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.")
|
||||
|
||||
[3](#dynamic.allocation-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4487)
|
||||
|
||||
For an allocation function other than
|
||||
a reserved placement allocation function ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms")),
|
||||
the pointer returned on a successful call
|
||||
shall represent the address of storage that is aligned as follows:
|
||||
|
||||
- [(3.1)](#dynamic.allocation-3.1)
|
||||
|
||||
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[.](#dynamic.allocation-3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#dynamic.allocation-3.2)
|
||||
|
||||
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]](basic.align "6.8.3 Alignment")) and
|
||||
is no larger than the requested size[.](#dynamic.allocation-3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#dynamic.allocation-3.3)
|
||||
|
||||
Otherwise, the storage is aligned for any object that
|
||||
does not have new-extended alignment and is of the requested size[.](#dynamic.allocation-3.3.sentence-1)
|
||||
|
||||
[4](#dynamic.allocation-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4508)
|
||||
|
||||
An allocation function that fails to allocate storage can invoke the
|
||||
currently installed new-handler function ([[new.handler]](new.handler "17.6.4.3 Type new_handler")), if any[.](#dynamic.allocation-4.sentence-1)
|
||||
|
||||
[*Note [1](#dynamic.allocation-note-1)*:
|
||||
|
||||
A program-supplied allocation function can obtain the
|
||||
currently installed new_handler using thestd::get_new_handler function ([[get.new.handler]](get.new.handler "17.6.4.5 get_new_handler"))[.](#dynamic.allocation-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An allocation function that has a non-throwing
|
||||
exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||||
indicates failure by returning
|
||||
a null pointer value[.](#dynamic.allocation-4.sentence-3)
|
||||
|
||||
Any other allocation function
|
||||
never returns a null pointer value and
|
||||
indicates failure only by throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")) of a type
|
||||
that would match a handler ([[except.handle]](except.handle "14.4 Handling an exception")) of typestd::bad_alloc ([[bad.alloc]](bad.alloc "17.6.4.1 Class bad_alloc"))[.](#dynamic.allocation-4.sentence-4)
|
||||
|
||||
[5](#dynamic.allocation-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4527)
|
||||
|
||||
A global allocation function is only called as the result of a [new
|
||||
expression](expr.new "7.6.2.8 New [expr.new]"), or called directly using the [function call](expr.call "7.6.1.3 Function call [expr.call]") syntax, or called indirectly to allocate storage for
|
||||
a coroutine state ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
|
||||
or called indirectly through calls to the
|
||||
functions in the C++ standard library[.](#dynamic.allocation-5.sentence-1)
|
||||
|
||||
[*Note [2](#dynamic.allocation-note-2)*:
|
||||
|
||||
In particular, a
|
||||
global allocation function is not called to allocate storage
|
||||
for objects with static storage duration ([[basic.stc.static]](#static "6.8.6.2 Static storage duration")),
|
||||
for objects or references with thread storage duration ([[basic.stc.thread]](#thread "6.8.6.3 Thread storage duration")),
|
||||
for objects of type std::type_info ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
for an object of type std::contracts::contract_violation when a contract violation occurs ([[basic.contract.eval]](basic.contract.eval "6.11.2 Evaluation")), or
|
||||
for an exception object ([[except.throw]](except.throw "14.2 Throwing an exception"))[.](#dynamic.allocation-5.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[23)](#footnote-23)[23)](#footnoteref-23)
|
||||
|
||||
The intent is
|
||||
to have operator new() implementable by
|
||||
calling std::malloc() or std::calloc(), so the rules are
|
||||
substantially the same[.](#footnote-23.sentence-1)
|
||||
|
||||
C++ differs from C in requiring a zero request
|
||||
to return a non-null pointer[.](#footnote-23.sentence-2)
|
||||
|
||||
#### [6.8.6.5.3](#dynamic.deallocation) Deallocation functions [[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation)
|
||||
|
||||
[1](#dynamic.deallocation-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4547)
|
||||
|
||||
A deallocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#dynamic.deallocation-1.sentence-1)
|
||||
|
||||
[2](#dynamic.deallocation-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4552)
|
||||
|
||||
A deallocation function
|
||||
is a [*destroying operator delete*](#def:operator_delete,destroying "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") if it has at least two parameters
|
||||
and its second parameter
|
||||
is of type std::destroying_delete_t[.](#dynamic.deallocation-2.sentence-1)
|
||||
|
||||
A destroying operator delete
|
||||
shall be a class member function named operator delete[.](#dynamic.deallocation-2.sentence-2)
|
||||
|
||||
[*Note [1](#dynamic.deallocation-note-1)*:
|
||||
|
||||
Array deletion cannot use a destroying operator delete[.](#dynamic.deallocation-2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#dynamic.deallocation-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4564)
|
||||
|
||||
Each deallocation function shall return void[.](#dynamic.deallocation-3.sentence-1)
|
||||
|
||||
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*[.](#dynamic.deallocation-3.sentence-2)
|
||||
|
||||
A deallocation function may have more
|
||||
than one parameter[.](#dynamic.deallocation-3.sentence-3)
|
||||
|
||||
A [*usual deallocation function*](#def:usual_deallocation_function "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") is a deallocation function
|
||||
whose parameters after the first are
|
||||
|
||||
- [(3.1)](#dynamic.deallocation-3.1)
|
||||
|
||||
optionally, a parameter of type std::destroying_delete_t, then
|
||||
|
||||
- [(3.2)](#dynamic.deallocation-3.2)
|
||||
|
||||
optionally, a parameter of type std::size_t,[24](#footnote-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]).") then
|
||||
|
||||
- [(3.3)](#dynamic.deallocation-3.3)
|
||||
|
||||
optionally, a parameter of type std::align_val_t[.](#dynamic.deallocation-3.sentence-4)
|
||||
|
||||
A destroying operator delete shall be a usual deallocation function[.](#dynamic.deallocation-3.sentence-5)
|
||||
|
||||
A deallocation function may be an instance of a function
|
||||
template[.](#dynamic.deallocation-3.sentence-6)
|
||||
|
||||
Neither the first parameter nor the return type shall depend
|
||||
on a template parameter[.](#dynamic.deallocation-3.sentence-7)
|
||||
|
||||
A deallocation
|
||||
function template shall have two or more function parameters[.](#dynamic.deallocation-3.sentence-8)
|
||||
|
||||
A template
|
||||
instance is never a usual deallocation function, regardless of its
|
||||
signature[.](#dynamic.deallocation-3.sentence-9)
|
||||
|
||||
[4](#dynamic.deallocation-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4600)
|
||||
|
||||
If a deallocation function terminates by throwing an exception, the behavior is undefined[.](#dynamic.deallocation-4.sentence-1)
|
||||
|
||||
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[.](#dynamic.deallocation-4.sentence-2)
|
||||
|
||||
[5](#dynamic.deallocation-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4606)
|
||||
|
||||
If the argument given to a deallocation function in the standard library
|
||||
is a pointer that is not the null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")), the
|
||||
deallocation function shall deallocate the storage referenced by the
|
||||
pointer, ending the duration of the region of storage[.](#dynamic.deallocation-5.sentence-1)
|
||||
|
||||
[24)](#footnote-24)[24)](#footnoteref-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]](diff.cpp11.basic "C.5.3 [basic]: basics"))[.](#footnote-24.sentence-1)
|
||||
40
cppdraft/basic/stc/auto.md
Normal file
40
cppdraft/basic/stc/auto.md
Normal file
@@ -0,0 +1,40 @@
|
||||
[basic.stc.auto]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.auto)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#auto)
|
||||
|
||||
#### 6.8.6.4 Automatic storage duration [basic.stc.auto]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4337)
|
||||
|
||||
Variables that belong to a block scope and are
|
||||
not explicitly declared static, thread_local, or extern have[*automatic storage duration*](#def:storage_duration,automatic "6.8.6.4 Automatic storage duration [basic.stc.auto]")[.](#1.sentence-1)
|
||||
|
||||
The storage
|
||||
for such variables lasts until the block in which they are created exits[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
These variables are initialized and destroyed as described in [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Variables that belong to a parameter scope also have automatic storage duration[.](#1.sentence-4)
|
||||
|
||||
The storage for a function parameter lasts until
|
||||
immediately after its destruction ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#1.sentence-5)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4350)
|
||||
|
||||
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]](class.copy.elision "11.9.6 Copy/move elision")[.](#2.sentence-1)
|
||||
326
cppdraft/basic/stc/dynamic.md
Normal file
326
cppdraft/basic/stc/dynamic.md
Normal file
@@ -0,0 +1,326 @@
|
||||
[basic.stc.dynamic]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.dynamic)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#dynamic)
|
||||
|
||||
#### 6.8.6.5 Dynamic storage duration [basic.stc.dynamic]
|
||||
|
||||
#### [6.8.6.5.1](#general) General [[basic.stc.dynamic.general]](basic.stc.dynamic.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4362)
|
||||
|
||||
Objects can be created dynamically during [program
|
||||
execution](intro.execution "6.10.1 Sequential execution [intro.execution]"), using[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), and destroyed using[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]")*s* ([[expr.delete]](expr.delete "7.6.2.9 Delete"))[.](#general-1.sentence-1)
|
||||
|
||||
A C++ implementation
|
||||
provides access to, and management of, dynamic storage via
|
||||
the global [*allocation functions*](#def:allocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator new andoperator new[] and
|
||||
the global [*deallocation functions*](#def:deallocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator delete andoperator delete[][.](#general-1.sentence-2)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
The non-allocating forms described in [[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms") do not perform allocation or deallocation[.](#general-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4381)
|
||||
|
||||
The library provides default definitions for the global allocation and
|
||||
deallocation functions[.](#general-2.sentence-1)
|
||||
|
||||
Some global allocation and deallocation
|
||||
functions are replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5 Replaceable function definitions"))[.](#general-2.sentence-2)
|
||||
|
||||
The following allocation and deallocation functions ([[support.dynamic]](support.dynamic "17.6 Dynamic memory management"))
|
||||
are implicitly declared in global scope in each translation unit of a
|
||||
program[.](#general-2.sentence-3)
|
||||
|
||||
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 namesoperator new,operator new[],operator delete, andoperator delete[][.](#general-2.sentence-4)
|
||||
|
||||
[*Note [2](#general-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[.](#general-2.sentence-5)
|
||||
|
||||
Thus, a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"),[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]"), or function call that refers to one of
|
||||
these functions without importing or including the header [<new>](support.dynamic.general#header:%3cnew%3e "17.6.1 General [support.dynamic.general]") or importing a C++ library module ([[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
is well-formed[.](#general-2.sentence-6)
|
||||
|
||||
However, referring to std or std::size_t or std::align_val_t is ill-formed unless
|
||||
a standard library declaration ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"), [[new.syn]](new.syn "17.6.2 Header <new> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
of that name precedes ([[basic.lookup.general]](basic.lookup.general "6.5.1 General")) the use of that name[.](#general-2.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Allocation and/or
|
||||
deallocation functions may also be declared and defined for any
|
||||
class ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#general-2.sentence-8)
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4433)
|
||||
|
||||
If the behavior of an allocation or deallocation function
|
||||
does not satisfy the semantic constraints
|
||||
specified in [[basic.stc.dynamic.allocation]](#allocation "6.8.6.5.2 Allocation functions") and [[basic.stc.dynamic.deallocation]](#deallocation "6.8.6.5.3 Deallocation functions"),
|
||||
the behavior is undefined[.](#general-3.sentence-1)
|
||||
|
||||
#### [6.8.6.5.2](#allocation) Allocation functions [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation)
|
||||
|
||||
[1](#allocation-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4444)
|
||||
|
||||
An allocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#allocation-1.sentence-1)
|
||||
|
||||
The return type shall be void*[.](#allocation-1.sentence-2)
|
||||
|
||||
The first
|
||||
parameter shall have type std::size_t ([[support.types]](support.types "17.2 Common definitions"))[.](#allocation-1.sentence-3)
|
||||
|
||||
The
|
||||
first parameter shall not have an associated default
|
||||
argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#allocation-1.sentence-4)
|
||||
|
||||
The value of the first parameter
|
||||
is interpreted as the requested size of the allocation[.](#allocation-1.sentence-5)
|
||||
|
||||
An allocation
|
||||
function can be a function template[.](#allocation-1.sentence-6)
|
||||
|
||||
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-1.sentence-7)
|
||||
|
||||
Allocation function templates shall have two or more parameters[.](#allocation-1.sentence-8)
|
||||
|
||||
[2](#allocation-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4458)
|
||||
|
||||
An allocation function attempts to allocate the requested amount of
|
||||
storage[.](#allocation-2.sentence-1)
|
||||
|
||||
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[.](#allocation-2.sentence-2)
|
||||
|
||||
The order,
|
||||
contiguity, and initial value of storage allocated by successive calls
|
||||
to an allocation function are unspecified[.](#allocation-2.sentence-3)
|
||||
|
||||
Even if the size of the space
|
||||
requested is zero, the request can fail[.](#allocation-2.sentence-4)
|
||||
|
||||
If the request succeeds, the
|
||||
value returned by a replaceable allocation function
|
||||
is a non-null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types"))p0 different from any previously returned value p1,
|
||||
unless that value p1 was subsequently passed to a
|
||||
replaceable deallocation function[.](#allocation-2.sentence-5)
|
||||
|
||||
Furthermore, for the library allocation functions
|
||||
in [[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms") and [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"),p0 represents the address of a block of storage disjoint from the storage
|
||||
for any other object accessible to the caller[.](#allocation-2.sentence-6)
|
||||
|
||||
The effect of indirecting through a pointer
|
||||
returned from a request for zero size is undefined[.](#allocation-2.sentence-7)[23](#footnote-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.")
|
||||
|
||||
[3](#allocation-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4487)
|
||||
|
||||
For an allocation function other than
|
||||
a reserved placement allocation function ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms")),
|
||||
the pointer returned on a successful call
|
||||
shall represent the address of storage that is aligned as follows:
|
||||
|
||||
- [(3.1)](#allocation-3.1)
|
||||
|
||||
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[.](#allocation-3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#allocation-3.2)
|
||||
|
||||
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]](basic.align "6.8.3 Alignment")) and
|
||||
is no larger than the requested size[.](#allocation-3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#allocation-3.3)
|
||||
|
||||
Otherwise, the storage is aligned for any object that
|
||||
does not have new-extended alignment and is of the requested size[.](#allocation-3.3.sentence-1)
|
||||
|
||||
[4](#allocation-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4508)
|
||||
|
||||
An allocation function that fails to allocate storage can invoke the
|
||||
currently installed new-handler function ([[new.handler]](new.handler "17.6.4.3 Type new_handler")), if any[.](#allocation-4.sentence-1)
|
||||
|
||||
[*Note [1](#allocation-note-1)*:
|
||||
|
||||
A program-supplied allocation function can obtain the
|
||||
currently installed new_handler using thestd::get_new_handler function ([[get.new.handler]](get.new.handler "17.6.4.5 get_new_handler"))[.](#allocation-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An allocation function that has a non-throwing
|
||||
exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||||
indicates failure by returning
|
||||
a null pointer value[.](#allocation-4.sentence-3)
|
||||
|
||||
Any other allocation function
|
||||
never returns a null pointer value and
|
||||
indicates failure only by throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")) of a type
|
||||
that would match a handler ([[except.handle]](except.handle "14.4 Handling an exception")) of typestd::bad_alloc ([[bad.alloc]](bad.alloc "17.6.4.1 Class bad_alloc"))[.](#allocation-4.sentence-4)
|
||||
|
||||
[5](#allocation-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4527)
|
||||
|
||||
A global allocation function is only called as the result of a [new
|
||||
expression](expr.new "7.6.2.8 New [expr.new]"), or called directly using the [function call](expr.call "7.6.1.3 Function call [expr.call]") syntax, or called indirectly to allocate storage for
|
||||
a coroutine state ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
|
||||
or called indirectly through calls to the
|
||||
functions in the C++ standard library[.](#allocation-5.sentence-1)
|
||||
|
||||
[*Note [2](#allocation-note-2)*:
|
||||
|
||||
In particular, a
|
||||
global allocation function is not called to allocate storage
|
||||
for objects with static storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")),
|
||||
for objects or references with thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")),
|
||||
for objects of type std::type_info ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
for an object of type std::contracts::contract_violation when a contract violation occurs ([[basic.contract.eval]](basic.contract.eval "6.11.2 Evaluation")), or
|
||||
for an exception object ([[except.throw]](except.throw "14.2 Throwing an exception"))[.](#allocation-5.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[23)](#footnote-23)[23)](#footnoteref-23)
|
||||
|
||||
The intent is
|
||||
to have operator new() implementable by
|
||||
calling std::malloc() or std::calloc(), so the rules are
|
||||
substantially the same[.](#footnote-23.sentence-1)
|
||||
|
||||
C++ differs from C in requiring a zero request
|
||||
to return a non-null pointer[.](#footnote-23.sentence-2)
|
||||
|
||||
#### [6.8.6.5.3](#deallocation) Deallocation functions [[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation)
|
||||
|
||||
[1](#deallocation-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4547)
|
||||
|
||||
A deallocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#deallocation-1.sentence-1)
|
||||
|
||||
[2](#deallocation-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4552)
|
||||
|
||||
A deallocation function
|
||||
is a [*destroying operator delete*](#def:operator_delete,destroying "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") if it has at least two parameters
|
||||
and its second parameter
|
||||
is of type std::destroying_delete_t[.](#deallocation-2.sentence-1)
|
||||
|
||||
A destroying operator delete
|
||||
shall be a class member function named operator delete[.](#deallocation-2.sentence-2)
|
||||
|
||||
[*Note [1](#deallocation-note-1)*:
|
||||
|
||||
Array deletion cannot use a destroying operator delete[.](#deallocation-2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#deallocation-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4564)
|
||||
|
||||
Each deallocation function shall return void[.](#deallocation-3.sentence-1)
|
||||
|
||||
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*[.](#deallocation-3.sentence-2)
|
||||
|
||||
A deallocation function may have more
|
||||
than one parameter[.](#deallocation-3.sentence-3)
|
||||
|
||||
A [*usual deallocation function*](#def:usual_deallocation_function "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") is a deallocation function
|
||||
whose parameters after the first are
|
||||
|
||||
- [(3.1)](#deallocation-3.1)
|
||||
|
||||
optionally, a parameter of type std::destroying_delete_t, then
|
||||
|
||||
- [(3.2)](#deallocation-3.2)
|
||||
|
||||
optionally, a parameter of type std::size_t,[24](#footnote-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]).") then
|
||||
|
||||
- [(3.3)](#deallocation-3.3)
|
||||
|
||||
optionally, a parameter of type std::align_val_t[.](#deallocation-3.sentence-4)
|
||||
|
||||
A destroying operator delete shall be a usual deallocation function[.](#deallocation-3.sentence-5)
|
||||
|
||||
A deallocation function may be an instance of a function
|
||||
template[.](#deallocation-3.sentence-6)
|
||||
|
||||
Neither the first parameter nor the return type shall depend
|
||||
on a template parameter[.](#deallocation-3.sentence-7)
|
||||
|
||||
A deallocation
|
||||
function template shall have two or more function parameters[.](#deallocation-3.sentence-8)
|
||||
|
||||
A template
|
||||
instance is never a usual deallocation function, regardless of its
|
||||
signature[.](#deallocation-3.sentence-9)
|
||||
|
||||
[4](#deallocation-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4600)
|
||||
|
||||
If a deallocation function terminates by throwing an exception, the behavior is undefined[.](#deallocation-4.sentence-1)
|
||||
|
||||
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[.](#deallocation-4.sentence-2)
|
||||
|
||||
[5](#deallocation-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4606)
|
||||
|
||||
If the argument given to a deallocation function in the standard library
|
||||
is a pointer that is not the null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")), the
|
||||
deallocation function shall deallocate the storage referenced by the
|
||||
pointer, ending the duration of the region of storage[.](#deallocation-5.sentence-1)
|
||||
|
||||
[24)](#footnote-24)[24)](#footnoteref-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]](diff.cpp11.basic "C.5.3 [basic]: basics"))[.](#footnote-24.sentence-1)
|
||||
155
cppdraft/basic/stc/dynamic/allocation.md
Normal file
155
cppdraft/basic/stc/dynamic/allocation.md
Normal file
@@ -0,0 +1,155 @@
|
||||
[basic.stc.dynamic.allocation]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.dynamic.allocation)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#dynamic.allocation)
|
||||
|
||||
#### 6.8.6.5 Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic#allocation)
|
||||
|
||||
#### 6.8.6.5.2 Allocation functions [basic.stc.dynamic.allocation]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4444)
|
||||
|
||||
An allocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#1.sentence-1)
|
||||
|
||||
The return type shall be void*[.](#1.sentence-2)
|
||||
|
||||
The first
|
||||
parameter shall have type std::size_t ([[support.types]](support.types "17.2 Common definitions"))[.](#1.sentence-3)
|
||||
|
||||
The
|
||||
first parameter shall not have an associated default
|
||||
argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))[.](#1.sentence-4)
|
||||
|
||||
The value of the first parameter
|
||||
is interpreted as the requested size of the allocation[.](#1.sentence-5)
|
||||
|
||||
An allocation
|
||||
function can be a function template[.](#1.sentence-6)
|
||||
|
||||
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)[.](#1.sentence-7)
|
||||
|
||||
Allocation function templates shall have two or more parameters[.](#1.sentence-8)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4458)
|
||||
|
||||
An allocation function attempts to allocate the requested amount of
|
||||
storage[.](#2.sentence-1)
|
||||
|
||||
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[.](#2.sentence-2)
|
||||
|
||||
The order,
|
||||
contiguity, and initial value of storage allocated by successive calls
|
||||
to an allocation function are unspecified[.](#2.sentence-3)
|
||||
|
||||
Even if the size of the space
|
||||
requested is zero, the request can fail[.](#2.sentence-4)
|
||||
|
||||
If the request succeeds, the
|
||||
value returned by a replaceable allocation function
|
||||
is a non-null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types"))p0 different from any previously returned value p1,
|
||||
unless that value p1 was subsequently passed to a
|
||||
replaceable deallocation function[.](#2.sentence-5)
|
||||
|
||||
Furthermore, for the library allocation functions
|
||||
in [[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms") and [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"),p0 represents the address of a block of storage disjoint from the storage
|
||||
for any other object accessible to the caller[.](#2.sentence-6)
|
||||
|
||||
The effect of indirecting through a pointer
|
||||
returned from a request for zero size is undefined[.](#2.sentence-7)[23](#footnote-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.")
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4487)
|
||||
|
||||
For an allocation function other than
|
||||
a reserved placement allocation function ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms")),
|
||||
the pointer returned on a successful call
|
||||
shall represent the address of storage that is aligned as follows:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
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[.](#3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
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]](basic.align "6.8.3 Alignment")) and
|
||||
is no larger than the requested size[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
Otherwise, the storage is aligned for any object that
|
||||
does not have new-extended alignment and is of the requested size[.](#3.3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4508)
|
||||
|
||||
An allocation function that fails to allocate storage can invoke the
|
||||
currently installed new-handler function ([[new.handler]](new.handler "17.6.4.3 Type new_handler")), if any[.](#4.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A program-supplied allocation function can obtain the
|
||||
currently installed new_handler using thestd::get_new_handler function ([[get.new.handler]](get.new.handler "17.6.4.5 get_new_handler"))[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An allocation function that has a non-throwing
|
||||
exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||||
indicates failure by returning
|
||||
a null pointer value[.](#4.sentence-3)
|
||||
|
||||
Any other allocation function
|
||||
never returns a null pointer value and
|
||||
indicates failure only by throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")) of a type
|
||||
that would match a handler ([[except.handle]](except.handle "14.4 Handling an exception")) of typestd::bad_alloc ([[bad.alloc]](bad.alloc "17.6.4.1 Class bad_alloc"))[.](#4.sentence-4)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4527)
|
||||
|
||||
A global allocation function is only called as the result of a [new
|
||||
expression](expr.new "7.6.2.8 New [expr.new]"), or called directly using the [function call](expr.call "7.6.1.3 Function call [expr.call]") syntax, or called indirectly to allocate storage for
|
||||
a coroutine state ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
|
||||
or called indirectly through calls to the
|
||||
functions in the C++ standard library[.](#5.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
In particular, a
|
||||
global allocation function is not called to allocate storage
|
||||
for objects with static storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2 Static storage duration")),
|
||||
for objects or references with thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration")),
|
||||
for objects of type std::type_info ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
for an object of type std::contracts::contract_violation when a contract violation occurs ([[basic.contract.eval]](basic.contract.eval "6.11.2 Evaluation")), or
|
||||
for an exception object ([[except.throw]](except.throw "14.2 Throwing an exception"))[.](#5.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[23)](#footnote-23)[23)](#footnoteref-23)
|
||||
|
||||
The intent is
|
||||
to have operator new() implementable by
|
||||
calling std::malloc() or std::calloc(), so the rules are
|
||||
substantially the same[.](#footnote-23.sentence-1)
|
||||
|
||||
C++ differs from C in requiring a zero request
|
||||
to return a non-null pointer[.](#footnote-23.sentence-2)
|
||||
106
cppdraft/basic/stc/dynamic/deallocation.md
Normal file
106
cppdraft/basic/stc/dynamic/deallocation.md
Normal file
@@ -0,0 +1,106 @@
|
||||
[basic.stc.dynamic.deallocation]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.dynamic.deallocation)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#dynamic.deallocation)
|
||||
|
||||
#### 6.8.6.5 Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic#deallocation)
|
||||
|
||||
#### 6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4547)
|
||||
|
||||
A deallocation function that is not a class member function
|
||||
shall belong to the global scope and not have a name with internal linkage[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4552)
|
||||
|
||||
A deallocation function
|
||||
is a [*destroying operator delete*](#def:operator_delete,destroying "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") if it has at least two parameters
|
||||
and its second parameter
|
||||
is of type std::destroying_delete_t[.](#2.sentence-1)
|
||||
|
||||
A destroying operator delete
|
||||
shall be a class member function named operator delete[.](#2.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Array deletion cannot use a destroying operator delete[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4564)
|
||||
|
||||
Each deallocation function shall return void[.](#3.sentence-1)
|
||||
|
||||
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*[.](#3.sentence-2)
|
||||
|
||||
A deallocation function may have more
|
||||
than one parameter[.](#3.sentence-3)
|
||||
|
||||
A [*usual deallocation function*](#def:usual_deallocation_function "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") is a deallocation function
|
||||
whose parameters after the first are
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
optionally, a parameter of type std::destroying_delete_t, then
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
optionally, a parameter of type std::size_t,[24](#footnote-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]).") then
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
optionally, a parameter of type std::align_val_t[.](#3.sentence-4)
|
||||
|
||||
A destroying operator delete shall be a usual deallocation function[.](#3.sentence-5)
|
||||
|
||||
A deallocation function may be an instance of a function
|
||||
template[.](#3.sentence-6)
|
||||
|
||||
Neither the first parameter nor the return type shall depend
|
||||
on a template parameter[.](#3.sentence-7)
|
||||
|
||||
A deallocation
|
||||
function template shall have two or more function parameters[.](#3.sentence-8)
|
||||
|
||||
A template
|
||||
instance is never a usual deallocation function, regardless of its
|
||||
signature[.](#3.sentence-9)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4600)
|
||||
|
||||
If a deallocation function terminates by throwing an exception, the behavior is undefined[.](#4.sentence-1)
|
||||
|
||||
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[.](#4.sentence-2)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4606)
|
||||
|
||||
If the argument given to a deallocation function in the standard library
|
||||
is a pointer that is not the null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")), the
|
||||
deallocation function shall deallocate the storage referenced by the
|
||||
pointer, ending the duration of the region of storage[.](#5.sentence-1)
|
||||
|
||||
[24)](#footnote-24)[24)](#footnoteref-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]](diff.cpp11.basic "C.5.3 [basic]: basics"))[.](#footnote-24.sentence-1)
|
||||
83
cppdraft/basic/stc/dynamic/general.md
Normal file
83
cppdraft/basic/stc/dynamic/general.md
Normal file
@@ -0,0 +1,83 @@
|
||||
[basic.stc.dynamic.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.dynamic.general)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#dynamic.general)
|
||||
|
||||
#### 6.8.6.5 Dynamic storage duration [[basic.stc.dynamic]](basic.stc.dynamic#general)
|
||||
|
||||
#### 6.8.6.5.1 General [basic.stc.dynamic.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4362)
|
||||
|
||||
Objects can be created dynamically during [program
|
||||
execution](intro.execution "6.10.1 Sequential execution [intro.execution]"), using[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), and destroyed using[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]")*s* ([[expr.delete]](expr.delete "7.6.2.9 Delete"))[.](#1.sentence-1)
|
||||
|
||||
A C++ implementation
|
||||
provides access to, and management of, dynamic storage via
|
||||
the global [*allocation functions*](#def:allocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator new andoperator new[] and
|
||||
the global [*deallocation functions*](#def:deallocation_function "6.8.6.5.1 General [basic.stc.dynamic.general]")operator delete andoperator delete[][.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The non-allocating forms described in [[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms") do not perform allocation or deallocation[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4381)
|
||||
|
||||
The library provides default definitions for the global allocation and
|
||||
deallocation functions[.](#2.sentence-1)
|
||||
|
||||
Some global allocation and deallocation
|
||||
functions are replaceable ([[dcl.fct.def.replace]](dcl.fct.def.replace#term.replaceable.function "9.6.5 Replaceable function definitions"))[.](#2.sentence-2)
|
||||
|
||||
The following allocation and deallocation functions ([[support.dynamic]](support.dynamic "17.6 Dynamic memory management"))
|
||||
are implicitly declared in global scope in each translation unit of a
|
||||
program[.](#2.sentence-3)
|
||||
|
||||
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 namesoperator new,operator new[],operator delete, andoperator delete[][.](#2.sentence-4)
|
||||
|
||||
[*Note [2](#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[.](#2.sentence-5)
|
||||
|
||||
Thus, a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"),[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]"), or function call that refers to one of
|
||||
these functions without importing or including the header [<new>](support.dynamic.general#header:%3cnew%3e "17.6.1 General [support.dynamic.general]") or importing a C++ library module ([[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
is well-formed[.](#2.sentence-6)
|
||||
|
||||
However, referring to std or std::size_t or std::align_val_t is ill-formed unless
|
||||
a standard library declaration ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"), [[new.syn]](new.syn "17.6.2 Header <new> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
of that name precedes ([[basic.lookup.general]](basic.lookup.general "6.5.1 General")) the use of that name[.](#2.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Allocation and/or
|
||||
deallocation functions may also be declared and defined for any
|
||||
class ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#2.sentence-8)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4433)
|
||||
|
||||
If the behavior of an allocation or deallocation function
|
||||
does not satisfy the semantic constraints
|
||||
specified in [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions") and [[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions"),
|
||||
the behavior is undefined[.](#3.sentence-1)
|
||||
68
cppdraft/basic/stc/general.md
Normal file
68
cppdraft/basic/stc/general.md
Normal file
@@ -0,0 +1,68 @@
|
||||
[basic.stc.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.general)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#general)
|
||||
|
||||
#### 6.8.6.1 General [basic.stc.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4244)
|
||||
|
||||
The [*storage duration*](#def:storage_duration "6.8.6.1 General [basic.stc.general]") is the property of an object that defines the minimum
|
||||
potential lifetime of the storage containing the object[.](#1.sentence-1)
|
||||
|
||||
The storage
|
||||
duration is determined by the construct used to create the object and is
|
||||
one of the following:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
static storage duration
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
thread storage duration
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
automatic storage duration
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
dynamic storage duration
|
||||
|
||||
[*Note [1](#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]](basic.compound "6.9.4 Compound types"))[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4261)
|
||||
|
||||
Static, thread, and automatic storage durations are associated with objects
|
||||
introduced by declarations ([[basic.def]](basic.def "6.2 Declarations and definitions")) and
|
||||
with temporary objects ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#2.sentence-1)
|
||||
|
||||
The dynamic storage duration
|
||||
is associated with objects created by a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")) or
|
||||
with implicitly created objects ([[intro.object]](intro.object "6.8.2 Object model"))[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4274)
|
||||
|
||||
The storage duration categories apply to references as well[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4277)
|
||||
|
||||
The storage duration of subobjects and reference members
|
||||
is that of their complete object ([[intro.object]](intro.object "6.8.2 Object model"))[.](#4.sentence-1)
|
||||
55
cppdraft/basic/stc/static.md
Normal file
55
cppdraft/basic/stc/static.md
Normal file
@@ -0,0 +1,55 @@
|
||||
[basic.stc.static]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.static)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#static)
|
||||
|
||||
#### 6.8.6.2 Static storage duration [basic.stc.static]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4285)
|
||||
|
||||
All variables which
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
do not have thread storage duration and
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
belong to a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace scope")) or
|
||||
are first declared with
|
||||
the static or extern keywords ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers"))
|
||||
|
||||
have [*static storage duration*](#def:storage_duration,static "6.8.6.2 Static storage duration [basic.stc.static]")[.](#1.sentence-1)
|
||||
|
||||
The storage for these entities lasts for the duration of the
|
||||
program ([[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.term]](basic.start.term "6.10.3.4 Termination"))[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4299)
|
||||
|
||||
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]](class.copy.elision "11.9.6 Copy/move elision")[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4305)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The keyword static can be used to declare
|
||||
a block variable ([[basic.scope.block]](basic.scope.block "6.4.3 Block scope")) with static storage duration;[[stmt.dcl]](stmt.dcl "8.10 Declaration statement") and [[basic.start.term]](basic.start.term "6.10.3.4 Termination") describe the
|
||||
initialization and destruction of such variables[.](#3.sentence-1)
|
||||
|
||||
The keyword static applied to
|
||||
a class data member in a class definition
|
||||
gives the data member static storage duration ([[class.static.data]](class.static.data "11.4.9.3 Static data members"))[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
33
cppdraft/basic/stc/thread.md
Normal file
33
cppdraft/basic/stc/thread.md
Normal file
@@ -0,0 +1,33 @@
|
||||
[basic.stc.thread]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#basic.stc.thread)
|
||||
|
||||
### 6.8.6 Storage duration [[basic.stc]](basic.stc#thread)
|
||||
|
||||
#### 6.8.6.3 Thread storage duration [basic.stc.thread]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4320)
|
||||
|
||||
All variables declared with the thread_local keyword have[*thread storage duration*](#def:storage_duration,thread "6.8.6.3 Thread storage duration [basic.stc.thread]")[.](#1.sentence-1)
|
||||
|
||||
The storage for these entities lasts for the duration of
|
||||
the thread in which they are created[.](#1.sentence-2)
|
||||
|
||||
There is a distinct object or reference
|
||||
per thread, and use of the declared name refers to the entity associated with
|
||||
the current thread[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4328)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A variable with thread storage duration is initialized as specified
|
||||
in [[basic.start.static]](basic.start.static "6.10.3.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement") and, if constructed, is destroyed on thread exit ([[basic.start.term]](basic.start.term "6.10.3.4 Termination"))[.](#2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
2517
cppdraft/basic/string.md
Normal file
2517
cppdraft/basic/string.md
Normal file
File diff suppressed because it is too large
Load Diff
79
cppdraft/basic/string/general.md
Normal file
79
cppdraft/basic/string/general.md
Normal file
@@ -0,0 +1,79 @@
|
||||
[basic.string.general]
|
||||
|
||||
# 27 Strings library [[strings]](./#strings)
|
||||
|
||||
## 27.4 String classes [[string.classes]](string.classes#basic.string.general)
|
||||
|
||||
### 27.4.3 Class template basic_string [[basic.string]](basic.string#general)
|
||||
|
||||
#### 27.4.3.1 General [basic.string.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L1994)
|
||||
|
||||
The
|
||||
class templatebasic_string describes objects that can store a sequence consisting of a varying number of
|
||||
arbitrary char-like objects with the first element of the sequence at position zero[.](#1.sentence-1)
|
||||
|
||||
Such a sequence is also called a âstringâ if the type of the
|
||||
char-like objects that it holds
|
||||
is clear from context[.](#1.sentence-2)
|
||||
|
||||
In the rest of [[basic.string]](basic.string "27.4.3 Class template basic_string"),
|
||||
the type of the char-like objects held in a basic_string object
|
||||
is designated by charT[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L2008)
|
||||
|
||||
A specialization of basic_string is a contiguous container ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements"))[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L2011)
|
||||
|
||||
In all cases,
|
||||
[data(), data() + size()] is a valid range,data() + size() points at an object with value charT() (a ânull terminatorâ),
|
||||
and size() <= capacity() is true[.](#3.sentence-1)
|
||||
|
||||
[ð](#lib:basic_string_)
|
||||
|
||||
namespace std {template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>class basic_string {public:// typesusing traits_type = traits; using value_type = charT; using allocator_type = Allocator; using size_type = typename allocator_traits<Allocator>::size_type; using difference_type = typename allocator_traits<Allocator>::difference_type; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; using reference = value_type&; using const_reference = const value_type&; using iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using const_iterator = *implementation-defined*; // see [[container.requirements]](container.requirements "23.2 Requirements")using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; static constexpr size_type npos = size_type(-1); // [[string.cons]](string.cons "27.4.3.3 Constructors and assignment operators"), construct/copy/destroyconstexpr basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }constexpr explicit basic_string(const Allocator& a) noexcept; constexpr basic_string(const basic_string& str); constexpr basic_string(basic_string&& str) noexcept; constexpr basic_string(const basic_string& str, size_type pos, const Allocator& a = Allocator()); constexpr basic_string(const basic_string& str, size_type pos, size_type n, const Allocator& a = Allocator()); constexpr basic_string(basic_string&& str, size_type pos, const Allocator& a = Allocator()); constexpr basic_string(basic_string&& str, size_type pos, size_type n, const Allocator& a = Allocator()); template<class T>constexpr basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); template<class T>constexpr explicit basic_string(const T& t, const Allocator& a = Allocator()); constexpr basic_string(const charT* s, size_type n, const Allocator& a = Allocator()); constexpr basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
basic_string(nullptr_t) = delete; constexpr basic_string(size_type n, charT c, const Allocator& a = Allocator()); template<class InputIterator>constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<charT> R>constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); constexpr basic_string(initializer_list<charT>, const Allocator& = Allocator()); constexpr basic_string(const basic_string&, const Allocator&); constexpr basic_string(basic_string&&, const Allocator&); constexpr ~basic_string(); constexpr basic_string& operator=(const basic_string& str); constexpr basic_string& operator=(basic_string&& str)noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); template<class T>constexpr basic_string& operator=(const T& t); constexpr basic_string& operator=(const charT* s);
|
||||
basic_string& operator=(nullptr_t) = delete; constexpr basic_string& operator=(charT c); constexpr basic_string& operator=(initializer_list<charT>); // [[string.iterators]](string.iterators "27.4.3.4 Iterator support"), iteratorsconstexpr iterator begin() noexcept; constexpr const_iterator begin() const noexcept; constexpr iterator end() noexcept; constexpr const_iterator end() const noexcept; constexpr reverse_iterator rbegin() noexcept; constexpr const_reverse_iterator rbegin() const noexcept; constexpr reverse_iterator rend() noexcept; constexpr const_reverse_iterator rend() const noexcept; constexpr const_iterator cbegin() const noexcept; constexpr const_iterator cend() const noexcept; constexpr const_reverse_iterator crbegin() const noexcept; constexpr const_reverse_iterator crend() const noexcept; // [[string.capacity]](string.capacity "27.4.3.5 Capacity"), capacityconstexpr size_type size() const noexcept; constexpr size_type length() const noexcept; constexpr size_type max_size() const noexcept; constexpr void resize(size_type n, charT c); constexpr void resize(size_type n); template<class Operation> constexpr void resize_and_overwrite(size_type n, Operation op); constexpr size_type capacity() const noexcept; constexpr void reserve(size_type res_arg); constexpr void shrink_to_fit(); constexpr void clear() noexcept; constexpr bool empty() const noexcept; // [[string.access]](string.access "27.4.3.6 Element access"), element accessconstexpr const_reference operator[](size_type pos) const; constexpr reference operator[](size_type pos); constexpr const_reference at(size_type n) const; constexpr reference at(size_type n); constexpr const charT& front() const; constexpr charT& front(); constexpr const charT& back() const; constexpr charT& back(); // [[string.modifiers]](string.modifiers "27.4.3.7 Modifiers"), modifiersconstexpr basic_string& operator+=(const basic_string& str); template<class T>constexpr basic_string& operator+=(const T& t); constexpr basic_string& operator+=(const charT* s); constexpr basic_string& operator+=(charT c); constexpr basic_string& operator+=(initializer_list<charT>); constexpr basic_string& append(const basic_string& str); constexpr basic_string& append(const basic_string& str, size_type pos, size_type n = npos); template<class T>constexpr basic_string& append(const T& t); template<class T>constexpr basic_string& append(const T& t, size_type pos, size_type n = npos); constexpr basic_string& append(const charT* s, size_type n); constexpr basic_string& append(const charT* s); constexpr basic_string& append(size_type n, charT c); template<class InputIterator>constexpr basic_string& append(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<charT> R>constexpr basic_string& append_range(R&& rg); constexpr basic_string& append(initializer_list<charT>); constexpr void push_back(charT c); constexpr basic_string& assign(const basic_string& str); constexpr basic_string& assign(basic_string&& str)noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value); constexpr basic_string& assign(const basic_string& str, size_type pos, size_type n = npos); template<class T>constexpr basic_string& assign(const T& t); template<class T>constexpr basic_string& assign(const T& t, size_type pos, size_type n = npos); constexpr basic_string& assign(const charT* s, size_type n); constexpr basic_string& assign(const charT* s); constexpr basic_string& assign(size_type n, charT c); template<class InputIterator>constexpr basic_string& assign(InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<charT> R>constexpr basic_string& assign_range(R&& rg); constexpr basic_string& assign(initializer_list<charT>); constexpr basic_string& insert(size_type pos, const basic_string& str); constexpr basic_string& insert(size_type pos1, const basic_string& str,
|
||||
size_type pos2, size_type n = npos); template<class T>constexpr basic_string& insert(size_type pos, const T& t); template<class T>constexpr basic_string& insert(size_type pos1, const T& t,
|
||||
size_type pos2, size_type n = npos); constexpr basic_string& insert(size_type pos, const charT* s, size_type n); constexpr basic_string& insert(size_type pos, const charT* s); constexpr basic_string& insert(size_type pos, size_type n, charT c); constexpr iterator insert(const_iterator p, charT c); constexpr iterator insert(const_iterator p, size_type n, charT c); template<class InputIterator>constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<charT> R>constexpr iterator insert_range(const_iterator p, R&& rg); constexpr iterator insert(const_iterator p, initializer_list<charT>); constexpr basic_string& erase(size_type pos = 0, size_type n = npos); constexpr iterator erase(const_iterator p); constexpr iterator erase(const_iterator first, const_iterator last); constexpr void pop_back(); constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str); constexpr basic_string& replace(size_type pos1, size_type n1, const basic_string& str,
|
||||
size_type pos2, size_type n2 = npos); template<class T>constexpr basic_string& replace(size_type pos1, size_type n1, const T& t); template<class T>constexpr basic_string& replace(size_type pos1, size_type n1, const T& t,
|
||||
size_type pos2, size_type n2 = npos); constexpr basic_string& replace(size_type pos, size_type n1, const charT* s, size_type n2); constexpr basic_string& replace(size_type pos, size_type n1, const charT* s); constexpr basic_string& replace(size_type pos, size_type n1, size_type n2, charT c); constexpr basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); template<class T>constexpr basic_string& replace(const_iterator i1, const_iterator i2, const T& t); constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s,
|
||||
size_type n); constexpr basic_string& replace(const_iterator i1, const_iterator i2, const charT* s); constexpr basic_string& replace(const_iterator i1, const_iterator i2, size_type n, charT c); template<class InputIterator>constexpr basic_string& replace(const_iterator i1, const_iterator i2,
|
||||
InputIterator j1, InputIterator j2); template<[*container-compatible-range*](container.intro.reqmts#concept:container-compatible-range "23.2.2.1 Introduction [container.intro.reqmts]")<charT> R>constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); constexpr basic_string& replace(const_iterator, const_iterator, initializer_list<charT>); constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; constexpr void swap(basic_string& str)noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value); // [[string.ops]](string.ops "27.4.3.8 String operations"), string operationsconstexpr const charT* c_str() const noexcept; constexpr const charT* data() const noexcept; constexpr charT* data() noexcept; constexpr operator basic_string_view<charT, traits>() const noexcept; constexpr allocator_type get_allocator() const noexcept; template<class T>constexpr size_type find(const T& t, size_type pos = 0) const noexcept(*see below*); constexpr size_type find(const basic_string& str, size_type pos = 0) const noexcept; constexpr size_type find(const charT* s, size_type pos, size_type n) const; constexpr size_type find(const charT* s, size_type pos = 0) const; constexpr size_type find(charT c, size_type pos = 0) const noexcept; template<class T>constexpr size_type rfind(const T& t, size_type pos = npos) const noexcept(*see below*); constexpr size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; constexpr size_type rfind(const charT* s, size_type pos, size_type n) const; constexpr size_type rfind(const charT* s, size_type pos = npos) const; constexpr size_type rfind(charT c, size_type pos = npos) const noexcept; template<class T>constexpr size_type find_first_of(const T& t, size_type pos = 0) const noexcept(*see below*); constexpr size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; constexpr size_type find_first_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_first_of(const charT* s, size_type pos = 0) const; constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept; template<class T>constexpr size_type find_last_of(const T& t,
|
||||
size_type pos = npos) const noexcept(*see below*); constexpr size_type find_last_of(const basic_string& str,
|
||||
size_type pos = npos) const noexcept; constexpr size_type find_last_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_last_of(const charT* s, size_type pos = npos) const; constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept; template<class T>constexpr size_type find_first_not_of(const T& t,
|
||||
size_type pos = 0) const noexcept(*see below*); constexpr size_type find_first_not_of(const basic_string& str,
|
||||
size_type pos = 0) const noexcept; constexpr size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_first_not_of(const charT* s, size_type pos = 0) const; constexpr size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; template<class T>constexpr size_type find_last_not_of(const T& t,
|
||||
size_type pos = npos) const noexcept(*see below*); constexpr size_type find_last_not_of(const basic_string& str,
|
||||
size_type pos = npos) const noexcept; constexpr size_type find_last_not_of(const charT* s, size_type pos, size_type n) const; constexpr size_type find_last_not_of(const charT* s, size_type pos = npos) const; constexpr size_type find_last_not_of(charT c, size_type pos = npos) const noexcept; constexpr basic_string substr(size_type pos = 0, size_type n = npos) const &; constexpr basic_string substr(size_type pos = 0, size_type n = npos) &&; constexpr basic_string_view<charT, traits> subview(size_type pos = 0,
|
||||
size_type n = npos) const; template<class T>constexpr int compare(const T& t) const noexcept(*see below*); template<class T>constexpr int compare(size_type pos1, size_type n1, const T& t) const; template<class T>constexpr int compare(size_type pos1, size_type n1, const T& t,
|
||||
size_type pos2, size_type n2 = npos) const; constexpr int compare(const basic_string& str) const noexcept; constexpr int compare(size_type pos1, size_type n1, const basic_string& str) const; constexpr int compare(size_type pos1, size_type n1, const basic_string& str,
|
||||
size_type pos2, size_type n2 = npos) const; constexpr int compare(const charT* s) const; constexpr int compare(size_type pos1, size_type n1, const charT* s) const; constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; constexpr bool starts_with(basic_string_view<charT, traits> x) const noexcept; constexpr bool starts_with(charT x) const noexcept; constexpr bool starts_with(const charT* x) const; constexpr bool ends_with(basic_string_view<charT, traits> x) const noexcept; constexpr bool ends_with(charT x) const noexcept; constexpr bool ends_with(const charT* x) const; constexpr bool contains(basic_string_view<charT, traits> x) const noexcept; constexpr bool contains(charT x) const noexcept; constexpr bool contains(const charT* x) const; }; template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>> basic_string(InputIterator, InputIterator, Allocator = Allocator())-> basic_string<typename iterator_traits<InputIterator>::value_type,
|
||||
char_traits<typename iterator_traits<InputIterator>::value_type>,
|
||||
Allocator>; template<ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class Allocator = allocator<ranges::range_value_t<R>>> basic_string(from_range_t, R&&, Allocator = Allocator())-> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>,
|
||||
Allocator>; template<class charT, class traits, class Allocator = allocator<charT>>explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator())-> basic_string<charT, traits, Allocator>; template<class charT, class traits, class Allocator = allocator<charT>> basic_string(basic_string_view<charT, traits>, typename *see below*::size_type, typename *see below*::size_type, const Allocator& = Allocator())-> basic_string<charT, traits, Allocator>;}
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L2351)
|
||||
|
||||
A size_type parameter type in
|
||||
a basic_string deduction guide
|
||||
refers to the size_type member type of
|
||||
the type deduced by the deduction guide[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L2357)
|
||||
|
||||
The types iterator and const_iterator meet
|
||||
the constexpr iterator requirements ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General"))[.](#5.sentence-1)
|
||||
23
cppdraft/basic/string/hash.md
Normal file
23
cppdraft/basic/string/hash.md
Normal file
@@ -0,0 +1,23 @@
|
||||
[basic.string.hash]
|
||||
|
||||
# 27 Strings library [[strings]](./#strings)
|
||||
|
||||
## 27.4 String classes [[string.classes]](string.classes#basic.string.hash)
|
||||
|
||||
### 27.4.6 Hash support [basic.string.hash]
|
||||
|
||||
[ð](#lib:hash,basic_string)
|
||||
|
||||
`template<class A> struct hash<basic_string<char, char_traits<char>, A>>;
|
||||
template<class A> struct hash<basic_string<char8_t, char_traits<char8_t>, A>>;
|
||||
template<class A> struct hash<basic_string<char16_t, char_traits<char16_t>, A>>;
|
||||
template<class A> struct hash<basic_string<char32_t, char_traits<char32_t>, A>>;
|
||||
template<class A> struct hash<basic_string<wchar_t, char_traits<wchar_t>, A>>;
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5392)
|
||||
|
||||
If S is one of these string types,SV is the corresponding string view type, ands is an object of type S,
|
||||
then hash<S>()(s) == hash<SV>()(SV(s))[.](#1.sentence-1)
|
||||
72
cppdraft/basic/string/literals.md
Normal file
72
cppdraft/basic/string/literals.md
Normal file
@@ -0,0 +1,72 @@
|
||||
[basic.string.literals]
|
||||
|
||||
# 27 Strings library [[strings]](./#strings)
|
||||
|
||||
## 27.4 String classes [[string.classes]](string.classes#basic.string.literals)
|
||||
|
||||
### 27.4.7 Suffix for basic_string literals [basic.string.literals]
|
||||
|
||||
[ð](#lib:operator%22%22s,string)
|
||||
|
||||
`constexpr string operator""s(const char* str, size_t len);
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5407)
|
||||
|
||||
*Returns*: string{str, len}[.](#1.sentence-1)
|
||||
|
||||
[ð](#lib:operator%22%22s,u8string)
|
||||
|
||||
`constexpr u8string operator""s(const char8_t* str, size_t len);
|
||||
`
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5417)
|
||||
|
||||
*Returns*: u8string{str, len}[.](#2.sentence-1)
|
||||
|
||||
[ð](#lib:operator%22%22s,u16string)
|
||||
|
||||
`constexpr u16string operator""s(const char16_t* str, size_t len);
|
||||
`
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5427)
|
||||
|
||||
*Returns*: u16string{str, len}[.](#3.sentence-1)
|
||||
|
||||
[ð](#lib:operator%22%22s,u32string)
|
||||
|
||||
`constexpr u32string operator""s(const char32_t* str, size_t len);
|
||||
`
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5437)
|
||||
|
||||
*Returns*: u32string{str, len}[.](#4.sentence-1)
|
||||
|
||||
[ð](#lib:operator%22%22s,wstring)
|
||||
|
||||
`constexpr wstring operator""s(const wchar_t* str, size_t len);
|
||||
`
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5447)
|
||||
|
||||
*Returns*: wstring{str, len}[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5452)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The same suffix s is used for chrono::duration literals denoting seconds but there is no conflict, since duration suffixes apply to numbers and string literal suffixes apply to character array literals[.](#6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
139
cppdraft/basic/type/qualifier.md
Normal file
139
cppdraft/basic/type/qualifier.md
Normal file
@@ -0,0 +1,139 @@
|
||||
[basic.type.qualifier]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.9 Types [[basic.types]](basic.types#basic.type.qualifier)
|
||||
|
||||
### 6.9.5 CV-qualifiers [basic.type.qualifier]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5991)
|
||||
|
||||
Each type other than a function or reference type
|
||||
is part of a group of four distinct, but related, types:
|
||||
a [*cv-unqualified*](#def:cv-unqualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version,
|
||||
a [*const-qualified*](#def:const-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version,
|
||||
a [*volatile-qualified*](#def:volatile-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version, and
|
||||
a [*const-volatile-qualified*](#def:const-volatile-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version[.](#1.sentence-1)
|
||||
|
||||
The types in each such group shall have
|
||||
the same representation and alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment"))[.](#1.sentence-2)[34](#footnote-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.")
|
||||
|
||||
A function or reference type is always cv-unqualified[.](#1.sentence-3)
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
A [*const object*](#def:object,const "6.9.5 CV-qualifiers [basic.type.qualifier]") is an object of type const T or a
|
||||
non-mutable subobject of a const object[.](#1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
A [*volatile object*](#def:object,volatile "6.9.5 CV-qualifiers [basic.type.qualifier]") is an object of type volatile T or a subobject of a volatile object[.](#1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
A [*const volatile object*](#def:object,const_volatile "6.9.5 CV-qualifiers [basic.type.qualifier]") 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[.](#1.3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The type of an object ([[intro.object]](intro.object "6.8.2 Object model")) includes
|
||||
the [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* specified in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") ([[dcl.spec]](dcl.spec "9.2 Specifiers")),[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3 Declarators")),[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ([[dcl.name]](dcl.name "9.3.2 Type names")), or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))
|
||||
when the object is created[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6033)
|
||||
|
||||
Except for array types, a compound type ([[basic.compound]](basic.compound "6.9.4 Compound types")) is not cv-qualified by the
|
||||
cv-qualifiers (if any) of the types from which it is compounded[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6037)
|
||||
|
||||
An array type whose elements are cv-qualified
|
||||
is also considered to have the same cv-qualifications
|
||||
as its elements[.](#3.sentence-1)
|
||||
|
||||
[*Note [2](#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]](dcl.array "9.3.4.5 Arrays"))[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#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 5const charâ, and the array type is considered to be
|
||||
const-qualified[.](#3.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6061)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
See [[dcl.fct]](dcl.fct "9.3.4.6 Functions") and [[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists") regarding function
|
||||
types that have [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6067)
|
||||
|
||||
There is a partial ordering on cv-qualifiers, so that a type can be
|
||||
said to be [*more cv-qualified*](#def:more_cv-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") than another[.](#5.sentence-1)
|
||||
|
||||
Table [16](#tab:basic.type.qualifier.rel "Table 16: Relations on const and volatile") shows the relations that
|
||||
constitute this ordering[.](#5.sentence-2)
|
||||
|
||||
Table [16](#tab:basic.type.qualifier.rel) — Relations on const and volatile [[tab:basic.type.qualifier.rel]](./tab:basic.type.qualifier.rel)
|
||||
|
||||
| [ð](#tab:basic.type.qualifier.rel-row-1)<br>*no cv-qualifier* | < | const |
|
||||
| --- | --- | --- |
|
||||
| [ð](#tab:basic.type.qualifier.rel-row-2)<br>*no cv-qualifier* | < | volatile |
|
||||
| [ð](#tab:basic.type.qualifier.rel-row-3)<br>*no cv-qualifier* | < | const volatile |
|
||||
| [ð](#tab:basic.type.qualifier.rel-row-4)<br>const | < | const volatile |
|
||||
| [ð](#tab:basic.type.qualifier.rel-row-5)<br>volatile | < | const volatile |
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6083)
|
||||
|
||||
In this document, the notation cv (or*cv1*, *cv2*, etc[.](#6.sentence-1))
|
||||
|
||||
, 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[.](#6.sentence-2)
|
||||
|
||||
For a type cv T, the [*top-level cv-qualifiers*](#def:cv-qualifier,top-level "6.9.5 CV-qualifiers [basic.type.qualifier]") of that type are those denoted by cv[.](#6.sentence-3)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
The type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")const int& has no top-level cv-qualifiers[.](#6.sentence-4)
|
||||
|
||||
The type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")volatile int * const has the top-level cv-qualifier const[.](#6.sentence-5)
|
||||
|
||||
For a class type C,
|
||||
the type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")void (C::* volatile)(int) const has the top-level cv-qualifier volatile[.](#6.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[34)](#footnote-34)[34)](#footnoteref-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[.](#footnote-34.sentence-1)
|
||||
1453
cppdraft/basic/types.md
Normal file
1453
cppdraft/basic/types.md
Normal file
File diff suppressed because it is too large
Load Diff
302
cppdraft/basic/types/general.md
Normal file
302
cppdraft/basic/types/general.md
Normal file
@@ -0,0 +1,302 @@
|
||||
[basic.types.general]
|
||||
|
||||
# 6 Basics [[basic]](./#basic)
|
||||
|
||||
## 6.9 Types [[basic.types]](basic.types#general)
|
||||
|
||||
### 6.9.1 General [basic.types.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5030)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
[[basic.types]](basic.types "6.9 Types") and the subclauses thereof
|
||||
impose requirements on implementations regarding the representation
|
||||
of types[.](#1.sentence-1)
|
||||
|
||||
There are two kinds of types: fundamental types and compound types[.](#1.sentence-2)
|
||||
|
||||
Types describe [objects](intro.object "6.8.2 Object model [intro.object]"),[references](dcl.ref "9.3.4.3 References [dcl.ref]"),
|
||||
or [functions](dcl.fct "9.3.4.6 Functions [dcl.fct]")[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5041)
|
||||
|
||||
For any object (other than a potentially-overlapping subobject) of trivially copyable typeT, whether or not the object holds a valid value of typeT, the underlying bytes ([[intro.memory]](intro.memory "6.8.1 Memory model")) making up the
|
||||
object can be copied into an array ofchar,unsigned char, orstd::byte ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"))[.](#2.sentence-1)[26](#footnote-26 "By using, for example, the library functions ([headers]) std::memcpy or std::memmove.")
|
||||
|
||||
If the content of that array
|
||||
is copied back into the object, the object shall
|
||||
subsequently hold its original value[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#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*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5068)
|
||||
|
||||
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]](intro.memory "6.8.1 Memory model")) making upobj1 are copied into obj2,[27](#footnote-27 "By using, for example, the library functions ([headers]) std::memcpy or std::memmove.")obj2 shall subsequently hold the same value asobj1[.](#3.sentence-1)
|
||||
|
||||
[*Example [2](#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*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5092)
|
||||
|
||||
The [*object representation*](#def:representation,object "6.9.1 General [basic.types.general]") 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* equalssizeof(T)[.](#4.sentence-1)
|
||||
|
||||
The [*value representation*](#def:representation,value "6.9.1 General [basic.types.general]") of a type T is the set of bits
|
||||
in the object representation of T that participate in representing a value of type T[.](#4.sentence-2)
|
||||
|
||||
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[.](#4.sentence-3)
|
||||
|
||||
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]](class.bit "11.4.10 Bit-fields"))[.](#4.sentence-4)
|
||||
|
||||
The value representation of a bit-field object is
|
||||
the set of bits in the object representation that
|
||||
participate in representing its value[.](#4.sentence-5)
|
||||
|
||||
Bits in the object representation of a type or object that are
|
||||
not part of the value representation
|
||||
are [*padding bits*](#def:padding_bits "6.9.1 General [basic.types.general]")[.](#4.sentence-6)
|
||||
|
||||
For trivially copyable types, the value representation is
|
||||
a set of bits in the object representation that determines a[*value*](#def:value "6.9.1 General [basic.types.general]"), which is one discrete element of animplementation-defined set of values[.](#4.sentence-7)[28](#footnote-28 "The intent is that the memory model of C++ is compatible with that of the C programming language.")
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5127)
|
||||
|
||||
A class that has been declared but not defined, an enumeration type in certain
|
||||
contexts ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), or an array of unknown
|
||||
bound or of incomplete element type, is an[*incompletely-defined object type*](#def:object_type,incompletely-defined "6.9.1 General [basic.types.general]")[.](#5.sentence-1)[29](#footnote-29 "The size and layout of an instance of an incompletely-defined object type is unknown.")
|
||||
|
||||
Incompletely-defined object types and cv void are[*incomplete types*](#def:type,incomplete "6.9.1 General [basic.types.general]") ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#5.sentence-2)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Objects cannot be defined to have an incomplete type ([[basic.def]](basic.def "6.2 Declarations and definitions"))[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5144)
|
||||
|
||||
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[.](#6.sentence-1)
|
||||
|
||||
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[.](#6.sentence-2)
|
||||
|
||||
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 ofN Tâ) are different types[.](#6.sentence-3)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
The type of a pointer or reference to array of unknown bound
|
||||
permanently points to or refers to an incomplete type[.](#6.sentence-4)
|
||||
|
||||
An array of unknown bound named by a typedef declaration
|
||||
permanently refers to an incomplete type[.](#6.sentence-5)
|
||||
|
||||
In either case, the array type cannot be completed[.](#6.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#example-3)*:
|
||||
|
||||
[ð](#:type,example_of_incomplete)
|
||||
|
||||
class X; // X is an incomplete typeextern X* xp; // xp is a pointer to an incomplete typeextern int arr[]; // the type of arr is incompletetypedef 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 typeint 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]](conv.qual "7.3.6 Qualification conversions")) xp++; // OK, X is complete arrp++; // error: UNKA can't be completed} â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5192)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The rules for declarations and expressions describe in which
|
||||
contexts incomplete types are prohibited[.](#7.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5198)
|
||||
|
||||
An [*object type*](#def:object_type "6.9.1 General [basic.types.general]") is a (possibly cv-qualified) type that is not
|
||||
a function type, not a reference type, and not cv void[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5203)
|
||||
|
||||
Arithmetic types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")), enumeration types,
|
||||
pointer types, pointer-to-member types ([[basic.compound]](basic.compound "6.9.4 Compound types")),std::meta::info, std::nullptr_t,
|
||||
and[cv-qualified](basic.type.qualifier "6.9.5 CV-qualifiers [basic.type.qualifier]") versions of these
|
||||
types are collectively called[*scalar types*](#def:type,scalar "6.9.1 General [basic.types.general]")[.](#9.sentence-1)
|
||||
|
||||
Scalar types, trivially copyable class types ([[class.prop]](class.prop "11.2 Properties of classes")),
|
||||
arrays of such types, and cv-qualified versions of these
|
||||
types are collectively called [*trivially copyable types*](#def:type,trivially_copyable "6.9.1 General [basic.types.general]")[.](#9.sentence-2)
|
||||
|
||||
Scalar types, trivially relocatable class types ([[class.prop]](class.prop "11.2 Properties of classes")),
|
||||
arrays of such types, and cv-qualified versions of these
|
||||
types are collectively called [*trivially relocatable types*](#def:type,trivially_relocatable "6.9.1 General [basic.types.general]")[.](#9.sentence-3)
|
||||
|
||||
Cv-unqualified scalar types, replaceable class types ([[class.prop]](class.prop "11.2 Properties of classes")), and
|
||||
arrays of such types are collectively called[*replaceable types*](#def:type,replaceable "6.9.1 General [basic.types.general]")[.](#9.sentence-4)
|
||||
|
||||
Scalar types, standard-layout class
|
||||
types ([[class.prop]](class.prop "11.2 Properties of classes")), arrays of such types, and
|
||||
cv-qualified versions of these types
|
||||
are collectively called [*standard-layout types*](#def:type,standard-layout "6.9.1 General [basic.types.general]")[.](#9.sentence-5)
|
||||
|
||||
Scalar types, implicit-lifetime class types ([[class.prop]](class.prop "11.2 Properties of classes")),
|
||||
array types, and cv-qualified versions of these types
|
||||
are collectively called [*implicit-lifetime types*](#def:type,implicit-lifetime "6.9.1 General [basic.types.general]")[.](#9.sentence-6)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5238)
|
||||
|
||||
A type is a [*literal type*](#def:type,literal "6.9.1 General [basic.types.general]") if it is:
|
||||
|
||||
- [(10.1)](#10.1)
|
||||
|
||||
cv void; or
|
||||
|
||||
- [(10.2)](#10.2)
|
||||
|
||||
a scalar type; or
|
||||
|
||||
- [(10.3)](#10.3)
|
||||
|
||||
a reference type; or
|
||||
|
||||
- [(10.4)](#10.4)
|
||||
|
||||
an array of literal type; or
|
||||
|
||||
- [(10.5)](#10.5)
|
||||
|
||||
a possibly cv-qualified [class type](class "11 Classes [class]") that
|
||||
has all of the following properties:
|
||||
* [(10.5.1)](#10.5.1)
|
||||
|
||||
it has a constexpr destructor ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers")),
|
||||
|
||||
* [(10.5.2)](#10.5.2)
|
||||
|
||||
all of its non-variant non-static data members and base classes are of non-volatile literal types, and
|
||||
|
||||
* [(10.5.3)](#10.5.3)
|
||||
|
||||
it
|
||||
+
|
||||
[(10.5.3.1)](#10.5.3.1)
|
||||
is a closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")),
|
||||
|
||||
+
|
||||
[(10.5.3.2)](#10.5.3.2)
|
||||
is an aggregate union type that has either
|
||||
no variant members or
|
||||
at least one variant member of non-volatile literal type,
|
||||
|
||||
+
|
||||
[(10.5.3.3)](#10.5.3.3)
|
||||
is a non-union aggregate type for which
|
||||
each of its anonymous union members
|
||||
satisfies the above requirements for an aggregate union type, or
|
||||
|
||||
+
|
||||
[(10.5.3.4)](#10.5.3.4)
|
||||
has at least one constexpr constructor or constructor template
|
||||
(possibly inherited ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")) from a base class)
|
||||
that is not a copy or move constructor[.](#10.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
A literal type is one for which
|
||||
it might be possible to create an object
|
||||
within a constant expression[.](#10.sentence-2)
|
||||
|
||||
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[.](#10.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5275)
|
||||
|
||||
Two types *cv1* T1 and *cv2* T2 are[*layout-compatible types*](#def:type,layout-compatible "6.9.1 General [basic.types.general]") if T1 and T2 are the same type,[layout-compatible enumerations](dcl.enum#def:layout-compatible,enumeration "9.8.1 Enumeration declarations [dcl.enum]"), or[layout-compatible standard-layout class types](class.mem#def:layout-compatible,class "11.4 Class members [class.mem]")[.](#11.sentence-1)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5283)
|
||||
|
||||
A type is [*consteval-only*](#def:consteval-only "6.9.1 General [basic.types.general]") if it is eitherstd::meta::info or
|
||||
a type compounded from a consteval-only type ([[basic.compound]](basic.compound "6.9.4 Compound types"))[.](#12.sentence-1)
|
||||
|
||||
Every object of consteval-only type shall be
|
||||
|
||||
- [(12.1)](#12.1)
|
||||
|
||||
the object associated with a constexpr variable or a subobject thereof,
|
||||
|
||||
- [(12.2)](#12.2)
|
||||
|
||||
a template parameter object ([[temp.param]](temp.param "13.2 Template parameters")) or a subobject thereof, or
|
||||
|
||||
- [(12.3)](#12.3)
|
||||
|
||||
an object whose lifetime begins and ends
|
||||
during the evaluation of a core constant expression[.](#12.sentence-2)
|
||||
|
||||
[26)](#footnote-26)[26)](#footnoteref-26)
|
||||
|
||||
By using, for example, the library
|
||||
functions ([[headers]](headers "16.4.2.3 Headers")) std::memcpy or std::memmove[.](#footnote-26.sentence-1)
|
||||
|
||||
[27)](#footnote-27)[27)](#footnoteref-27)
|
||||
|
||||
By using, for example,
|
||||
the library functions ([[headers]](headers "16.4.2.3 Headers")) std::memcpy or std::memmove[.](#footnote-27.sentence-1)
|
||||
|
||||
[28)](#footnote-28)[28)](#footnoteref-28)
|
||||
|
||||
The intent is that the memory model of C++ is compatible
|
||||
with that of the C programming language[.](#footnote-28.sentence-1)
|
||||
|
||||
[29)](#footnote-29)[29)](#footnoteref-29)
|
||||
|
||||
The size and layout of an instance of an incompletely-defined
|
||||
object type is unknown[.](#footnote-29.sentence-1)
|
||||
Reference in New Issue
Block a user