Init
This commit is contained in:
275
cppdraft/expr/static/cast.md
Normal file
275
cppdraft/expr/static/cast.md
Normal 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* Dâ, whereD is a complete class derived ([[class.derived]](class.derived "11.7 Derived 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.12 Pointer 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.4 References"))[.](#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.2 Lvalue-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.8 Member access control")) or
|
||||
ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2 Member 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.2 Properties 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.1 Value 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.7 Temporary 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.2 Implicit conversion sequences"))
|
||||
from E to T,
|
||||
if overload resolution for a direct-initialization ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
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.3 Viable functions")), or
|
||||
if T is an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"))
|
||||
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.5 Initializers"))
|
||||
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.2 Lvalue-to-rvalue conversion")),
|
||||
array-to-pointer ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")), and
|
||||
function-to-pointer ([[conv.func]](conv.func "7.3.4 Function-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.1 Enumeration 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.7 Integral promotions")) or integral conversion ([[conv.integral]](conv.integral "7.3.9 Integral 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.1 Enumeration 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.11 Floating-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* Bâ, where B is a class type, can be converted to a prvalue of type âpointer to*cv2* Dâ,
|
||||
where D is a complete class[derived](class.derived "11.7 Derived 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.12 Pointer conversions")), the program is ill-formed[.](#10.sentence-2)
|
||||
|
||||
The null pointer value ([[basic.compound]](basic.compound "6.9.4 Compound types")) is converted
|
||||
to the null pointer value of the destination type[.](#10.sentence-3)
|
||||
|
||||
If the prvalue of type
|
||||
âpointer to *cv1* Bâ points to a B that is
|
||||
actually a base class subobject of an object of type D, the resulting
|
||||
pointer points to the enclosing object of type D[.](#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* Tâ, whereD is a complete class type andB is a [base class](class.derived "11.7 Derived 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.6 Functions"))[.](#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.13 Pointer-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.13 Pointer-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.4 Pointer-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* Tâ,
|
||||
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.4 Compound 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.4 Compound 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*]
|
||||
Reference in New Issue
Block a user