是否"潜在评估"与" odr-used"相同在C ++ 03中?

时间:2015-07-22 14:20:25

标签: c++ language-lawyer 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所述:

  

如果使用成员,则仍应在命名空间范围内定义该成员   在程序和命名空间范围定义中不应包含   初始化程序。

我发现C ++ 03中使用的定义相当混乱,因为它指向可能已评估的表达式:

  

如果对象或非重载函数的名称出现在中,则使用   潜在评估的表达。

从我的猜测来看,它排除了以下表达式:

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

但不一定是具有上述重载<<运算符的表达式。

1 个答案:

答案 0 :(得分:5)

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

  

最初,所有静态数据成员仍然必须在外部定义   这个班级是否被使用。

     

但是这个限制应该被取消以便静态数据   成员不需要在课外定义,除非他们被使用   以与...相同的方式要求其定义的方式   命名空间范围变量。特别是,如果是整数/枚举常量   静态数据成员在类中初始化,其地址为   从未采取过,我们同意没有命名空间范围定义   必需的。

此修改后的3.2p2如下:

  

表达式可能会被评估,除非它出现在哪里   需要积分常数表达式(见5.19 [expr.const]),   是sizeof运算符的操作数(5.3.3 [expr.sizeof]),或者是   typeid运算符的操作数和表达式没有   指定多态类类型的左值(5.2.8 [expr.typeid])。

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

  

3.2 basic.def.odr第2段中关于&#34;潜在的措辞   评价&#34;不完整。它不区分表达式   用作&#34;积分常数表达式&#34;以及那些   不;它也没有区分对象所使用的用途   被采取和那些不是。 (合适的定义   &#34;所采取的地址&#34;可以写,而不是实际说&#34;地址&#34;。)

但是标准中的措辞没有被修改为包含缺陷报告中的陈述意图,并且不清楚为什么,只添加了需要整数常量表达式的例外。

更新

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

  

由于解决了核心问题48,目前的C ++   标准与现有做法和用户不同步   对具有const的静态数据成员的定义的期望   整数或常数枚举类型。基本上是什么   当前的实现确实只需要一个定义   取常数的地址。例如:

void f() {

  std::string s;
  ... 

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

但是,对于标准的字母,上述内容需要一个定义   npos,因为表达式std :: string :: npos是潜在的   评估。我认为这个问题很容易通过简单的方法解决   更改为9.4.2 class.static.data第4段,9.4.2   class.static.data第5段和第3.2段basic.def.odr第3段。

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