C++ constexpr constexpr functions


Example

A function that is declared constexpr is implicitly inline and calls to such a function potentially yield constant expressions. For example, the following function, if called with constant expression arguments, yields a constant expression too:

C++11
constexpr int Sum(int a, int b)
{
    return a + b;
}

Thus, the result of the function call may be used as an array bound or a template argument, or to initialize a constexpr variable:

C++11
int main()
{
    constexpr int S = Sum(10,20);
   
    int Array[S];
    int Array2[Sum(20,30)]; // 50 array size, compile time
}

Note that if you remove constexpr from function's return type specification, assignment to S will not work, as S is a constexpr variable, and must be assigned a compile-time const. Similarly, size of array will also not be a constant-expression, if function Sum is not constexpr.

Interesting thing about constexpr functions is that you may also use it like ordinary functions:

C++11
int a = 20;
auto sum = Sum(a, abs(-20));

Sum will not be a constexpr function now, it will be compiled as an ordinary function, taking variable (non-constant) arguments, and returning non-constant value. You need not to write two functions.

It also means that if you try to assign such call to a non-const variable, it won't compile:

C++11
int a = 20;
constexpr auto sum = Sum(a, abs(-20));

The reason is simple: constexpr must only be assigned a compile-time constant. However, the above function call makes Sum a non-constexpr (R-value is non-const, but L-value is declaring itself to be constexpr).


The constexpr function must also return a compile-time constant. Following will not compile:

C++11
constexpr int Sum(int a, int b)
{
    int a1 = a;     // ERROR
    return a + b;
}

Because a1 is a non-constexpr variable, and prohibits the function from being a true constexpr function. Making it constexpr and assigning it a will also not work - since value of a (incoming parameter) is still not yet known:

C++11
constexpr int Sum(int a, int b)
{
   constexpr int a1 = a;     // ERROR
   ..

Furthermore, following will also not compile:

C++11
constexpr int Sum(int a, int b)
{
   return abs(a) + b; // or abs(a) + abs(b)
}

Since abs(a) is not a constant expression (even abs(10) will not work, since abs is not returning a constexpr int !

What about this?

C++11
constexpr int Abs(int v)
{
    return v >= 0 ? v : -v;
}

constexpr int Sum(int a, int b)
{
    return Abs(a) + b;
}

We crafted our own Abs function which is a constexpr, and the body of Abs also doesn't break any rule. Also, at the call site (inside Sum), the expression evaluates to a constexpr. Hence, the call to Sum(-10, 20) will be a compile-time constant expression resulting to 30.