Files
cppdraft_translate/cppdraft/expr/static/cast.md
2025-10-25 03:02:53 +03:00

276 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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*]