你错过了前提的一部分。Account::period
如果您还在某处定义(但没有提供初始化程序),则上面给出的类定义是完全有效的。见 9.4.2/3 的最后一句话:
如果该成员在程序中被 odr-used (3.2) 并且命名空间范围定义不应包含初始化程序,则该成员仍应在命名空间范围内定义。
整个讨论仅适用于静态 constexpr 数据成员,不适用于命名空间范围的静态变量。当静态数据成员constexpr
(而不是简单的 const)时,您必须在类定义中初始化它们。所以你的问题应该是:你可以用静态 constexpr 数据成员做什么,这样你就不必在命名空间范围内为它提供定义?
从前面看,答案是成员不能被odr-used。而且您已经找到了odr-used定义的相关部分。因此,您可以在没有潜在评估的上下文中使用该成员- 作为未评估的操作数(例如sizeof
or decltype
)或其子表达式。您可以在立即应用左值到右值转换的表达式中使用它。
所以现在我们要讨论变量的什么用途导致立即左值到右值的转换?
部分答案在 §5/8 中:
每当一个泛左值表达式作为操作数的操作数出现时,该操作数需要一个纯右值,左值到右值 (4.1)、数组到指针 (4.2) 或函数到指针 (4.3) 标准转换是应用于将表达式转换为纯右值。
对于基本上适用于所有应用标准算术转换的运算符的算术类型。因此,您可以在各种算术和逻辑运算中使用该成员,而无需定义。
我不能列举所有事情,你可以或不能在这里做,因为某事物是 [g]lvalue 或 [p]rvalue 的要求遍布整个标准。经验法则是:如果只使用变量的值,则应用左值到右值的转换;如果变量用作对象,则将其用作左值。
您不能在明确需要左值的上下文中使用它,例如作为地址运算符或变异运算符的参数)。左值引用的直接绑定(没有转换)就是这样一个上下文。
更多示例(没有详细的标准分析):
您可以将它传递给函数,除非函数参数是可以直接绑定变量的引用。
For returning it from a function: if implicit conversion to the return type involves a user-defined conversion function, the rules for passing to a function apply. Otherwise you can return it, unless the function returns an lvalue (a reference) referring directly to the variable.
The key rule for odr-used variables, the "One Definition Rule" is in 3.2/3:
Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required.
The "no diagnostic required" part means that programs violating this rule cause undefined behavior, which may range from failing to compile, compiling and failing in surprising ways to compiling and acting as if everything was OK. And your compiler need not warn you about the problem.
The reason, as others have already indicated, is that many of these violations would only be detected by a linker. But optimizations may have removed references to objects, so that no cause for linkage failure remains or else linking may sometimes occur only at runtime or be defined to pick an arbitrary instance from multiple definitions of a name.