关于类成员访问表达式

时间:2015-07-13 10:58:34

标签: c++ one-definition-rule

在N4296中,3.2 [basic.def.odr] p3:

  

x的名称显示为可能评估的表达式ex的变量exx使用,除非将左值到右值的转换应用于x一个不调用任何非平凡函数的常量表达式,如果ex是一个对象,e是表达式e的潜在结果集的一个元素,其中左值到右值转换适用于e,或ex是废弃值表达式。

如何解释这一段?我找到了两个解释。

1从这里“Trying to understand [basic.def.odr]/2 in C++14 (N4140)

让我们把它分成几步:在表达式“ex”中出现变量“x”构成一个odr-use,除非:
      
  1. 无法评估 x
  2.   
  3. 必须满足以下所有条件:      
             
    1. “将左值到右值的转换应用于ex会产生一个不会调用任何非平凡函数的常量表达式”
    2.        
    3. e是表达式e 的潜在结果集的元素,并且以下任一项:          
                   
      1. 左值到右值转换适用于e
      2.            
      3. x是一个废弃值表达式”
      4.                          
来自cppreference http://en.cppreference.com/w/cpp/language/definition

和2

  

潜在评估表达式ex中的变量x除非任何以下内容为真,否则将被使用:

     
      
  • 将lvalue-to-rvalue转换应用于x会产生一个不会调用非平凡函数的常量表达式

  •   
  • e是一个对象,ex是较大表达式struct S { static const int x = 0; }; extern S s;// no definition of s int i = s.x;// is s odr-used? is x odr-used? // gcc 5.1.0 is ok 的潜在结果之一,其中较大的表达式是丢弃值表达式或左值到右值转换

  •   

关于两个规则的第一个答案是,另一个是任何。哪一个是对的?

请将规则拆分为解释此代码的步骤:

SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1, Col2 ORDER BY Col3) As seq
    FROM yourTable) dt
WHERE (seq > 1)

1 个答案:

答案 0 :(得分:3)

cppreference 错了;从两个子条款必须包含的标准(无论哪个版本)中的语言中可以清楚地看出。我已经纠正过了。

在您的示例中,s不是常量表达式(C ++ 14:不满足出现在常量表达式中的要求),因此使用了odr。第二个子条款没有出现。

同时,x也使用了odr,因为尽管可以在适当的上下文中使用x的常量表达式(例如,作为{{1的定义中的数组绑定) }}); S不是封闭表达式x的潜在结果之一,它是唯一一个受废弃值转换或左值到右值转换的封闭表达式。

如果没有s.xs的定义,

gcc可能没问题,但是并不要求实现诊断每个odr违规。

相关问题