The reason why constexpr
static data members were made implicitly inline
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:
// foo.h
struct foo {
static constexpr int kAnswer = 42;
};
// foo.cpp
// a linker error will occur if this definition is omitted before C++17
#include "foo.h"
constexpr int foo::kAnswer;
// main.cpp
#include "foo.h"
#include <vector>
int main() {
std::vector<int> bar;
bar.push_back(foo::kAnswer); // ODR-use of 42
}
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 implicitly static
, and therefore have internal linkage, unless declared extern
) 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.