臭気使用の目的
非公式には、odr による変数の使用は次のことを意味します。
プログラム内のいずれかの式がオブジェクトのアドレスを取得するか、参照をオブジェクトに直接バインドする場合、このオブジェクトを定義する必要があります。
最新草案での明確化
仕様の最新バージョンでは、§3.2 が明確化されています ( GitHub の Draft C++14 を参照)。
2 式は、未評価のオペランド (第 5 節) またはその部分式でない限り、評価される可能性があります。式の潜在的な結果のセットはe
、次のように定義されます。
e
が id-expression (5.1.1) の場合、セットには のみが含まれますe
。
e
がクラス メンバ アクセス式 (5.2.5) の場合、セットにはオブジェクト式の潜在的な結果が含まれます。
e
2 番目のオペランドが定数式であるメンバーへのポインター式 (5.5) の場合、セットにはオブジェクト式の潜在的な結果が含まれます。
e
形式が (e1) の場合、セットには e1 の潜在的な結果が含まれます。
e
が glvalue 条件式 (5.16) の場合、セットは、2 番目と 3 番目のオペランドの潜在的な結果のセットの和集合です。
e
がコンマ式 (5.18) の場合、セットには右側のオペランドの潜在的な結果が含まれます。
- それ以外の場合、セットは空です。
[ 注: このセットは、id-expressions の (おそらく空の) セットであり、それぞれがe
または の部分式ですe
。
[ 例: 次の例では、初期化子の潜在的な結果のセットにn
最初のS::x
部分式が含まれていますが、2 番目のS::x
部分式は含まれていません。
struct S { static const int x = 0; };
const int &f(const int &r);
int n = b ? (1, S::x) // S::x is not odr-used here
: f(S::x); // S::x is odr-used here, so
// a definition is required
—例の終了] —注記の終了]
x
3潜在的に評価される式として現れる名前を持つ変数は、左辺値から右辺値への変換 (4.1) を適用して、重要な関数を呼び出さない定数式 (5.19) を生成しない限り、 ex
odr によって使用されex
ます。 、式 の潜在的な結果のセットの要素であり、左辺値から右辺値への変換 (4.1) が に適用されるか、破棄された値の式 (第 5 節) です。x
x
ex
e
e
e
C++11 ではどのような状況でしたか?
C++11 の §3.2/2 には次のように書かれています。
式は、未評価のオペランド (第 5 節) またはその部分式でない限り、評価される可能性があります。名前が潜在的に評価される式として表示される変数は、それが定数式 (5.19) に表示されるための要件を満たし、左辺値から右辺値への変換 (4.1) がすぐに適用されるオブジェクトでない限り、odr 使用されます。
これらの文言の問題は、DR 712でした。次の例を検討してください。
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
、条件式x ? S::a : S::b
も左辺値です。これは、左辺値から右辺値への変換がすぐS::a
にandに適用されるのではなくS::b
、条件式の結果に適用されることを意味します。これは、C++11 の表現では、これらの静的データ メンバーは ODR で使用され、定義が必要であることを意味します。ただし、実際には値のみが使用されるため、静的データ メンバーを定義する必要はありません。宣言で十分です。ドラフト C++14 の新しい文言はこれを解決します。
新しい文言はすべての問題を解決しますか?
いいえ。次の例では、変数S::a
はまだ ODR で使用されています。
struct S { static constexpr int a[2] = {0, 1}; };
void f() {
auto x = S::a[0];
}
したがって、§3.2/2 に次の箇条書きを追加するために、新しい問題を提出しました。
- が
e
形式の glvalue 添字式 (5.2.1) である場合E1[E2]
、セットには の潜在的な結果が含まれますE1
。