constexpr int square(int x) { return x * x; }
constexpr int n = square(5); // computed at compile time
C++
Topics in this category
Casting & Conversions
Compilation & Linking
Concepts & Constraints
Concurrency
Const Correctness
Constexpr & Compile-Time
Coroutines
Enums & Enum Classes
Exception Handling
I/O Streams
Lambda Expressions
Memory Management
Modern C++
Move Semantics
Namespaces
OOP & Classes
Operator Overloading
Preprocessor & Macros
RAII & Smart Pointers
Ranges & Views
C++
Constexpr & Compile-Time
constexpr indicates that a value or function can be evaluated at compile time. A constexpr variable is a compile-time constant; a constexpr function can be evaluated at compile time when given constant arguments (and at run time otherwise). It enables computations to move from run time to compile time, improving performance and enabling constant expressions.
Real-world example
A constexpr function computes a lookup table at compile time so no runtime cost is incurred.
Templates
Modern C++
Constexpr & Compile-Time
const means the value won't change after initialization but it may be initialized at run time. constexpr means the value is a compile-time constant and must be initializable at compile time. All constexpr objects are const, but not all const objects are constexpr. Use constexpr when you need a true compile-time constant.
const int a = getValue(); // runtime init, immutable
constexpr int b = 10 * 5; // compile-time constant
Real-world example
An array size must be constexpr, so a const initialized from a runtime call can't be used for it.
Const Correctness
Constexpr & Compile-Time
Constexpr & Compile-Time
A constexpr function must be able to produce a compile-time constant when given constant arguments: historically its body was limited (single return in C++11), but C++14+ allows loops, local variables, and multiple statements. It can't have side effects that aren't allowed in constant evaluation (no I/O, no non-constexpr calls, no undefined behavior). If used in a runtime context, it runs normally.
constexpr int fib(int n) {
int a = 0, b = 1;
for (int i = 0; i < n; ++i) { int t=a; a=b; b=t+b; }
return a;
}
Real-world example
A constexpr fib is used to size a compile-time array, forcing the computation into the build.
Templates
Constexpr & Compile-Time
Constexpr & Compile-Time
consteval declares an 'immediate function' that must be evaluated at compile time—every call must produce a constant, otherwise it's a compile error. Unlike constexpr (which may run at compile or run time), consteval guarantees compile-time evaluation, useful for functions that must never incur runtime cost or that generate compile-time-only values.
consteval int cube(int x) { return x*x*x; }
constexpr int c = cube(3); // OK
// int r = cube(runtimeVar); // error: not constant
Real-world example
A consteval function guarantees a hash or ID is computed at compile time, never at runtime.
Modern C++
Constexpr & Compile-Time
Constexpr & Compile-Time
constinit guarantees that a variable with static/thread storage duration is initialized at compile time (constant initialization), preventing the 'static initialization order fiasco' for that variable. Unlike constexpr, the variable need not be const—it can be modified at run time—but its initial value must be a constant expression.
constinit int counter = 0; // guaranteed constant-initialized
// may be modified later at runtime
Real-world example
A global initialized with constinit avoids initialization-order bugs while still being mutable at runtime.
Modern C++
Constexpr & Compile-Time
Constexpr & Compile-Time
Moving work to compile time (via constexpr/consteval, templates) removes runtime cost, enables constants for array sizes and template arguments, and can catch errors earlier. Trade-offs include longer compile times, increased code/complexity, and debugging difficulty of compile-time logic. It's most valuable for hot constants, lookup tables, and configuration known at build time.
constexpr auto table = makeSineTable(); // built at compile time
Real-world example
Precomputing a CRC or sine table at compile time eliminates its runtime initialization cost.
Templates
Constexpr & Compile-Time
Constexpr & Compile-Time
Yes. Constructors and member functions can be constexpr, allowing literal (constexpr-constructible) types to be created and manipulated at compile time. C++20 greatly expanded this: constexpr std::vector and std::string, constexpr dynamic allocation (that doesn't escape constant evaluation), and constexpr algorithms, enabling far richer compile-time programming.
struct Point {
int x, y;
constexpr Point(int a, int b) : x(a), y(b) {}
constexpr int sum() const { return x + y; }
};
constexpr Point p(1,2); static_assert(p.sum()==3);
Real-world example
A constexpr geometry type computes fixed layout coordinates entirely at compile time.
OOP & Classes
Constexpr & Compile-Time
Constexpr & Compile-Time
static_assert performs a compile-time check: if the constant boolean condition is false, compilation fails with the given message. It's used to enforce assumptions (type sizes, template constraints, configuration invariants) at build time rather than discovering them at run time.
static_assert(sizeof(int) == 4, "int must be 32-bit");
Real-world example
A static_assert guards that a struct's size matches a wire protocol, failing the build if it drifts.
Templates
Constexpr & Compile-Time
Constexpr & Compile-Time
if constexpr (C++17) is a compile-time conditional: only the taken branch is instantiated/compiled, and the other is discarded. It's invaluable in templates to select behavior based on type traits without needing separate overloads or SFINAE, keeping generic code readable while avoiding compilation of invalid branches.
template <class T>
auto value(T t) {
if constexpr (std::is_pointer_v<T>) return *t;
else return t;
}
Real-world example
if constexpr lets one template function dereference pointers but return values directly for non-pointers.
Templates
Modern C++
Constexpr & Compile-Time
By evaluating expressions during compilation, constexpr moves computation out of the runtime path—constants, lookup tables, and derived values are baked into the binary, eliminating startup or per-call cost. It also enables the compiler to optimize based on known values. The runtime simply uses the precomputed results.
constexpr int limit = compute(); // no runtime work to get 'limit'
Real-world example
Computing configuration constants at compile time removes their setup cost from application startup.
Constexpr & Compile-Time
Templates
Constexpr & Compile-Time