3

What is the proper way to declare a constexpr constant in a source file? I'm split between two ways:

constexpr int ORDER = 1;

vs

namespace {
constexpr int ORDER = 1;
} // unnamed namespace

The reason I question the usefulness of wrapping into an unnamed namespace is because at global scope, constexpr implies static. So similar to how in header files writing

static constexpr int ORDER = 1;

makes static just a repetition, I'm assuming that the same should apply in source files as well, hence internal linkage should be guaranteed for "constexpr variables declared in a source file's global scope".

Is this the case? Are there different suggestions?

Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63
  • 2
    Namespaces are preferable in C++. Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later. PS: I would wrap such constants in a structure. – Martin.Martinsson Jul 06 '21 at 09:01
  • @Martin.Martinsson: `constexpr` definitely requires compile-time initialization (although as-if can as usual do a lot). – Davis Herring Jul 06 '21 at 18:59
  • In a header you should [use `inline`](https://stackoverflow.com/q/53794625/8586227) and never an unnamed namespace or `static`. – Davis Herring Jul 06 '21 at 19:04
  • @DavisHerring I added a bounty to draw more attention to the question. Do you agree with the existing answer? Do you want to contribute a different answer? – Lorah Attkins Jul 08 '21 at 12:24
  • @LorahAttkins: The answer here is fine: I just commented about the header case because it matters more. – Davis Herring Jul 08 '21 at 14:48

1 Answers1

2

It's not required to enclose constexpr variables, declared in a source file, in an unnamed namespace. Since the end goal is to achieve internal linkage you have to remember this:

The name of an entity that belongs to a namespace scope has internal linkage if it is the name of

  • a variable, variable template,
  • function, or function template that is explicitly declared static; or
  • a non-template variable of non-volatile const-qualified type, unless
    • it is explicitly declared extern, or
    • it is inline or exported, or
    • it was previously declared and the prior declaration did not have internal linkage; or
  • a data member of an anonymous union.

i.e since "constexpr implies const and const on namespace scope implies internal linkage", it's superfluous to say

static constexpr int ORDER = 1;

or even

namespace {
  static constexpr int ORDER = 1;
}

If you want a tangible proof of the internal linkage property, consider this compilation error

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • That being said, it doesn't hurt to put your singly defined internally linked variables inside a named namespace to improve structuring your code. – 303 May 30 '22 at 00:12