2

I don't know if it is meaningful to define a variable with constexpr in a function.

void func() { static const int i = 1; }
void func2() { constexpr const int i = 1; }

static const in a function would be initialized on the first function call, how about constexpr in a function? I know that constexpr specifies that the object should be available during compilation. So does it mean that the variable i in the func2 would be evaluated at compile time whereas the i in the func wouldn't?

Yves
  • 11,597
  • 17
  • 83
  • 180
  • For types that have no side effects when constructed and destructed (don't do IO, or similar) the outcome of the generated binary might become the same due to optimizations the compiler can do. From the perspective of the language, they express two different things. – t.niese Jul 28 '21 at 07:17
  • Does [Does static constexpr variable inside a function make sense?](https://stackoverflow.com/questions/13865842/does-static-constexpr-variable-inside-a-function-make-sense) answer your question? "_note that `static` and `constexpr` are completely independent of each other. `static` defines the object's lifetime during execution; `constexpr` specifies that the object should be available during compilation. Compilation and execution are disjoint and discontiguous, both in time and space. So once the program is compiled, `constexpr` is no longer relevant._" – Ted Lyngmo Jul 28 '21 at 07:19
  • _"`static const` in a function would be initialized on the first function call"_ — Note that this is basically true only for non-trivial types. For trivial ones, they binary representation is hardcoded in the program. Live demo: https://godbolt.org/z/hxPTGoanK (there is no initialization of `i` in `g` at the machine code level). – Daniel Langr Jul 28 '21 at 07:21
  • In fact I care about the time of evaluation. I just re-edited my question. – Yves Jul 28 '21 at 07:36
  • In most cases ````constexpr```` is the preferred solution. It is a compile time constant. Additional info: ````const```` after ````constexpr```` is not needed. And, reading your question, if you can define a ````constexpr```` in a function body, then do it, because it will narrow the scope. – A M Jul 28 '21 at 07:43

2 Answers2

2

There is an important difference.

A static local variable is initialized on the first call, so that in subsequent calls its declaration is no longer used. In particular, the constructor of the static local variable is called only once. A static const is a static variable which is also a constant: thus, its value, once initialized on the first call, cannot be changed anymore.

A constexpr expression is an expression that can be evaluated at compile time. Because of that, a constexpr variable can, for instance, be used as nontype template parameter.

Generically, you would not be able to use a simple static const as template parameter, because even if it is a const, its actual value might not be determined at compile time; for example:

void f(int x)
{
     static const i = x;
     std::array<int, i> a; // Compile error!
}

Though, variables of integral type, that are initialized as constant expression can still be used as nontype template parameters. So, in the code of the question, the variable i of func2 could be used as nontype template parameter.

francesco
  • 7,189
  • 7
  • 22
  • 49
  • _"You would not be able to use a simple static const as template parameter"_ — Sorry, but this is incorrect (if you actually mean _"as template argument"_). Live demo: https://godbolt.org/z/vf1GYf7x4. – Daniel Langr Jul 28 '21 at 07:26
  • 1
    @DanielLangr, Worth noting that this applies only to integral types because they had special rules before `constexpr` existed. Other types behave as described. – chris Jul 28 '21 at 07:30
  • Will `constexpr` make the variable `i` in `func2` to be evaluated at compile time? Or both `i` are evaluated at compile time? – Yves Jul 28 '21 at 07:38
  • @DanielLangr Mmm, correct, I did not know that. I amended the answer. – francesco Jul 28 '21 at 07:44
  • An especially notable use for this is that `constexpr` variables can be used in `if constexpr` conditionals, [like so](https://godbolt.org/z/d3hWhnq36). While this specific example is the same with either `constexpr` or `const`, you have no guarantee that this will hold true with _every_ example. Only true constant expressions are guaranteed to be available to use like this at compile time, and `const` doesn't require the initialiser to be a constant expression, after all. – Justin Time - Reinstate Monica Aug 13 '23 at 02:32
-1

There are some differences. Initialization is one fo them. Let's rename the variables so that we can talk about them more easily:

void func() { static const int i = 1; } //internal linkage
void func2() { constexpr const int a = 1; } //external linkage
  1. Initialization

In the above code, only a is a compile-time constant. It shall be initialized at compile time. The idea is to spend time in compilation and save time at run time. However, i may be initialized at compile time or run time.

As to which you should use? Use whichever meets your needs.

  • They are local variables in functions so linkage does not apply to them. `static` only defines linkage on file-scope, which this is not. – Jan Hudec Jul 28 '21 at 07:51
  • Thank you for pointing it out. I have edited my answer and only limited it to the initialization difference. – Mushahid Hussain Jul 28 '21 at 07:59