In C++17 we got inline variables and I have assumed that global constexpr variables are implicitly inline. But apparently this is true only for static member variables.
What is the logic/technical limitation behind this?
source:
A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.
The point here is that
constexpr int x = 1;
at namespace scope has internal linkage in C++14.If you make it implicitly inline without changing the internal linkage part, the change would have no effect, because the internal linkage means that it can't be defined in other translation units anyway. And it harms teachability, because we want things like
inline constexpr int x = 1;
to get external linkage by default (the whole point of inline, after all, is to permit the same variable to be defined in multiple translation units).If you make it implicitly inline with external linkage, then you break existing code:
This perfectly valid C++14 would become an ODR violation.
The reason why
constexpr
static data members were made implicitlyinline
was to solve a common problem in C++: when defining a class-scoped constant, one was previously forced to emit the definition in exactly one translation unit, lest the variable be ODR-used:In such cases, we usually care only about the value of the constant, not its address; and it's convenient for the compiler to synthesize a unique location for the constant in case it really is ODR-used, but we don't care where that location is.
Thus, C++17 changed the rules so that the out-of-line definition is no longer required. In order to do so, it makes the declaration of
foo::kAnswer
an inline definition, so that it can appear in multiple translation units without clashing, just like inline functions.For namespace-scope
constexpr
variables (which are implicitlystatic
, and therefore have internal linkage, unless declaredextern
) there is no similar issue. Each translation unit has its own copy.inline
, as it's currently specified, would have no effect on such variables. And changing the existing behaviour would break existing programs.