Constexpr was introduced in C++11 to enable compile-time evaluation of expressions, functions, and objects whenever possible. By performing computations during compilation instead of execution, constexpr can improve program efficiency and allow values to be used in contexts that require compile-time constants.
- Enables computations to be evaluated at compile time
- Helps reduce runtime overhead and improve performance
- Allows functions and variables to be used in constant expressions
#include <iostream>
constexpr int product(int x, int y) { return (x * y); }
int main()
{
constexpr int x = product(10, 20);
std::cout << x;
return 0;
}
Output
200
Explanation
- The product() function is declared as constexpr.
- Since the arguments are known at compile time, the result is computed during compilation.
- The variable x becomes a compile-time constant with the value 200.
Requirements for constexpr Functions (C++11)
In C++11, a constexpr function must satisfy the following conditions:
- The function body can contain only a single return statement.
- It can use only constant expressions and constant global variables.
- It can call only other constexpr functions.
- The return type cannot be void.
- Loops, local variables, and many operations were not allowed.
Note: Many of these restrictions were removed in C++14, making constexpr functions much more flexible.
Using constexpr for Compile-Time Array Sizes
One of the major advantages of constexpr is that it allows function results to be used where a compile-time constant is required.
constexpr int product(int x, int y) { return (x * y); }
int main()
{
int arr[product(2, 3)] = {1, 2, 3, 4, 5, 6};
std::cout << arr[5];
return 0;
}
Output
6
Explanation
- product(2, 3) is evaluated at compile time.
- The result (6) is used as the array size.
- This allows functions to participate in compile-time array declarations.
Using constexpr for Unit Conversion
constexpr is useful for mathematical conversions and calculations where the inputs may be known at compile time.
#include <iostream>
using namespace std;
constexpr double PI = 3.14159265359;
constexpr double ConvertDegreeToRadian(const double& dDegree)
{
return (dDegree * (PI / 180));
}
int main()
{
auto dAngleInRadian = ConvertDegreeToRadian(90.0);
cout << "Angle in radian: " << dAngleInRadian;
return 0;
}
Output
Angle in radian: 1.5708
Explanation
- PI is declared as a compile-time constant.
- ConvertDegreeToRadian() can be evaluated during compilation when given constant arguments.
- This improves readability without sacrificing performance.
constexpr Constructors
A constructor declared with the constexpr specifier is known as a constexpr constructor. It allows objects to be created and initialized at compile time when provided with constant expressions.
Requirements for constexpr constructors
- The class must not have virtual base classes.
- Constructor arguments must be usable in constant expressions.
- The constructor cannot be a function-try-block.
- A constexpr constructor is implicitly inline.
#include <iostream>
// A class with constexpr
// constructor and function
class Rectangle
{
int _h, _w;
public:
// A constexpr constructor
constexpr Rectangle(int h, int w) : _h(h), _w(w) {}
constexpr int getArea() const { return _h * _w; }
};
// driver program to test function
int main()
{
// Below object is initialized at compile time
constexpr Rectangle obj(10, 20);
std::cout << obj.getArea();
return 0;
}
Output
200
Explanation
- Rectangle is initialized at compile time.
- getArea() is also evaluated at compile time.
- The resulting value can be used in constant expressions.
constexpr Vs inline Functions
Both constexpr and inline can reduce function call overhead, but they serve different purposes.
| constexpr | inline |
|---|---|
| Enables compile-time evaluation when possible. | Suggests that the compiler replace a function call with the function body. |
| Can be used in constant expressions. | Cannot be used as a compile-time constant expression by itself. |
| Can be applied to variables, functions, and constructors. | Primarily applies to functions. |
| Focuses on compile-time computation. | Focuses on reducing function call overhead. |
Note: A constexpr function is implicitly inline.
constexpr Vs const
Both const and constexpr are used to define values that should not change, but they differ in when those values are evaluated. const creates a read-only value, while constexpr guarantees that the value is computed at compile time.
| Feature | const | constexpr |
|---|---|---|
| Purpose | Makes a value read-only | Ensures value is known at compile time |
| Compile-time evaluation | Not guaranteed | Always guaranteed |
| Runtime evaluation | Allowed | Not allowed |
| Use in array size | Not reliable | Reliable |
| Use in switch cases | Not allowed | Allowed |
| Can be applied to functions | No | Yes |
| Performance benefit | No special benefit | Better optimization |
| Introduced in C++ | C++98 | C++11 |
| Relationship | May or may not be compile-time | Always compile-time constant |