Search⌘ K
AI Features

Compile-Time Programming

Explore how to leverage compile-time programming in modern C++ through constexpr, consteval, and constinit keywords. Understand how these features enable computations and validations during compilation, improving performance and safety by detecting errors early and eliminating runtime overhead.

Traditionally, programs are written with the assumption that all logic executes at runtime, after the application has started. Modern C++, however, allows certain computations to be performed while the compiler is building the program. By shifting work to compile-time, we gain two significant advantages: zero runtime overhead, since results are embedded directly into the binary, and greater safety, because invalid logic is detected during compilation rather than at runtime.

In this lesson, we explore how to instruct the compiler to perform computations on our behalf.

The power of constexpr

We have already used const to declare values that cannot be modified after initialization. However, const only guarantees immutability; it does not specify when the value is computed. A const variable may still be initialized at runtime, for example, based on user input.

To require compile-time evaluation, C++ provides the constexpr keyword, which stands for constant expression. Declaring a variable or function as constexpr tells the compiler that its value must be known and computed during compilation.

If the compiler cannot evaluate a constexpr expression at compile time, such as when it depends on runtime input, the program will fail to compile. This strict requirement ensures that no runtime cost is incurred for that computation and that errors are caught as early as possible.

C++ 23
#include <iostream>
int main() {
int runtime_input = 10;
// Standard const: Read-only, but initialized at runtime
const int x = runtime_input;
// constexpr: Must be computed at compile time
constexpr int y = 5 * 5;
// ERROR: The value of 'runtime_input' is not known at compile time
// constexpr int z = runtime_input;
std::cout << "Runtime const x: " << x << "\n";
std::cout << "Compile-time constexpr y: " << y << "\n";
return 0;
}

Let’s break this down step by step:

  • Line 7: We declare x as const, which makes it immutable after initialization. However, because its value depends on runtime_input, it is still determined at runtime.

  • Line 10: We declare y as constexpr ...