12 KiB
[expr.static.cast]
7 Expressions [expr]
7.6 Compound expressions [expr.compound]
7.6.1 Postfix expressions [expr.post]
7.6.1.9 Static cast [expr.static.cast]
The result of the expression static_cast(v) is the result of converting the expression v to type T.
If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue.
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]) from B, if cv2 is the same cv-qualification as, or greater cv-qualification than,cv1.
If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from âpointer to Dâ to âpointer to Bâ exists ([conv.ptr]), the program is ill-formed.
An xvalue of type âcv1 Bâ can be cast to type ârvalue reference tocv2 Dâ with the same constraints as for an lvalue of type âcv1 Bâ.
If the object of type âcv1 Bâ is actually a base class subobject of an object of type D, the result refers to the enclosing object of typeD.
Otherwise, the behavior is undefined.
[Example 1: struct B { };struct D : public B { }; D d; B &br = d;
static_cast<D&>(br); // produces lvalue denoting the original d object â end example]
An lvalue of type T1 can be cast to type ârvalue reference to T2â if T2 is reference-compatible withT1 ([dcl.init.ref]).
If the value is not a bit-field, the result refers to the object or the specified base class subobject thereof; otherwise, the lvalue-to-rvalue conversion is applied to the bit-field and the resulting prvalue is used as the operand of the static_cast for the remainder of this subclause.
If T2 is an inaccessible ([class.access]) or ambiguous ([class.member.lookup]) base class of T1, a program that necessitates such a cast is ill-formed.
Any expression can be explicitly converted to type cv void, in which case the operand is a discarded-value expression ([expr.prop]).
[Note 1:
Such a static_cast has no result as it is a prvalue of type void; see [basic.lval].
â end note]
[Note 2:
However, if the value is in a temporary object ([class.temporary]), the destructor for that object is not executed until the usual time, and the value of the object is preserved for the purpose of executing the destructor.
â end note]
Otherwise, an expression E can be explicitly converted to a type T if there is an implicit conversion sequence ([over.best.ics]) from E to T, if overload resolution for a direct-initialization ([dcl.init]) of an object or reference of type T from E would find at least one viable function ([over.match.viable]), or if T is an aggregate type ([dcl.init.aggr]) having a first element x and there is an implicit conversion sequence from E to the type of x.
If T is a reference type, the effect is the same as performing the declaration and initializationT t(E); for some invented temporary variable t ([dcl.init]) and then using the temporary variable as the result of the conversion.
Otherwise, the result object is direct-initialized from E.
[Note 3:
The conversion is ill-formed when attempting to convert an expression of class type to an inaccessible or ambiguous base class.
â end note]
[Note 4:
If T is âarray of unknown bound of Uâ, this direct-initialization defines the type of the expression as U[1].
â end note]
Otherwise, the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) conversions are applied to the operand, and the conversions that can be performed using static_cast are listed below.
No other conversion can be performed using static_cast.
A value of a scoped enumeration type ([dcl.enum]) can be explicitly converted to an integral type; the result is the same as that of converting to the enumeration's underlying type and then to the destination type.
A value of a scoped enumeration type can also be explicitly converted to a floating-point type; the result is the same as that of converting from the original value to the floating-point type.
A value of integral or enumeration type can be explicitly converted to a complete enumeration type.
If the enumeration type has a fixed underlying type, the value is first converted to that type by integral promotion ([conv.prom]) or integral conversion ([conv.integral]), if necessary, and then to the enumeration type.
If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values ([dcl.enum]), and otherwise, the behavior is undefined.
A value of floating-point type can also be explicitly converted to an enumeration type.
The resulting value is the same as converting the original value to the underlying type of the enumeration ([conv.fpint]), and subsequently to the enumeration type.
A prvalue of floating-point type can be explicitly converted to any other floating-point type.
If the source value can be exactly represented in the destination type, the result of the conversion has that exact representation.
If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values.
Otherwise, the behavior is undefined.
A prvalue of type âpointer to cv1 Bâ, where B is a class type, can be converted to a prvalue of type âpointer tocv2 Dâ, where D is a complete classderived from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from âpointer to Dâ to âpointer to Bâ exists ([conv.ptr]), the program is ill-formed.
The null pointer value ([basic.compound]) is converted to the null pointer value of the destination type.
If the prvalue of type âpointer to cv1 Bâ points to a B that is actually a base class subobject of an object of type D, the resulting pointer points to the enclosing object of type D.
Otherwise, the behavior is undefined.
A prvalue of type âpointer to member of D of type cv1Tâ 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 of D, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
[Note 5:
Function types (including those used in pointer-to-member-function types) are never cv-qualified ([dcl.fct]).
â end note]
If no valid standard conversion from âpointer to member of B of type Tâ to âpointer to member of D of type Tâ exists ([conv.mem]), the program is ill-formed.
The null member pointer value is converted to the null member pointer value of the destination type.
If class B contains the original member, or is a base class of the class containing the original member, the resulting pointer to member points to the original member.
Otherwise, the behavior is undefined.
[Note 6:
Although class B need not contain the original member, the dynamic type of the object with which indirection through the pointer to member is performed must contain the original member; see [expr.mptr.oper].
â end note]
A prvalue of type âpointer to cv1 voidâ can be converted to a prvalue of type âpointer to cv2 Tâ, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
If the original pointer value represents the addressA of a byte in memory andA does not satisfy the alignment requirement of T, then the resulting pointer value ([basic.compound]) is unspecified.
Otherwise, if the original pointer value points to an object a, and there is an object b of type similar to T that is pointer-interconvertible with a, the result is a pointer to b.
Otherwise, the pointer value is unchanged by the conversion.
[Example 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]