C++ constexpr
constexpr means can be evaluated at compile time when used with compile-time
inputs. This lets the compiler calculate and validate values before the
program starts.
constexpr was introduced in C++11 and became more capable in later standards.
The examples in this lesson use C++20.
Goal and prerequisites
After this lesson, you should be able to:
- create compile-time constants;
- write a function that works at compile time and runtime;
- verify a result with
static_assert; - choose between
const,constexpr, and a normal function; - recognize when
constexprdoes not guarantee compile-time evaluation.
You should already understand functions, return values, and const variables.
Brief example
The compiler can evaluate square(5) while building the program. If the
assertion is false, compilation fails.
Why use constexpr?
Before constexpr, programmers often used macros or repeated literal values:
A typed compile-time constant is clearer and follows normal C++ rules:
Unlike a macro, a constexpr variable has a real type, scope, and compiler
diagnostics.
Useful compile-time values include:
- fixed array sizes;
- protocol constants;
- unit conversions;
- small lookup tables;
- values checked by
static_assert; - calculations shared by compile-time and runtime code.
const versus constexpr
Both prevent changing a variable after initialization, but they express different guarantees:
| Declaration | Meaning |
|---|---|
const int value |
value cannot be changed through this name. |
constexpr int value |
value is a compile-time constant and is also const. |
This does not compile because a runtime result cannot initialize a constexpr
variable:
Use const for a runtime value that must not change. Use constexpr when the
value must be available during compilation.
A constexpr function can run at runtime
Declaring a function constexpr does not force every call to happen during
compilation:
The same function supports both calls. The arguments and the surrounding context determine whether compile-time evaluation is required.
Require a compile-time result
Store the result in a constexpr variable, use it in static_assert, or
use it in another context that requires a constant expression.
Compile-time validation with static_assert
static_assert checks a Boolean expression while compiling:
It creates no runtime test code. Use it for rules that the compiler can prove. Keep runtime tests for values that arrive from files, users, sensors, or the network.
More than one statement
In C++20, a constexpr function can contain normal control flow when every
operation used during compile-time evaluation is allowed in a constant
expression:
Do not make a function complicated merely because modern constexpr permits
it. A small, pure calculation is easiest to understand and test.
constexpr objects
A class can support compile-time construction and member functions:
This is useful for small value types. It does not mean every class should be rewritten for compile-time use.
Related C++20 keywords
These keywords solve different problems:
| Keyword | Meaning |
|---|---|
constexpr |
A value or function can participate in compile-time evaluation. |
consteval |
Every call to the function must be evaluated at compile time. |
constinit |
A static or thread-local variable must be statically initialized. |
Use consteval only when a runtime call would be meaningless or invalid.
constinit does not make a variable immutable; it controls initialization.
When not to use constexpr
Keep an ordinary function when:
- its inputs only exist at runtime;
- it performs input/output;
- compile-time use provides no practical value;
- adding compile-time constraints makes the code harder to understand.
constexpr is a guarantee and design signal, not a command to move as much work
as possible into compilation.
Predict the behavior
Does this program compile, and what does it print?
Show the answer
It compiles and prints:Compile the examples
Use the complete constexpr_demo.cpp and
exercise_starter.cpp files.
Small coding exercise
Open code/constexpr/exercise_starter.cpp. Add:
- A
constexpr bool is_even(int value)function. - A
constexpr int clamp_percentage(int value)function that returns a value from 0 through 100. - At least two
static_assertchecks for each function. - One runtime call using a value entered by the user.
Show one possible solution
Quiz
1. What does constexpr mean for a function?
2. Which declaration requires a compile-time value?
3. What happens if a static_assert condition is false?
4. Which keyword requires every function call to be evaluated at compile time?
5. Which value should usually remain a runtime const value?
Code-review challenge
A programmer says this calculation is guaranteed to happen during compilation:
Are they correct?
Show the review
No. `input` is only known at runtime, so this call to `square` runs at runtime. The function is allowed to run at compile time, but `constexpr` does not require all calls to do so. If the input is fixed and the result must be computed during compilation, use a constant expression: Do not replace the original code with `consteval`: a value read from the user cannot be evaluated during compilation.Completion check
You should now be able to:
- explain the difference between
constandconstexpr; - write a
constexprfunction usable at compile time and runtime; - require compile-time validation with
static_assert; - explain why a particular call runs at runtime;
- distinguish
constexpr,consteval, andconstinit.
Next, continue with compile-time programming or learn how
std::optional represents a value that may be absent.