constexpr
in C++ allows expressions to be evaluated at compile time rather than runtime. This feature helps optimize programs by computing constant values during compilation and enables creating objects with immutable values that the compiler can use in constant expressions. Using constexpr with functions and variables encourages safer and more efficient code by catching errors early and reducing runtime overhead.
Compared to const
:
const
marks data as read-only after initialziation, but its value is not necessarily known during compile time.constexpr
provides a stronger compile-time guarantee.constexpr
variables are alwaysconst
constexpr
functions and pointers doesn’t make everythingconst
- Use
constexpr
in compile-time evaluations:static_asserts
- template parameters
constexpr
Functions
A constexpr
function is NOT a const
function, nor does it imply that its parameters or local const are const. It merely guarantees that when provided with constexpr
arguments, the function can be evaluated at compile time.
One example is: without constexpr
function, static_assert
would throw an error:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
// A constexpr function to compute factorial of n
int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
// Compile-time evaluation using static_assert, but this would throw an error
static_assert(factorial(5) == 120, "factorial(5) should be 120");
return 0;
}
With constexpr
, static_assert
is happy. The function can be evaluated during runtime too:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
// A constexpr function to compute factorial of n
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
// Compile-time evaluation using static_assert
static_assert(factorial(5) == 120, "factorial(5) should be 120");
// Runtime usage: even though the function is constexpr,
// it can be used with values not known until runtime.
int runtime_value = 6;
int runtime_result = factorial(runtime_value);
std::cout << "Factorial of " << runtime_value << " is " << runtime_result << "\n";
return 0;
}
Constexpr Improvements [C++20]
constexpr
rules in cpp20 are relaxed. Operations like allocation, resizing, element access on vectors are allowed, as long as those operations themselves meet the requirements for constexpr evaluation
While vectors
still can’t be compiled on my C++20 compiler, one can use std::array
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <numeric>
#include <array>
int main() {
std::cout << std::endl;
constexpr std::array myArray{1, 2, 3, 4, 5}; // (1)
constexpr auto sum = std::accumulate(myArray.begin(), myArray.end(), 0); // (2)
}