在N4296中,3.2 [basic.def.odr] p3:
x
的名称显示为可能评估的表达式ex
的变量ex
由x
使用,除非将左值到右值的转换应用于x
一个不调用任何非平凡函数的常量表达式,如果ex
是一个对象,e
是表达式e
的潜在结果集的一个元素,其中左值到右值转换适用于e
,或ex
是废弃值表达式。
如何解释这一段?我找到了两个解释。
1从这里“Trying to understand [basic.def.odr]/2 in C++14 (N4140)”
让我们把它分成几步:在表达式“ex”中出现变量“x”构成一个odr-use,除非:来自cppreference http://en.cppreference.com/w/cpp/language/definition 的
- 无法评估
x
,或- 必须满足以下所有条件:
醇>
- “将左值到右值的转换应用于
ex
会产生一个不会调用任何非平凡函数的常量表达式” 和- “
醇>e
是表达式e
” 的潜在结果集的元素,并且以下任一项:
- “ 左值到右值转换适用于
e
”- “或
醇>x
是一个废弃值表达式”
和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)
答案 0 :(得分:3)
cppreference 错了;从两个子条款必须包含的标准(无论哪个版本)中的语言中可以清楚地看出。我已经纠正过了。
在您的示例中,s
不是常量表达式(C ++ 14:不满足出现在常量表达式中的要求),因此使用了odr。第二个子条款没有出现。
同时,x
也使用了odr,因为尽管可以在适当的上下文中使用x
的常量表达式(例如,作为{{1的定义中的数组绑定) }}); S
不是封闭表达式x
的潜在结果之一,它是唯一一个受废弃值转换或左值到右值转换的封闭表达式。
s.x
或s
的定义,gcc可能没问题,但是并不要求实现诊断每个odr违规。