constexpr in C++

The constexpr keyword is a relatively new addition to C++. You need to use the C++11 standard in order to compile the following programs:

g++ -std=c++11 test.cpp

Let’s examine what the keyword is about. There’s no difficulty to split it into words to get the meaning: constant expression.

In practice, constant expression means that the expression can be computed at compile time. Take, for example, the following constant:

#include <iostream>
#include <math.h>

const auto three_quaters_of_pi = 3 * M_PI / 4;

int main() {
    std::cout << three_quaters_of_pi << std::endl;
}

The selected name is a constant, and it can be computed at compile time, as all the parts of the expression are constants. But what if one of them is a function:

#include <iostream>
#include <math.h>

int square(int x) {
    return x * x;
}

const auto three_quaters_of_pi = 3 * M_PI / square(2);

int main() {
    std::cout << three_quaters_of_pi << std::endl;
}

The three_quaters_of_pi is still a constant declared with the const keyword. The code compiles with no warnings or errors and it runs as expected.

Can you answer the question of when the square() function was called? Add a debug output in it:

int square(int x) {
    std::cout << "square() called\n";
    return x * x;
}

Compile it and run:

$ ./a.out 
square() called
2.35619 

The function was called at runtime, so that’s when the constant was initialised.

To make sure the whole expression is computed at compile time, use constexpr:

constexpr auto three_quaters_of_pi = 3 * M_PI / square(2);

This small change requires all parts of the expression to be available at compile time. As soon as the function is used, it also has to be declared as constexpr:

#include <iostream>
#include <math.h>

constexpr int square(int x) {
    return x * x;
}

constexpr auto three_quaters_of_pi = 3 * M_PI / square(2);

int main() {
    std::cout << three_quaters_of_pi << std::endl;
}

Without the constexpr, the compiler complains:

error: constexpr variable 'three_quaters_of_pi' must be initialized by a constant expression

Notice that you cannot anymore do any side effects from such function. It has to be executed at compile time, not at runtime, so you cannot print from it. The compiler throws an error otherwise:

note: non-constexpr function 'operator<<<std::__1::char_traits<char> >' cannot be used in a constant expression

Leave a Reply