What is if consteval needed for?
Asked Answered
L

1

29

C++23 is going to introduce if consteval. Where is this going to be used and how does it differ from constexpr if?

Latinalatinate answered 1/7, 2021 at 15:29 Comment(0)
L
35

if consteval detects if a constexpr function is called in a constant expression context. The proposal motivates its introduction for the case where one intends to call a consteval function from a constexpr function. To understand what that means we consider the following example.

Let's assume we have a consteval function f:

consteval int f( int i )
{ ... }

f can only be called in a constant expression. On the other hand a constexpr function g can be called either in a constant expression or at run time. That depends on if the arguments to g are known at compile time or not. Now, calling f from g if g is called at compile time can be done as follows.

constexpr int g( int i )
{
  if consteval {    //1
    return f( i );
  }
  else { 
    return fallback();
  }
}

Here if consteval in line //1 triggers if g is called in a constant expression. Note that there must be no condition in //1. Also the braces after if consteval are obligatory.

C++20 introduced is_constant_evaluated for detecting whether a function call occurs within a constant-evaluated context. Using is_constant_evaluated in our example leads to a subtle bug. I.e. exchanging //1 by if constexpr (std::is_constant_evaluated()) { results in is_constant_evaluated to always return true.

Latinalatinate answered 1/7, 2021 at 15:29 Comment(5)
This last is because is_constant_evaluated isn't giving you information on the entire body of g() but on the controlling expression of if constexpr ?Proliferate
The issue isn't so much that if constexpr (is_constant_evaluated()) is a bug (it is, but compilers warn, so meh), but that even with if (is_constant_evaluated()) you cannot call f(i) there.Flare
The thing of constexpr functions is that their constexpr-ness doesn't only depend on their arguments, but also on the context they are being called from. is_constant_evaluated() likes constexpr int x = f(5); but not int x = f(5);.Phrasing
and also why cannot we do at least this? constexpr int g( int i ) { if consteval { static_assert( i < ... ); ... } ... } If we know that something is evaluated @ compile time, why not treat the values accordingly?Discordance
Good idea, Alex.Wittie

© 2022 - 2024 — McMap. All rights reserved.