25

C++14 ドラフト (N3936) は、§3.2/3 で次のように述べています。

名前が潜在的に評価される式 ex として表示される変数 x は、左辺値から右辺値への変換 (4.1) を x に適用して、重要な関数を呼び出さない定数式 (5.19) を生成しない限り、odr で使用されます。 x はオブジェクトであり、ex は式 e の潜在的な結果のセットの要素です。ここで、左辺値から右辺値への変換 (4.1) が e に適用されるか、e は破棄値式 (節 5) です。

これは私には意味がありません。式e破棄された値の式であるかどうかは、使用されるコンテキストに依存しますeexpression-statement (§6.2) で使用されるすべての式は、破棄された値の式です。左辺値から右辺値への変換が適用される場合は、使用されるeコンテキストにも依存しますe

さらに、式が別の式の潜在的な結果のセットにあるとはどういう意味ですか。セットのメンバーシップを決定できるようにするには、式が等しいという概念が必要です。しかし、参照透過性がないため、これをどのように達成できるかわかりません。

これが C++11 から C++14 に変更されたのはなぜですか? そして、これはどのように解釈されるべきですか?このままでは、意味がありません。

4

1 に答える 1

27

臭気使用の目的

非公式には、odr による変数の使用は次のことを意味します。

プログラム内のいずれかの式がオブジェクトのアドレスを取得するか、参照をオブジェクトに直接バインドする場合、このオブジェクトを定義する必要があります。

最新草案での明確化

仕様の最新バージョンでは、§3.2 が明確化されています ( GitHub の Draft C++14 を参照)。

2 式は、未評価のオペランド (第 5 節) またはその部分式でない限り、評価される可能性があります。式の潜在的な結果のセットはe、次のように定義されます。

  • eが id-expression (5.1.1) の場合、セットには のみが含まれますe
  • eがクラス メンバ アクセス式 (5.2.5) の場合、セットにはオブジェクト式の潜在的な結果が含まれます。
  • e2 番目のオペランドが定数式であるメンバーへのポインター式 (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

—例の終了] —注記の終了]

x3潜在的に評価される式として現れる名前を持つ変数は、左辺値から右辺値への変換 (4.1) を適用して、重要な関数を呼び出さない定数式 (5.19) を生成しない限り、 exodr によって使用さexます。 、式 の潜在的な結果のセットの要素であり、左辺値から右辺値への変換 (4.1) が に適用されるか、破棄された値の式 (第 5 節) です。xxexeee

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
于 2014-05-14T12:44:26.810 に答える