Casting
Casting shows up early in programming because sooner or later you’ll run into mathematical expressions that don’t behave the way you expect. When that happens, two things usually need to be checked:
- The order of operations
- The types involved in the calculation
Integer math in particular can produce surprising results, especially with division or expressions that combine division with other operators.
For example:
7 / 2gives3, not3.55 + 7 / 2gives8, not8.5(5 + 7) / 2gives6, not6.0
When the default behavior isn’t what you want, you often need to force the calculation into the correct form — usually by casting one or more operands to a different type.
Casting lets you take control of the expression so the result matches your intention rather than the compiler’s default rules.
In C++ there we typically use the following to cast (force) a value to a specific type.
static_cast<type_to_convert_to>(expression)
Example
// Ex05 - Simple cast example
import std;
int main()
{
double metalSpringSize = {34.65};
int metalSpringIntSize = static_cast<int>(metalSpringSize);
std::println("Integer spring size: {}.", static_cast<int>(metalSpringSize));
std::println("Integer spring size: {}.", metalSpringIntSize);
return 0;
}
static_cast is a built‑in C++ cast operator, not a function.
It uses function‑like syntax, but the compiler treats it as a special language construct.
🧠 Key differences from a real function
The compiler enforces rules about what conversions are allowed.
No function is called — the compiler rewrites the expression at compile time.
No runtime cost — it doesn’t generate a function call instruction.
The angle‑bracket type is not a template parameter — it’s part of the cast syntax.
As we progress through later lessons, the full power of static_cast will become clearer. For now, just understand that using static_cast tells the compiler:
“I know what I’m doing — perform this conversion exactly as written.”
Without this explicit cast, the compiler may issue warnings or even errors depending on the situation.
⚠️ Loss of Precision
For Example:
// Ex06 - Loss of percision
import std;
int main()
{
double metalSpringSize = {34.65};
int metalSpringIntSize = metalSpringSize;
std::println("Integer spring size: {}.", metalSpringIntSize);
return 0;
}
The above will produce the following warning.

Assigning a double to an int causes a narrowing conversion.
The fractional part is discarded, not rounded.
Output: Integer sprint size: 34.
The compiler will warn you about this because it may not be what you intended. The program still compiles, but the warning is a hint that you should review the code.
Treating warnings as errors
To prevent accidental precision loss (and many other issues), you can force the compiler to treat all warnings as errors by adding /WX:
@echo on
mkdir .\build
pushd .\build
del /Q *.*
cl /std:c++latest /EHsc /nologo /W4 /WX /c "%VCToolsInstallDir%\modules\std.ixx" "%VCToolsInstallDir%\modules\std.compat.ixx" ../src/main.cpp
cl /EHsc /std:c++latest ../build/main.obj ../build/std.obj /Fe:main.exe
popd

It is good practice to clear all warnings before moving code to production.
C Style Cast
Before the introduction of static_cast there was what is commonly referred to as the C Style Cast.
(convert_to)expression
Example from our Ex05 would be like this.
// Ex07 - C Style Cast
import std;
int main()
{
double metalSpringSize = {34.65};
int metalSpringIntSize = (int)metalSpringSize;
std::println("Integer spring size: {}.", (int)metalSpringSize);
std::println("Integer spring size: {}.", metalSpringIntSize);
return 0;
}
The output is identical to the static_cast example, but C‑style casts are considered less safe because they allow many different types of conversions — some of which static_cast would reject.
For this reason, modern C++ code strongly prefers static_cast.