cppreference のこの例を検討してください。
_struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
_
_&S::x
_は廃棄値式であることに同意します。標準では(9.2、パラグラフ1 [stmt.expr] from n4700 )
式ステートメントの形式は
_expression-statement: expression_opt ;
_式は廃棄値式です(第8項)...
ただし、_S::x
_がodr-usedではないのに十分ですか? 6.2、パラグラフ3 [basic.def.odr]の状態
名前が潜在的に評価される式として表示される変数
x
ex
は、odr-usedbyex
- ...
x
がオブジェクトの場合、ex
は式e
の潜在的な結果セットの要素です。ここで、どちらか
- 左辺値から右辺値への変換(7.1)が
e
に適用される、またはe
は廃棄値の式です(第8項)。
問題は、破棄された値の式_&S::x
_には潜在的な結果がないことです(つまり、_S::x
_は_&S::x
_の潜在的な結果ではありません)。 basic.def.odr]:
...式
e
の潜在的な結果のセットは、次のように定義されます。
e
がid-expression(8.1.4)の場合、セットにはe
のみが含まれます。e
が配列オペランドを持つ添え字演算(8.2.1)である場合、セットにはそのオペランドの潜在的な結果が含まれます。- ...
- それ以外の場合、セットは空です。
それでは、_S::x
_がODRで使用されていないことをどのように説明できますか?
それは確かにODRで使用されます。あなたの分析は正しいです(そして、私はその例を修正しました しばらく前 )。
はい、この例では、&S::x
odr-uses S::x
です。
[basic.def.odr]/4
名前が潜在的に評価される式
x
として表示される変数ex
は、ex
への左辺値から右辺への変換を適用しない限り、x
によってodr-usedになります定数式は非自明な関数を呼び出さず、xがオブジェクトの場合、exは式eの潜在的な結果のセットの要素であり、左辺値-to-rvalue変換がeに適用されるか、eが廃棄値式です。
オブジェクトのアドレスが定数式になることはありません。 S::x
が&S::x
でODRで使用される理由です。
その最後の主張を正当化するには:
[expr.const]/6
定数式は、定数式(以下で定義)の許可された結果であるエンティティを参照するglvalueコア定数式、または次の制約を満たす値を持つprvalueコア定数式です[...]
そして
[expr.const]/2.7
2)式
e
は、コア定数式です。ただし、e
の評価、抽象マシンの規則に従う場合、次の式のいずれかを評価します。
[...]
2.7)に適用されない限り、左辺値から右辺値への変換
(以下の点は適用されません:)
2.7.1)事前の初期化、定数式で初期化された完全な不揮発性constオブジェクトを参照する整数型または列挙型の不揮発性glvalue、または
2.7.2)文字列リテラルのサブオブジェクトを参照する不揮発性glvalue、または
2.7.3)constexprで定義された不揮発性オブジェクトを参照する、またはそのようなオブジェクトの不変サブオブジェクトを参照する不揮発性glvalue、または
2.7.4)e
の評価内で有効期間が始まった不揮発性オブジェクトを参照するリテラル型の不揮発性glvalue。