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:

Listing 109 constexpr_example.cpp
#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().

Listing 110 powers.cpp
#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;

}