An object or function must be defined if it is odr-used. In some cases objects and functions are not odr-used and in those cases you don't have to define them. Whether or not the declaration of a static class member has an initializer, it is still not a definition. In all cases the rule is that an out-of-class definition at an enclosing namespace scope is required if the static member is odr-used.
The intuition is that "odr-used" means "the linker needs its address". If a constexpr
variable is only used in ways that require its value---and never its address---then it may avoid being odr-used. In such cases the compiler simply inlines its value, and it does not need to be defined, because the linker doesn't need its address. That's the case with const char* Something<int>::str
, but not const char Something<int>::str[]
.
"But they're the same!", you shout. Not so. For when str
is a const char*
, its value is the address of the string literal "int"
. The address of the string literal is needed, but not the address of str
itself. The former is the value of str
and it satisfies the requirements for not being odr-used; the compiler can just inline it. But when str
is a const char[]
, its value is the string literal "int"
itself. When you try to output it using istream::operator<<
, it is implicitly converted into a const char*
. But the const char*
's value is the address of the string literal, that is, the address of Something<int>::str
. Therefore in this case Something<int>::str
is odr-used; its address is needed.
There is logic in the standard that can be used to determine precisely when a variable is odr-used ([basic.def.odr]). But I'm not going to quote it because it's the most confusing section of the entire standard. I will say that in the case where you have const char* Something<int>::str
, the lvalue-to-rvalue conversion is immediately applied, which is one of the conditions for it to not be odr-used; and in the case where you have const char Something<int>::str[]
, the array-to-pointer conversion is immediately applied, and that doesn't satisfy the condition.