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:
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:
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:
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:
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:
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:
constexpr int Sum(int a, int b)
{
constexpr int a1 = a; // ERROR
..
Furthermore, following will also not compile:
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?
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
.