constexpr in C++ is used to declare values, functions, and certain constructors that can be evaluated at compile time. It tells the compiler that an expression is intended to be a constant expression whenever possible. This makes the program more expressive and often safer because some computations can be checked or completed before the program even runs.
At first glance, constexpr may look similar to const, but the idea is more specific. A const object is read-only after initialization, while a constexpr object is expected to be usable as a compile-time constant. This difference matters in array bounds, template arguments, switch labels, and many performance-friendly expressions. In this article, we will understand what constexpr means, how it works, where it is used, and what mistakes beginners should avoid.
What Is constexpr in C++?
constexpr is a keyword that marks something as eligible for compile-time evaluation. If the compiler has enough information, it can compute the result during compilation instead of waiting until runtime. This applies most commonly to variables and functions.
| Use | Meaning | Example |
|---|---|---|
constexpr variable | A value known at compile time | constexpr int size = 10; |
constexpr function | A function that can produce a compile-time result | constexpr int square(int x) |
constexpr constructor | Allows object creation in constant expressions when rules are satisfied | constexpr Point(int x, int y) |
constexprexpresses compile-time intent. It tells the compiler that a value or function should be usable as a constant expression when the inputs allow it.
Why constexpr Is Important in C++
- It allows values to be computed during compilation.
- It makes code safer where a true compile-time constant is required.
- It helps document programmer intent clearly.
- It can reduce runtime work in appropriate situations.
- It is widely used in modern C++ libraries and template-based code.
Suppose a program needs a fixed array size, a bit mask, or a constant used in multiple expressions. If the value is truly known in advance, using constexpr makes that knowledge explicit. The compiler can then treat the value as a genuine compile-time entity instead of just a read-only variable.
constexpr Variable in C++
A constexpr variable must be initialized with a constant expression. That means the compiler must be able to determine its value during compilation.
constexpr int maxStudents = 60;
constexpr double pi = 3.141592653589793;Both of these values are known immediately, so the compiler can store and use them as compile-time constants. They are not just read-only values. They are also valid constant expressions.
| Declaration | Valid? | Reason |
|---|---|---|
constexpr int a = 10; | Yes | The initializer is a constant expression |
int x = 5; constexpr int b = x; | No | x is not a compile-time constant expression |
const int c = 7; constexpr int d = c; | Often yes if c itself is constant-expression friendly | The initializer may still qualify as a constant expression |
This is a key point: a constexpr variable cannot depend on an ordinary runtime value. If the value is not available during compilation, the declaration is invalid.
constexpr Function in C++
A constexpr function is a function that can be evaluated at compile time if it is called with constant-expression arguments. The same function may also run at runtime when the arguments are not compile-time constants. This dual nature is one reason constexpr is so useful.
constexpr int square(int x)
{
return x * x;
}Now the function can be used in a compile-time context when the input is known in advance.
constexpr int area = square(5);Because 5 is known during compilation, square(5) can also be computed during compilation. But if the argument comes from user input, the same function may execute at runtime instead.
Compile-Time Use and Runtime Use of constexpr Functions
One common source of confusion is that a constexpr function does not always run at compile time. It only does so when the context and arguments make that possible. Otherwise, it behaves like an ordinary function call at runtime.
#include <iostream>
constexpr int cube(int x)
{
return x * x * x;
}
int main()
{
constexpr int a = cube(3);
int n;
std::cin >> n;
int b = cube(n);
std::cout << a << std::endl;
std::cout << b << std::endl;
return 0;
}In this example, cube(3) can be evaluated at compile time, while cube(n) must run at runtime because n comes from user input. The function itself supports both situations.
Difference Between const and constexpr in C++
const and constexpr are related, but they are not identical. A const object cannot be modified after initialization. A constexpr object is also constant, but it must additionally be usable as a compile-time constant expression.
| Feature | const | constexpr |
|---|---|---|
| Read-only after initialization | Yes | Yes |
| Compile-time constant required | Not always | Yes |
| Can be initialized from runtime value | Yes | No |
| Suitable where constant expression is required | Not always | Yes |
For example, if you write const int value = input;, the value is read-only but still depends on runtime input. That means it is not a compile-time constant. By contrast, constexpr int value = 10; is both read-only and compile-time known.
Where constexpr Is Commonly Used in C++
- Array sizes and fixed compile-time limits
- Template arguments and metaprogramming contexts
- Mathematical helper functions used with constant inputs
- Switch case labels and bit-mask style values
- Configuration values that must be known during compilation
These use cases matter because some parts of C++ require constant expressions rather than just read-only values. constexpr is designed specifically for those situations.
constexpr with Arrays in C++
Array-related examples are often used to introduce constexpr because fixed sizes are easy to understand. If a size is known at compile time, the compiler can treat it as a constant expression.
constexpr int size = 5;
int arr[size] = {1, 2, 3, 4, 5};Here, size is known during compilation, so it can be used wherever a compile-time constant is required by the language or the compiler rules in that environment.
constexpr Constructor in C++
Modern C++ also allows constructors to be marked constexpr when they satisfy the required rules. This lets objects be created in constant expressions.
class Point
{
public:
int x;
int y;
constexpr Point(int a, int b) : x(a), y(b) {}
};
constexpr Point p(2, 3);This makes the object p eligible to exist as a compile-time value, provided all the rules for constant evaluation are met. It is a good example of how constexpr is not limited to primitive types.
Rules and Limitations of constexpr in C++
Although constexpr is powerful, it is not magic. The compiler still enforces strict rules. A constexpr variable must have a compile-time initializer, and a constexpr function body must follow the rules supported by the language standard being used.
- A
constexprvariable needs a constant-expression initializer. - A
constexprfunction should be able to produce a constant expression when given constant inputs. - If the function call depends on runtime data, it cannot be evaluated at compile time in that call site.
- Older C++ standards had stricter rules for
constexprfunction bodies than newer standards.
That last point is important. The capabilities of constexpr became broader in later standards like C++14, C++17, and beyond. So when reading old material, you may notice more restrictions than in modern tutorials and compilers.
Common Mistakes with constexpr in C++
- Thinking
constexpris just another spelling ofconst. - Trying to initialize a
constexprvariable with runtime input. - Assuming a
constexprfunction always executes at compile time. - Using
constexprwhere the value is not truly meant to be a compile-time constant. - Ignoring the language-standard differences in older compiler modes.
Most beginner errors come from misunderstanding the phrase compile-time constant. If the compiler cannot know the value while compiling, then constexpr cannot be applied in the way you expect.
Best Practices for Using constexpr in C++
- Use
constexprwhen a value truly belongs to compile-time logic. - Prefer it for mathematical helper functions that work naturally with constant inputs.
- Do not force
constexpron values that are really runtime values. - Use clear naming so readers understand that a value is meant to be fixed and compile-time friendly.
- Remember that readability still matters more than using a modern keyword everywhere.
A Complete Example of constexpr in C++
#include <iostream>
constexpr int multiply(int a, int b)
{
return a * b;
}
int main()
{
constexpr int fixedValue = multiply(4, 5);
int userValue = 6;
std::cout << "Compile-time result: " << fixedValue << std::endl;
std::cout << "Runtime result: " << multiply(userValue, 3) << std::endl;
return 0;
}In this program, multiply(4, 5) can be evaluated during compilation, while multiply(userValue, 3) runs during execution because userValue is not known in advance. This shows the flexible role of constexpr functions in real code.
constexpr and Repeated Fixed Values
In larger codebases, constexpr is also useful for repeated fixed values that appear in formulas, configuration headers, lookup logic, and compile-time helper utilities. Instead of scattering raw literals across multiple files, a single constexpr definition can document the rule and keep every use consistent. This improves maintenance because if the fixed rule changes, the programmer updates one declaration instead of searching through many unrelated expressions. It also makes code review easier because readers can immediately see that the value belongs to compile-time program logic rather than temporary runtime state.
Frequently Asked Questions about constexpr in C++
Is every const variable also constexpr?
No. A const variable is only guaranteed to be read-only after initialization. It is not automatically guaranteed to be a compile-time constant expression.
Can a constexpr function run at runtime?
Yes. If the function is called with runtime data, the same function can execute at runtime. constexpr means it can be evaluated at compile time when the conditions are right.
Why do compilers care whether a value is known at compile time?
Because some parts of the language and many optimizations depend on constant expressions. A compile-time-known value gives the compiler stronger guarantees and more opportunities for checking and simplification.
Should I replace every const with constexpr?
No. Only use constexpr when the value is genuinely intended to be known at compile time. If a value is just read-only after runtime initialization, const is the more accurate choice.
Continue learning C++ in order
Follow the topic sequence with the previous and next lesson.