1

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);     
}
DanRechtsaf
  • 518
  • 3
  • 8

2 Answers2

5
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.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
  • I understand that calling a function taking a runtime parameter can't be consteval - (but works with constexpr). But then I can also use an ordinary function. So my question is why would I make a function constexpr if I sometimes want to call it with runtime parameters. Could make it an ordinary function instead. And if I really need compile time evaluation I can use consteval. – DanRechtsaf Aug 11 '23 at 11:20
  • 4
    @DanRechtsaf but if you need the same logic (potentially) both in compile and run time (e.g. in different code parts) - why should you have 2 separate functions ? That's what `constexpr` is for. – wohlstad Aug 11 '23 at 11:27
  • I often use `consteval` for helper functions I use inside metaprogramming blocks. The function could be used at runtime but its sole purpose is to be used inside `concept`s, type-traits or other compile time contexts. – Rerito Aug 11 '23 at 14:02
  • @DanRechtsaf, you'd need 2 distinct functions then; not even 2 overloads, because the inputs would have similar types. `constexpr` keyword allows you to define both functions simultaneously, with same name and signature. You can even devide the implementation with an `if consteval` clause; so that you can provide special optimizations for runtime case. – Red.Wave Aug 11 '23 at 18:01
2
  • 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.
Jarod42
  • 203,559
  • 14
  • 181
  • 302