"potentially-evaluated" 是否与 C++03 中的 "odr-used" 相同?

Does "potentially-evaluated" means the same as "odr-used" in C++03?

举个例子:

#include <iostream>

class A
{
public:
    static const int numberOfWheels = 4;
};

// const int A::numberOfWheels;

int main()
{
    std::cout << A::numberOfWheels << std::endl;
}

它是正式未定义的行为(UB) 因为 A::numberOfWheels 在没有定义的情况下被 使用 吗? (另见 here)。正如 C++03 所述:

The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

我发现 C++03 中 used 的定义相当混乱,因为它指向 potentially-evaluated 表达式:

An object or non-overloaded function is used if its name appears in a potentially-evaluated expression.

根据我的猜测,它排除了以下表达式:

sizeof(A::numberOfWheels) ;
typeid(A::numberOfWheels).name() ;

但不一定是像上面那样带有重载 << 运算符的表达式。

从这两个缺陷报告来看,它的意图似乎是它应该与 odr-used 非常相似:defect report 48: Definitions of unused static members 它说(强调我的前进) :

Originally, all static data members still had to be defined outside the class whether they were used or not.

But that restriction was supposed to be lifted so that static data members need not be defined outside the class unless they are used in a manner which requires their definition, in the same manner as namespace-scope variables. In particular, if an integral/enum const static data member is initialized within the class, and its address is never taken, we agreed that no namespace-scope definition was required.

修改3.2p2如下:

An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19 [expr.const] ), is the operand of the sizeof operator (5.3.3 [expr.sizeof] ), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8 [expr.typeid] ).

defect report 82: Definition of "using" a constant expression :

The wording in 3.2 basic.def.odr paragraph 2 about "potentially evaluated" is incomplete. It does not distinguish between expressions which are used as "integral constant expressions" and those which are not; nor does it distinguish between uses in which an objects address is taken and those in which it is not. (A suitable definition of "address taken" could be written without actually saying "address".)

但是标准中的措辞没有被修改以包含任何一个缺陷报告中声明的意图,并且不清楚为什么,只是在需要整数常量表达式的地方添加了例外。

更新

defect report 454: When is a definition of a static data member required? 最终将标准的措辞与缺陷报告 48 中表达的意图同步起来,它说:

As a result of the resolution of core issue 48, the current C++ standard is not in sync with existing practice and with user expectations as far as definitions of static data members having const integral or const enumeration type are concerned. Basically what current implementations do is to require a definition only if the address of the constant is taken. Example:

void f() {

  std::string s;
  ... 

  // current implementations don't require a definition
  if (s.find('a', 3) == std::string::npos) {
   ...
  }

To the letter of the standard, though, the above requires a definition of npos, since the expression std::string::npos is potentially evaluated. I think this problem would be easily solved with simple changes to 9.4.2 class.static.data paragraph 4, 9.4.2 class.static.data paragraph 5 and 3.2 basic.def.odr paragraph 3.

因此对于 C++03 部分,[basic.def.odr] 旨在涵盖接近我们认为来自 C++11 的 odr-used 规则。通过 defect report 712 对 C++11 规则进行了后续更改,使 C++11 更接近 C++14 规则。