What are the advantages of using constexpr instead of consteval function?

329 Views Asked by At

This might seem the same question as What are the advantages of using consteval instead of constexpr function? but it is actually exactly the opposite:

Now that we have C++20 consteval, what are the (realistic) scenarios for which I would still need/create a constexpr function instead of consteval a function (or an ordinary function)?

I know that constexpr functions can also be called with parameters evaluated at run time, unlike consteval functions (see *** in the sample code), but why would I ever need that? I mean I can also use an ordinary function then.

int FunNormal()
{
    return 12345;
}    

consteval int FunConstEval(int p)
{
    return p+3;
}    

constexpr int FunConstExpr(int p)
{
    return p+3;
}    
    

int main() 
{
    // FunConstEval(FunNormal());               // illegal
    FunConstExpr(FunNormal());                  // legal, but why would I ever want to do this? ***
    
//    constexpr int a1 = FunNormal();           // illegal, obviously
//    constexpr int a1 = FunConstExpr(FunNormal());     // illegal
    constexpr int a2 = FunConstEval(1);     
    constexpr int a3 = FunConstExpr(1);     
}
2

There are 2 best solutions below

4
Jan Schultke On
FunConstExpr(FunNormal()); // legal, but why would I ever want to do this?

FunNormal might be a function that obtains its value from user input or another source which isn't available at compile time. As a commenter has pointed out, a constexpr function lets you do things like:

std::cin >> x;
std::cout << FunConstExpr(x);

There is no good reason to artificially restrict your function to only run at compile time, unless it is unimplementable at run-time.

consteval should only be used for things that must be evaluated at compile time. Some examples from the C++ standard library are:

These examples are all fairly rare and unusual. The vast majority of functions should be constexpr, not consteval.

0
Jarod42 On
  • FunNormal() can only be used at runtime
  • FunConstEval can only be used at compile time
  • FunConstExpr might be used in both (compile time in constant expression, else at runtime).

"Non-constexpr operations" are forbidden in consteval/constexpr functions.Those operations depend on standard used.

One additional restriction with consteval/constexpr functions is that they need to be defined where used (so mostly inline in header), whereas, for regular functions, we can separate declaration (header) and definition (source file).

So

  • If your function cannot be compile-time, it has to be regular one.
  • If your function has to be compile-time only, it has to be consteval function.
  • If your function has to be both, it has to be constexpr.

For other cases, you might choose

  • if function is only used in compile time context, constexpr or consteval.
  • if function is only used in runtime time context, constexpr or regular one.

For internal/private functions, do as your convenience. Having constexpr for functions only used at runtime is unneeded, but might allow compiler to signal non-constexpr operations inside the function.

Having consteval instead of constexpr would spot/prevent runtime usage.

For functions in public interface, and for not breaking backward compatibility, you might turn:

  • regular functions into constexpr ones.
  • consteval functions into constexpr ones.