On this page
static_cast conversion
Converts between types using a combination of implicit and user-defined conversions.
Syntax
static_cast<target-type >(expression ) |
Returns a value of type target-type.
Explanation
Only the following conversions can be done with static_cast, except when such conversions would cast away constness (or volatility).
D and expression is an lvalue of its non-virtual base B, or target-type is a pointer to some complete class D and expression is a prvalue pointer to its non-virtual base B, static_cast performs a downcast. (This downcast is ill-formed if B is ambiguous, inaccessible, or virtual base (or a base of a virtual base) of D.)
D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism. Safe downcast may be done with dynamic_cast.
D, the result refers to the enclosing object of type D. Otherwise, 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 object
static_cast<D&>(br2); // UB: the b subobject is not a base class subobject
2) If target-type is an rvalue reference type and the referenced type is reference-compatible with the type of expression, static_cast converts the value of glvalue, 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 sub-object (depending on target-type). If the target type is an inaccessible or ambiguous base of the type of the expression, the program is ill-formed. If the expression is a bit-field lvalue, it is first converted to prvalue of the underlying type. This type of static_cast is used to implement move semantics in std::move. |
(since C++11) |
static_cast<target-type >(expression ) returns the imaginary variable Temp initialized as if by target-type Temp(expression );, which may involve implicit conversions, a call to the constructor of target-type or a call to a user-defined conversion operator. For non-reference target-type, the result object of the static_cast prvalue expression is what's direct-initialized.(since C++17)
void (possibly cv-qualified), static_cast discards the value of expression after evaluating it.
static_cast can perform the inverse of that implicit conversion.
static_cast.
7) Scoped enumeration type can be converted to an integer or floating-point type.
|
(since C++11) |
- If the underlying type is not fixed, the behavior is undefined if the value of expression is out of range (the range is all values possible for the smallest bit-field large enough to hold all enumerators of the target enumeration).
- If the underlying type is fixed, the result is the same as converting the original value first to the underlying type of the enumeration and then to the enumeration type.
- The result is the same as converting the original value first to the underlying type of the enumeration, and then to the enumeration type.
9) A prvalue of floating-point type can be explicitly converted to any other floating-point type.
|
(since C++23) |
D can be upcast to a pointer to member of its unambiguous, accessible base class B. This static_cast makes no checks to ensure the member actually exists in the runtime type of the pointed-to object: if B does not contain the original member and is not a base class of the class containing the original member, the behavior is undefined.
T.
- If the original pointer value represents an address of a byte in memory that does not satisfy the alignment requirement of
T, then the resulting pointer value is unspecified. - Otherwise, if the original pointer value points to an object
a, and there is an objectbof type similar toTthat is pointer-interconvertible witha, the result is a pointer tob. - Otherwise the pointer value is unchanged.
void and back to pointer to the original (or more cv-qualified) type preserves its original value.
As with all cast expressions, the result is:
- an lvalue if target-type is an lvalue reference type or an rvalue reference to function type(since C++11);
|
(since C++11) |
- a prvalue otherwise.
Pointer-interconvertible objects
Two objects a and b are pointer-interconvertible if:
- they are the same object, or
- one is a union object and the other is a non-static data member of that object, or
- one is a standard-layout class object and the other is the first non-static data member of that object or any base class subobject of that object, or
- there exists an object
csuch thataandcare pointer-interconvertible, andcandbare pointer-interconvertible.
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"
Notes
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));
Keywords
Example
#include <iostream>
#include <vector>
struct B
{
int m = 42;
const char* hello() const
{
return "Hello world, this is B!\n";
}
};
struct D : B
{
const char* hello() const
{
return "Hello world, this is D!\n";
}
};
enum class E { ONE = 1, TWO, THREE };
enum EU { ONE = 1, TWO, THREE };
int main()
{
// 1. static downcast
D d;
B& br = d; // upcast via implicit conversion
std::cout << "1) " << br.hello();
D& another_d = static_cast<D&>(br); // downcast
std::cout << "1) " << another_d.hello();
// 2. lvalue to xvalue
std::vector<int> v0{1,2,3};
std::vector<int> v2 = static_cast<std::vector<int>&&>(v0);
std::cout << "2) after move, v0.size() = " << v0.size() << '\n';
// 3. initializing conversion
int n = static_cast<int>(3.14);
std::cout << "3) n = " << n << '\n';
std::vector<int> v = static_cast<std::vector<int>>(10);
std::cout << "3) v.size() = " << v.size() << '\n';
// 4. discarded-value expression
static_cast<void>(v2.size());
// 5. inverse of implicit conversion
void* nv = &n;
int* ni = static_cast<int*>(nv);
std::cout << "5) *ni = " << *ni << '\n';
// 6. array-to-pointer followed by upcast
D a[10];
[[maybe_unused]]
B* dp = static_cast<B*>(a);
// 7. scoped enum to int
E e = E::TWO;
int two = static_cast<int>(e);
std::cout << "7) " << two << '\n';
// 8. int to enum, enum to another enum
E e2 = static_cast<E>(two);
[[maybe_unused]]
EU eu = static_cast<EU>(e2);
// 9. pointer to member upcast
int D::*pm = &D::m;
std::cout << "9) " << br.*static_cast<int B::*>(pm) << '\n';
// 10. void* to any type
void* 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!
2) after move, v0.size() = 0
3) n = 3
3) v.size() = 10
5) *ni = 3
7) 2
9) 42
Defect reports
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 void pointers could be casted away |
cv-qualifications cannot be casted away in such cases |
| 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 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 if expression 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 allowed target-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 if expression 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 |
See also
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/static_cast