This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,275 @@
[expr.static.cast]
# 7 Expressions [[expr]](./#expr)
## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.static.cast)
### 7.6.1 Postfix expressions [[expr.post]](expr.post#expr.static.cast)
#### 7.6.1.9 Static cast [expr.static.cast]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4658)
The result of the expression static_cast<T>(v) is the result of
converting the expression v to type T[.](#1.sentence-1)
If T is an lvalue reference type
or an rvalue reference to function type, the result is an lvalue;
if T is an rvalue reference to object type, the result is an xvalue;
otherwise, the result is a prvalue[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4670)
An lvalue of type “*cv1* B”, where B is a class
type, can be cast to type “reference to *cv2*€, whereD is a complete class derived ([[class.derived]](class.derived "11.7Derived classes")) from B,
if *cv2* is the
same cv-qualification as, or greater cv-qualification than,*cv1*[.](#2.sentence-1)
If B is a virtual base class of D or a base class of a virtual base class of D,
or if no valid standard conversion from “pointer to D”
to “pointer to B” exists ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")), the program is ill-formed[.](#2.sentence-2)
An xvalue of type
“*cv1* B” can be cast to type “rvalue reference to*cv2* D” with the same constraints as for an lvalue of
type “*cv1* B”[.](#2.sentence-3)
If the object
of type “*cv1* B” is actually a base class subobject of an object
of type D, the result refers to the enclosing object of typeD[.](#2.sentence-4)
Otherwise, the behavior is undefined[.](#2.sentence-5)
[*Example [1](#example-1)*: struct B { };struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue denoting the original d object — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4700)
An lvalue
of type T1 can be cast to type “rvalue
reference to T2” if T2 is reference-compatible withT1 ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#3.sentence-1)
If the value is not a bit-field,
the result refers to the object or the specified base class subobject
thereof; otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]") is applied to the bit-field and the resulting prvalue is used as the
operand of the static_cast for the remainder of this subclause[.](#3.sentence-2)
If T2 is an inaccessible ([[class.access]](class.access "11.8Member access control")) or
ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) base class of T1,
a program that necessitates such a cast is ill-formed[.](#3.sentence-3)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4713)
Any expression can be explicitly converted to type cv void,
in which case the operand is a discarded-value expression ([[expr.prop]](expr.prop "7.2Properties of expressions"))[.](#4.sentence-1)
[*Note [1](#note-1)*:
Such a static_cast has no result
as it is a prvalue of type void; see [[basic.lval]](basic.lval "7.2.1Value category")[.](#4.sentence-2)
— *end note*]
[*Note [2](#note-2)*:
However, if the value is in a temporary
object ([[class.temporary]](class.temporary "6.8.7Temporary objects")), the destructor for that
object is
not executed until the usual time, and the value of the object is
preserved for the purpose of executing the destructor[.](#4.sentence-3)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4728)
Otherwise, an expression E can be explicitly converted to a type T if there is an implicit conversion sequence ([[over.best.ics]](over.best.ics "12.2.4.2Implicit conversion sequences"))
from E to T,
if overload resolution for a direct-initialization ([[dcl.init]](dcl.init "9.5Initializers"))
of an object or reference of type T from E would find at least one viable function ([[over.match.viable]](over.match.viable "12.2.3Viable functions")), or
if T is an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))
having a first element x and
there is an implicit conversion sequence
from E to the type of x[.](#5.sentence-1)
If T is a reference type, the effect is
the same as performing the declaration and initializationT t(E); for some invented temporary variable t ([[dcl.init]](dcl.init "9.5Initializers"))
and then using the temporary variable as the result of the conversion[.](#5.sentence-2)
Otherwise, the result object is direct-initialized from E[.](#5.sentence-3)
[*Note [3](#note-3)*:
The conversion is ill-formed when attempting to convert an
expression of class type to an inaccessible or ambiguous base class[.](#5.sentence-4)
— *end note*]
[*Note [4](#note-4)*:
If T is “array of unknown bound of U”,
this direct-initialization defines the type of the expression as U[1][.](#5.sentence-5)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4756)
Otherwise, the lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2Lvalue-to-rvalue conversion")),
array-to-pointer ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion")), and
function-to-pointer ([[conv.func]](conv.func "7.3.4Function-to-pointer conversion")) conversions are applied to the
operand, and the conversions that can be performed using static_cast are listed below[.](#6.sentence-1)
No other conversion can be performed using static_cast[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4763)
A value of a scoped enumeration type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations"))
can be explicitly converted to an integral type;
the result is the same as that of converting
to the enumeration's underlying type and then to the destination type[.](#7.sentence-1)
A value of a scoped enumeration type
can also be explicitly converted to a floating-point type;
the result is the same as that of converting
from the original value to the floating-point type[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4773)
A value of integral or enumeration type can be explicitly converted to
a complete enumeration type[.](#8.sentence-1)
If the enumeration type has a fixed underlying type,
the value is first converted to that type
by
integral promotion ([[conv.prom]](conv.prom "7.3.7Integral promotions")) or integral conversion ([[conv.integral]](conv.integral "7.3.9Integral conversions")),
if necessary, and
then to the enumeration type[.](#8.sentence-2)
If the enumeration type does not have a fixed underlying type,
the value is unchanged
if the original value is within the range
of the enumeration values ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")), and
otherwise, the behavior is undefined[.](#8.sentence-3)
A value of floating-point type can also be explicitly converted to an enumeration type[.](#8.sentence-4)
The resulting value is the same as converting the original value to the
underlying type of the enumeration ([[conv.fpint]](conv.fpint "7.3.11Floating-integral conversions")), and subsequently to
the enumeration type[.](#8.sentence-5)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4794)
A prvalue of floating-point type can be explicitly converted to
any other floating-point type[.](#9.sentence-1)
If the source value can be exactly represented in the destination type,
the result of the conversion has that exact representation[.](#9.sentence-2)
If the source value is between two adjacent destination values,
the result of the conversion is
an implementation-defined choice of
either of those values[.](#9.sentence-3)
Otherwise, the behavior is undefined[.](#9.sentence-4)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4805)
A prvalue of type “pointer to *cv1*€, where B is a class type, can be converted to a prvalue of type “pointer to*cv2* D”,
where D is a complete class[derived](class.derived "11.7Derived classes[class.derived]") from B,
if *cv2* is the same cv-qualification as,
or greater cv-qualification than, *cv1*[.](#10.sentence-1)
If B is a virtual base class of D or
a base class of a virtual base class of D, or
if no valid standard conversion from “pointer to D”
to “pointer to B” exists ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")), the program is ill-formed[.](#10.sentence-2)
The null pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")) is converted
to the null pointer value of the destination type[.](#10.sentence-3)
If the prvalue of type
“pointer to *cv1*€ points to a B that is
actually a base class subobject of an object of type D, the resulting
pointer points to the enclosing object of type D[.](#10.sentence-4)
Otherwise, the
behavior is undefined[.](#10.sentence-5)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4827)
A prvalue of type “pointer to member of D of type *cv1*T” can be converted to a prvalue of type “pointer to member ofB of type *cv2*€, whereD is a complete class type andB is a [base class](class.derived "11.7Derived classes[class.derived]") of D,
if *cv2* is the same cv-qualification
as, or greater cv-qualification than, *cv1*[.](#11.sentence-1)
[*Note [5](#note-5)*:
Function types (including those used in pointer-to-member-function types)
are never cv-qualified ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#11.sentence-2)
— *end note*]
If no valid standard conversion
from “pointer to member of B of type T”
to “pointer to member of D of type T”
exists ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions")), the program is ill-formed[.](#11.sentence-3)
The [null member pointer value](conv.mem#def:value,null_member_pointer "7.3.13Pointer-to-member conversions[conv.mem]") is converted to the null
member pointer value of the destination type[.](#11.sentence-4)
If class B contains the original member, or is a base class of the class
containing the original member, the resulting pointer to member points
to the original member[.](#11.sentence-5)
Otherwise, the behavior is undefined[.](#11.sentence-6)
[*Note [6](#note-6)*:
Although class B need not contain the original member, the
dynamic type of the object with which indirection through the pointer
to member is performed must contain the original member;
see [[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")[.](#11.sentence-7)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L4856)
A prvalue of type “pointer to *cv1* void” can be
converted to a prvalue of type “pointer to *cv2*€,
where T is an object type and *cv2* is the same
cv-qualification as, or greater cv-qualification than, *cv1*[.](#12.sentence-1)
If the original pointer value represents the addressA of a byte in memory andA does not satisfy the alignment requirement of T,
then the resulting pointer value ([[basic.compound]](basic.compound "6.9.4Compound types")) is unspecified[.](#12.sentence-2)
Otherwise, if the original pointer value points to an object *a*,
and there is an object *b* of type similar to T that is [pointer-interconvertible](basic.compound#def:pointer-interconvertible "6.9.4Compound types[basic.compound]") with *a*,
the result is a pointer to *b*[.](#12.sentence-3)
Otherwise, the pointer value is unchanged by the conversion[.](#12.sentence-4)
[*Example [2](#example-2)*: T* p1 = new T;const T* p2 = static_cast<const T*>(static_cast<void*>(p1));bool b = p1 == p2; // b will have the value true. — *end example*]