Step 4 of 8
constexpr
Templates run the type machinery at compile time. constexpr lets ordinary calculations run at compile time too. A constexpr function can be evaluated by the compiler whenever its arguments are compile-time constants, and the result is baked into the program as a number.
#include <array>
#include <iostream>
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
}
constexpr int cube(int x) { return x * x * x; }
static_assert(factorial(5) == 120); // checked while compiling
static_assert(cube(3) == 27, "cube is broken");
int main() {
std::array<int, cube(2)> slots{}; // size 8, known at compile time
std::cout << slots.size() << "\n";
constexpr int f6 = factorial(6); // computed by the compiler
std::cout << f6 << "\n";
int n = 4; // a run-time value...
std::cout << factorial(n) << "\n"; // ...so this call runs normally
}
8
720
24
How it works
static_assert(condition)is checked by the compiler. If it's false, the program doesn't compile at all. It's a test that runs before your program exists.- Anything that needs a compile-time constant, like a
std::arraysize or a template argument, can use aconstexprfunction call. - The same function still works at run time with normal variables, as
factorial(n)shows. - Since C++14,
constexprfunctions can have loops, local variables andifstatements. They can't do things like I/O or (before C++20) heap allocation.
Your task: power
Multiply result by base, exp times, starting from result = 1. Mark the function constexpr; the tests use static_assert, so without it the tests won't even compile. Use long long for the result so big powers fit.
Your turn: write constexpr long long power(long long base, int exp). The tests include static_asserts, so if your function can't run at compile time, it won't even compile.