0

Why isn't constexpr guaranteed to run during compilation?

Additionally, why was consteval added instead of changing constexpr to guarantee a compile-time execution?

cigien
  • 57,834
  • 11
  • 73
  • 112
user904963
  • 1,520
  • 2
  • 15
  • 33
  • So... how would you write a container type that could be used at compile time *or* runtime? How would you write a function that could be used at compile time or runtime? There's nothing about computing, for example, the absolute value of a signed integer, that specifically *requires* compile-time execution. But you ought to be able to do it at compile-time too. – Nicol Bolas Mar 31 '22 at 02:10
  • @NicolBolas Thanks for the information. It's mind-blowing having a question about programming that fits the Q&A style of Stack Overflow is getting downvoted. That's the point of the website. Sorry for not knowing everything in the universe. – user904963 Mar 31 '22 at 02:27

2 Answers2

1

constexpr already guarantees compile-time evaluation when used on a variable.

If used on a function it is not supposed to enforce compile-time evaluation since you want most functions to be usable at both compile-time and runtime.

consteval allows forcing functions to not be usable at runtime. But that is not all that common of a requirement.


Here a modified answer, since technically constexpr and consteval are about whether or not certain evaluations are constant expressions or must be constant expressions. This does not mean that the compiler must evaluate these expressions at compile-time (as there couldn't possibly be any observable difference), however that's the intent:

constexpr already guarantees that the full-expression of initialization is a constant expression when used on a variable.

If used on a function it is not supposed to enforce evaluation in a constant expression at the call site since you want most functions to be usable both inside and outside constant expressions.

consteval allows forcing functions to be callable only as constant expressions. But that is not all that common of a requirement.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • So is `consteval` only used for functions to disable its use at runtime (not allowed on variables as `constexpr` guarantees compile-time computation)? That seems like a weird restriction, so I imagine there aren't many places where `consteval` is used. – user904963 Mar 31 '22 at 11:26
  • @user904963 As mentioned in the other answer there is currently only one use in the whole standard library: retrieving a source location, which is something that should always be resolved at compile-time. You can see in the [proposal for `consteval`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r3.html) that the main motivation are functions for compile-time reflection. You can also imagine e.g. functions generating compile-time constants like Pi from scratch that are too costly to execute at runtime, but that use case can also be solved with a `constexpr` variable instead. – user17732522 Mar 31 '22 at 17:33
  • "already guarantees compile-time evaluation when used on a variable." Is NOT true: The standard makes NO such guarantees as there is no such thing as "compile-time" in the language specification. What it does guarantee is that certain invocations result in constant-expressions. The compiler is still free to evaluate a `consteval` function at runtime - before the call to the main-function. Any sane compiler will not do that, but even they will at times not do it during compilation but linking as there is no way around that. – ABaumstumpf Aug 21 '23 at 16:53
  • 1
    @ABaumstumpf Yes that is true, I was oversimplifying in my answer. That caveat always applies when talking about anything being done "at compile-time" in C++ and I am myself not sure whether always adding it to every answer about compile-time evaluation is helpful or rather confusing, because the correct modification of the answer would be something like: – user17732522 Aug 21 '23 at 20:33
  • @ABaumstumpf "_constexpr already guarantees that the full-expression of initialization is a constant expression when used on a variable. If used on a function it is not supposed to enforce evaluation in a constant expression at the call site since you want most functions to be usable both inside and outside constant expressions. consteval allows forcing functions to be callable only as constant expressions. But that is not all that common of a requirement._" – user17732522 Aug 21 '23 at 20:33
  • i just think that stating that it guarantees compiletime-evaluation when that is not the case is misleading. It would be sufficient to just put "compiletime" in quotes and add a little clarifications at the end that this is what compilers do but that the language (sadly) makes no such promises. – ABaumstumpf Aug 21 '23 at 20:45
1

The language has specific linguistic restrictions that require certain expressions to be compile-time constant expressions. Template parameters, array sizes, and a few other locations specifically require a compile-time constant value. As such, if you apply constexpr to a variable, you did so with the explicit intention of using that variable in one of those places. So the language requires that it be a constant expression.

This is not the case for functions. There are (at present in C++) few language constructs in C++ that a function could use at compile time which are not also available to the compiled executable at runtime. That is, there isn't much a function could do at compile time which it could not also do at runtime.

If all of a compile-time function would execute just fine with runtime values, then there's no reason to require that functions which can run at compile-time must run at compile-time.

consteval was added to the language for the specific purpose of cases where only the compiler has certain information. As it stands, there is exactly one standard library function is consteval: std::source_location::current. This is because the information being queried (the location in source code of the function call) is only available to the compiler.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Question: Can I think that if I apply `constexpr` to a variable(not function), the value of the variable is fixed during compilation? When you said "if you apply constexpr to a variable, ... So the language requires that it be a constant expression", does it mean the C++ language standard _requires_ any compiler to make the variable set at compile-time? (is it guaranteed?) – starriet Jun 28 '23 at 23:06
  • @starriet nope, there is absolutely nothing in C++ that is guaranteed to happen at compile-time as the language does not have concepts like runtime or compile-time. It only guarantees that the evaluation of an immediate function is only performed in a constant expression. – ABaumstumpf Aug 21 '23 at 16:58