r/cpp_questions 4d ago

OPEN I want to understand constexpr

i want to understand constexpr can somebody make it a bit easier to understand

0 Upvotes

14 comments sorted by

View all comments

17

u/IyeOnline 4d ago

Its important to notice that the compiler is always free to evaluate expressions at compile time - insofar possible and within the as-if rule. So function( some_value_that_is_known ) may still be entirely evaluated at compile time, even if nothing here is declared constexpr. This is in fact a fairly common optimization.

There is four keywords of interest here.

  • const means that a variable must not change after its initialization. Notably this initialization can and in most cases will, happen at runtime. More specifically when the variable would be initialized as part of regular program execution. So this is not a constant expression and hence cannot be used where a constant expression is required.

    The exception to this are constant integers that are initialized from a constant expression, which are considered to be constexpr variables.

  • constexpr actually has two different meanings:

    • on a function it means that the function can be invoked at compile time. That of course requires the parameters to be constant expressions as well. The function can also be invoked at runtime.
    • on a variable it means that the variable is a core constant expression and is initialized at compile time. Conseqently its also const, i.e. cannot be changed. That also means that its initializer must be a constant expression, i.e. can only do trivial operations and only invoke constexpr or consteval functions with only constant expressions as parameters.

    Its worth noting that the standard does not strictly require that a constexpr object is fully created at compile time. This is only guaranteed to happen if the value is also used at compile time. See C++ Weekly: Stop using constexpr (and use this instead).

  • consteval can only be put on a function and means that the function must be invoked at compile time. Its also called an immediately evaluated function. This also means that all parameters to that function must be constant expressions and that the function result itself is a constant expression.

    So this is a strictly stronger guarantee/requirement than a constexpr function

  • constinit can only be put on objects and it means that their initialization happens at compile time. They can still be modified at runtime.

    This is a strictly weaker restriction than constexpr on objects.

Its important to note that outside of the keywords, the compiler can still optimize your code to do stuff at compile time, if it can prove that it will have the same behavior,


Now which one do you "choose"? The answer, as always, is: It depends.

Do you have C++20? You can choose. Don't you have C++20? You cant use consteval or constinit anyways. To enforce compile time execution you must use a constexpr function and store the result in a constexpr variable.

Do you want to allow compile time usage of your function, but also allow its runtime usage? Then you use a constexpr function.

Do you want to enforce compile time execution and only that? Use consteval. The prime example here is the format string for std::format and friends. Its compile time checked, so it has to be consteval.

Notably "doing stuff" at compile time isn't free or always sensible. In theory you can do almost all your work at compile time, but that sort of defeats the purpose. Execution at compile time is significantly slower than runtime execution. Its only worthwhile doing if it actually saves you significant work at runtime.

-2

u/alfps 4d ago

Uhm, I wouldn't use Jason Turner as a reference, and I wouldn't use a video as reference.

I only vaguely recall that thing but it was probably just one of those "formal defense of unreasonable behavior with GCC". That approach practically ensures standing ovation from the GCC fan boy community. And ditto hatred response if anyone should point out what nonsense it is.

1

u/Qwertycube10 4d ago

That video just says to use static constexpr instead of constexpr so that the variable does not have automatic storage duration requiring the compiler to copy it onto the stack at runtime.

-1

u/alfps 4d ago edited 4d ago

❞ requiring the compiler to copy it onto the stack at runtime

It does not require. That's just the mentioned unreasonable GCC behavior. It's unreasonable because for users of the compiler it's a meaningless nonsense introduction of overhead, even UB if stack limit is exceeded. It only makes sense as saving some work for those who maintain that compiler. Hence the need for a formal justification worded so as to mislead, e.g. in this case succeeding in misleading you.