A constexpr function can be used in non-constant-expression context as shown below.
constexpr int min(int a, int b)
{
return a < b ? a : b;
}
constexpr int result{min(1, 2)};
int value{min(3, 2)};So, it can be used in both places. This is very useful as we do not need to create double functions for the same purpose. Now let’s take a look at another example where constexpr function calls normal function.
int getMax(int a, int b)
{
return a < b ? b : a;
}
constexpr int max(int a, int b)
{
return getMax(a, b);
}
int value{max(1, 2)}; // works
constexpr int result{max(1, 2)}; // compiler failsIf we compile this program with C++ standard prior to C++23, it would fail. In C++23 prior versions, this is an ill-formed program because there is no set of arguments that will make max() evaluated at compile-time. If we add this condition as shown below, it compiles successfully. However, we still can’t use this function in constant expression context.
constexpr int max(int a, int b)
{
if (a < 0) // we can put any condition
return 0;
return getMax(a, b);
}With this we have some set of arguments (where a is negative) where this function can be evaluated at compile time and compiler can successfully compile this function.
int value{max(1, 2)}; // works
constexpr int result{max(1, 2)}; // compiler failsThis restriction was revoked in C++23 (P2448R1), so we can remove that condition and compiler will not complain about that function.
How this is useful? Well, it allows us to use constexpr function in non-constant expression context. It will still fail for constant expression context, which is right.