static_cast conversion

From cppreference.com
< cpp‎ | language

Converts between types using a combination of implicit and user-defined conversions.

Contents

[edit] Syntax

static_cast < new_type > ( expression )

Returns a value of type new_type.

[edit] Explanation

Only the following conversions can be done with static_cast, except when such conversions would cast away constness or volatility.

1) If a temporary object of type new_type can be declared and initialized with expression, as by new_type Temp(expression);, which may involve implicit conversions, a call to the constructor of new_type or a call to a user-defined conversion operator, then static_cast<type>(expression) computes and returns the value of that temporary object.
2) If new_type is a pointer or reference to some class D and the type of expression is a pointer or reference to its non-virtual base B, static_cast performs a downcast. Such static_cast makes no runtime checks to ensure that the object's runtime type is actually 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.
3) If new_type is an rvalue reference type, static_cast converts the value of expression to xvalue referring to the same object as the expression, or to its base sub-object (depending on new_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)
4) If new_type is the type void (possibly cv-qualified), static_cast discards the value of expression after evaluating it.
5) If a standard conversion sequence from new_type to the type of expression exists, that does not include lvalue-to-rvalue, array-to-pointer, function-to-pointer, null pointer, null member pointer, function pointer, (since C++17) or boolean conversion, then static_cast can perform the inverse of that implicit conversion.
6) If conversion of expression to new_type involves lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion, it can be performed explicitly by static_cast.
7) Scoped enumeration type can be converted to an integer or floating-point type. When the target type is cv bool, the result is false if the original value is zero and true for all other values. For the remaining integral types, the result is the value of the enum if it can be represented by the target type and unspecified otherwise. (since C++11)
8) Integer, floating-point, or enumeration type can be converted to any complete enumeration type. The result is unspecified (until C++17)undefined behavior (since C++17) if the value of expression, converted to the enumeration's underlying type, is out of range (if the underlying type is fixed, the range is the range of the type. If the underlying type is not fixed, the range is all values possible for the smallest bit field large enough to hold all enumerators of the target enumeration)
9) A pointer to member of some class D can be upcast to a pointer to member of its base class B. This static_cast makes no checks to ensure the member actually exists in the runtime type of the pointed-to object.
10) A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any type. If the value of the original pointer satisfies the alignment requirement of the target type, then the resulting pointer value is unchanged, otherwise it is unspecified. Conversion of any pointer to pointer to 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 new_type is an lvalue reference type or an rvalue reference to function type;
  • an xvalue if new_type is an rvalue reference to object type;
  • a prvalue otherwise.

[edit] Notes

static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type, as in std::transform(s.begin(), s.end(), s.begin(), static_cast<int(*)(int)>(std::toupper));

[edit] Keywords

static_cast

[edit] Example

#include <vector>
#include <iostream>
 
struct B {};
struct D : B {};
 
enum class E { ONE, TWO, THREE };
enum EU { ONE, TWO, THREE };
 
int main()
{
    // 1: initializing conversion
    int n = static_cast<int>(3.14); 
    std::cout << "n = " << n << '\n';
    std::vector<int> v = static_cast<std::vector<int>>(10);
    std::cout << "v.size() = " << v.size() << '\n';
 
    // 2: static downcast
    D d;
    B& br = d; // upcast via implicit conversion
    D& another_d = static_cast<D&>(br); // downcast
 
    // 3: lvalue to xvalue
    std::vector<int> v2 = static_cast<std::vector<int>&&>(v);
    std::cout << "after move, 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 << "*ni = " << *ni << '\n';
 
    // 6. array-to-pointer followed by upcast
    D a[10];
    B* dp = static_cast<B*>(a);
 
    // 7. scoped enum to int or float
    E e = E::ONE;
    int one = static_cast<int>(e);
 
    // 8. int to enum, enum to another enum
    E e2 = static_cast<E>(one);
    EU eu = static_cast<EU>(e2);
 
    // 9. pointer to member upcast
    // todo
 
    // 10. void* to any type
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}

Output:

n = 3
v.size() = 10
after move, v.size() = 0
*ni = 3

[edit] See also