DR 712负责将{c ++ 11中[basic.def.odr] / 2的措辞改为今天的[basic.def.odr]2 and 3当前措辞。但我仍然试图了解改革的原因,如DR中所述,如下:
712。条件表达式的整数常量操作数是“使用?”
描述在类中初始化的静态数据成员 定义,9.2.3.2 [class.static.data]第3段说,
如果使用成员,则仍应在命名空间范围内定义该成员 在程序中...
“used”的定义见3.2 [basic.def.odr]第1段:
一个对象或非重载函数 name显示为可能评估的
除非它是满足出现在a中的要求的对象,否则使用表达式 常量表达式(5.20 [expr.const])和左值到右值的转换(4.1 [conv.lval])
立即申请。现在考虑以下示例:
struct S { static const int a = 1; static const int b = 2; }; int f(bool x) { return x ? S::a : S::b; }
根据标准的当前措辞,这个例子 要求在命名空间作用域中定义
S::a
和S::b
。该 原因是,根据5.16 [expr.cond]第4段, 这个条件表达式的结果是左值和 lvalue-to-rvalue转换应用于该转换,而不是直接转换为 对象,所以这不符合“立即应用”的要求。这是 令人惊讶和不幸,因为只有价值而不是 使用静态数据成员的地址。 (这个问题也 适用于问题696的拟议决议。)
好吧,如果“立即应用的要求失败,那么条件表达式中的表达式S::a
和S::b
不使用(使用了odr),因此, struct S
的相应静态成员不需要在命名空间范围内定义。但这与DR所说的正好相反。我缺少什么?
答案 0 :(得分:7)
我认为你错过了used
定义的要点:
it is used UNLESS ( (const) AND (immediately applied) )
所以,如果"立即应用"是假的,那么UNLESS是假的,因此被使用了。
答案 1 :(得分:2)
除非[...]
,否则将使用其名称显示为可能已评估的表达式的对象或非重载函数
嗯,S::a
和S::b
出现在f
内的潜在评估表达式中。
所以他们被使用,除非以下任何一个例外适用。
[...]它是一个满足出现在常量表达式(5.20 [expr.const])中的要求的对象,并且立即应用左值到右值的转换(4.1 [conv.lval])。
嗯,这是一个满足出现在常量表达式中的要求的对象。所以它通过了那个测试。
但是不会立即应用左值到右值的转换。
所以它没能通过测试。
由于整个部分属于"除非",失败意味着前一种情况适用;该对象被视为"使用"。