constexpr
A constexpr
variable or function is one that can be evaluated at compile time. In particular, it can be used in constant expressions.
One place where constexpr
will be useful in the future is when we
start working with templates and want to compiler to do some
evaluations for us.
We can use constexpr
in place of const
to define constants, e.g.,
constexpr double pi{3.1415926535897932384626433};
An if constexpr
is a compile-time if-test. It essentially allows
you to template a general function and have the compiler write
specific versions based on the template parameters. One way this is
used is to cut out expensive computations if we know we won’t need
them, while still being able to write just a single implementation
that handles the general case.
Here’s a trivial example:
#include <iostream>
#include <cmath>
template <int do_deriv>
inline
void func(const double x, double& f, double& dfdx) {
f = std::sin(x);
if constexpr(do_deriv == 0) {
dfdx = 0.0;
} else {
dfdx = std::cos(x);
}
}
int main() {
double x = 1.0;
double f;
double dfdx;
func<0>(x, f, dfdx);
std::cout << "with template parameter = 0: " << f << " " << dfdx << std::endl;
func<1>(x, f, dfdx);
std::cout << "with template parameter = 1: " << f << " " << dfdx << std::endl;
}
We can also use it to define a function where we want the function to
be evaluated at compile time. For example, here’s a function that
computes integer powers, which can be faster than using
std::pow()
.
#include <iostream>
template <int n>
inline
constexpr double power(double x) {
if constexpr (n < 0) {
return 1.0 / power<-n>(x);
} else if constexpr (n == 0) {
return 1.0;
} else {
return x * power<n-1>(x);
}
}
int main() {
double x{3.5};
std::cout << power<2>(x) << std::endl;
}