static_cast
conversionGeneral topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
| ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
General | |||||||||||||||||||||
Literals | |||||||||||||||||||||
Operators | |||||||||||||||||||||
Conversions | |||||||||||||||||||||
|
Converts between types using a combination of implicit and user-defined conversions.
Contents |
static_cast< target-type >( expression ) | |||||||||
Returns a value of typetarget-type.
Only the following conversions can be done withstatic_cast, except when such conversions wouldcast away constness (or volatility).
Base
” andtarget-type is “reference tocv2Derived
”, the result refers to the object of typeDerived
enclosingexpression if all following conditions are satisfied:Derived
is a complete class type.Base
is a base class ofDerived
.Base
is avirtual base class ofDerived
.Base
is a base class of a virtual base class ofDerived
.Derived
” to “pointer toBase
” exists.Derived
, the behavior is undefined.struct B{};struct D: B{ B b;}; D d;B& br1= d;B& br2= d.b; static_cast<D&>(br1);// OK, lvalue denoting the original “d” objectstatic_cast<D&>(br2);// UB: the “b” subobject is not a base class subobject
2) Iftarget-type is “rvalue reference to Derived ” andexpression is an xvalue of type “(possibly cv-qualified)Base ” such thatBase is a base class ofDerived , the result and constraints of such a conversion are the same as those of the “Base lvalue toDerived reference” conversion.3) Iftarget-type is an rvalue reference type and the referenced type isreference-compatible with the type ofexpression,static_cast converts the value ofglvalue, class prvalue, or array prvalue(until C++17)any lvalue(since C++17)expression to xvalue referring to the same object as the expression, or to its base class subobject (depending ontarget-type).[1] Iftarget-type is an inaccessible or ambiguous base of the type ofexpression, the program is ill-formed. Ifexpression is abit-field lvalue, it is first converted to prvalue of the underlying type. | (since C++11) |
the declarationtarget-typetemp(expression ); is well-formed for some invented temporary variabletemp. The effect of such an explicit conversion is the same as performing the declaration and initialization and then usingtemp as the result of the conversion. Theexpression is used asan lvalue(until C++11)a glvalue(since C++11) if and only if the initialization uses it asan lvalue(until C++11)a glvalue(since C++11). | (until C++17) | ||
any of the following conditions is satisfied:
The explicit conversion is defined as follows:
| (since C++17) |
(since C++17) |
a) A value ofscoped enumeration type can be converted to an integer or floating-point type.
| (since C++11) |
d) A prvalue of floating-point type can be explicitly converted to any other floating-point type.
| (since C++23) |
Base
” can be explicitly converted to the type “pointer tocv2Derived
” if all following conditions are satisfied:Derived
is a complete class type.Base
is a base class ofDerived
.Derived
enclosing the object of typeBase
pointed to byexpression.Base
is avirtual base class ofDerived
.Base
is a base class of a virtual base class ofDerived
.Derived
” to “pointer toBase
” exists.Derived
, the behavior is undefined.Derived
of typecv1T
” can be explicitly converted to the type “pointer to member ofBase
of typecv2T
” if all following conditions are satisfied:Derived
is a complete class type.Base
is a base class ofDerived
.Base
.Base
of typeT
” to “pointer to member ofDerived
of typeT
” exists, the program is ill-formed.Base
, the behavior is undefined.T
” ifT
is an object type andcv1 is not a greater cv-qualification thancv2.
| (until C++17) |
| (since C++17) |
As with all cast expressions, the result is:
| (since C++11) |
Two objectsa andb arepointer-interconvertible if:
union U{int a;double b;} u;void* x=&u;// x's value is “pointer to u”double* y=static_cast<double*>(x);// y's value is “pointer to u.b”char* z=static_cast<char*>(x);// z's value is “pointer to u”
Base-to-derived conversions (downcasts) usingstatic_cast make no runtime checks to ensure that thedynamic type of the pointed/referred object isDerived
, and may only be used safely if this precondition is guaranteed by other means, such as when implementingstatic polymorphism. Safe downcast may be done withdynamic_cast
.
static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type, as in
std::for_each(files.begin(), files.end(),static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
#include <iostream>#include <vector> struct B{int m=42;constchar* hello()const{return"Hello world, this is B!\n";}}; struct D: B{constchar* hello()const{return"Hello world, this is D!\n";}}; enumclass E{ ONE=1, TWO, THREE};enum EU{ ONE=1, TWO, THREE}; int main(){// 1. static downcast D d; B& br= d;// upcast via implicit conversionstd::cout<<"1) "<< br.hello(); D& another_d=static_cast<D&>(br);// downcaststd::cout<<"1) "<< another_d.hello(); // 3. lvalue to xvaluestd::vector<int> v0{1,2,3};std::vector<int> v2=static_cast<std::vector<int>&&>(v0);std::cout<<"3) after move, v0.size() = "<< v0.size()<<'\n'; // 4. discarded-value expressionstatic_cast<void>(v2.size()); // 5. initializing conversionint n=static_cast<int>(3.14);std::cout<<"5) n = "<< n<<'\n';std::vector<int> v=static_cast<std::vector<int>>(10);std::cout<<"5) v.size() = "<< v.size()<<'\n'; // 6. inverse of implicit conversionvoid* nv=&n;int* ni=static_cast<int*>(nv);std::cout<<"6) *ni = "<<*ni<<'\n'; // 7a. scoped enum to int E e= E::TWO;int two=static_cast<int>(e);std::cout<<"7a) "<< two<<'\n'; // 7b. int to enum, enum to another enum E e2=static_cast<E>(two);[[maybe_unused]] EU eu=static_cast<EU>(e2); // 7f. pointer to member upcastint D::*pm=&D::m;std::cout<<"7f) "<< br.*static_cast<int B::*>(pm)<<'\n'; // 7g. void* to any object pointervoid* voidp=&e;[[maybe_unused]]std::vector<int>* p=static_cast<std::vector<int>*>(voidp);}
Output:
1) Hello world, this is B!1) Hello world, this is D!3) after move, v0.size() = 05) n = 35) v.size() = 106) *ni = 37a) 27f) 42
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 137 | C++98 | the constness and volatility of pointers tovoid could be casted away | cv-qualifications cannot be casted away in such cases |
CWG 427 | C++98 | downcast might be ambiguous with direct-initialization | selects downcast in this case |
CWG 439 | C++98 | when converting a “pointer to object” to “pointer to void” then back to itself, it could only preserve its value if the result type has the same cv-qualification | cv-qualification may be different |
CWG 1094 | C++98 | the conversion from floating-point values to enumeration values was unspecified | specified |
CWG 1320 | C++11 | the conversion from scoped enumeration values to bool was unspecified | specified |
CWG 1412 | C++98 | the result of the conversion from “pointer to void” to “pointer to object” was unclear | made clear |
CWG 1447 | C++11 | the conversion from bit-fields to rvalue references was unspecified (cannot bind references to bit-fields) | specified |
CWG 1766 | C++98 | the conversion from integral or enumeration values to enumeration values yielded unspecified result ifexpression is out of range | the behavior is undefined in this case |
CWG 1832 | C++98 | the conversion from integral or enumeration values to enumeration values allowedtarget-type to be incomplete | not allowed |
CWG 2224 | C++98 | the conversion from a member of base class type to its complete object of derived class type was valid | the behavior is undefined in this case |
CWG 2254 | C++11 | a standard-layout class object with no data members was pointer-interconvertible to its first base class | it is pointer-interconvertible to any of its base classes |
CWG 2284 | C++11 | a non-standard-layout union object and a non-static data member of that object were not pointer-interconvertible | they are |
CWG 2310 | C++98 | for base-to-derived pointer conversions and derived-to-base pointer-to-member conversions, the derived class type could be incomplete | must be complete |
CWG 2338 | C++11 | the conversion to enumeration types with fixed underlying type resulted in undefined behavior ifexpression is out of range | convert to the underlying type first (no undefined behavior) |
CWG 2499 | C++11 | a standard-layout class might have a non-pointer-interconvertible base class, even though all base subobjects have the same address | it does not have |
CWG 2718 | C++98 | for base-to-derived reference conversions, the derived class type could be incomplete | must be complete |
CWG 2882 | C++98 | it was unclear whetherstatic_cast<void>(expr) attempts to form an implicit conversion sequence fromexpr tovoid | no attempt in this case |