8

このコードは機能します:

struct Blob {
    static constexpr int a = 10;
};

int main() {
    Blob b;
    auto c = b.a;
}

しかし、次のように変更intするfloatと、エラーが発生します。

struct Blob {
    static constexpr float a = 10.0f;
};

/tmp/main-272d80.o: 関数main': main.cpp:(.text+0xe): undefined reference toBlob::a' 内

そのように a を使用できないのはなぜconstexpr floatですか?

コンパイラ: Ubuntu clang バージョン 3.5.0-4ubuntu2 (tags/RELEASE_350/final)

gcc バージョン 4.9.1 (Ubuntu 4.9.1-16ubuntu6) でテストされ、エラーはありませんでした。

編集:

-O1、-O2、-O3、または -Os を使用するとコンパイルされますが、-O0 で失敗します

4

2 に答える 2

6

C++11 読み取り

名前が潜在的に評価される式として表示される変数 は、それが定数式 (5.19) に表示されるための要件を満たし、左辺値から右辺値への変換 (4.1) がすぐに適用されるオブジェクトでない限り、odr 使用されます。

明らかに、ltr 変換がすぐに適用され、constexpr[expr.const]/(2.7.1) に従って、浮動小数点型の変数を定数式に含めることができます。

条件式は、潜在的に評価される部分式として次のいずれかを含まない限り、コア定数式です [..]

  • 適用されない限り、左辺値から右辺値への変換 (4.1)
    • で定義された非揮発性オブジェクトconstexprを参照する、またはそのようなオブジェクトのサブオブジェクトを参照するリテラル型の glvalue、または

Clang のバグのようです。

于 2015-02-01T15:57:46.203 に答える
3

興味深いことに、Blob::a代わりに使用すると、clang文句はありません。

auto c = Blob::a;

これは、それが臭気を帯びているかどうかを判断する上で重要ではありません。したがって、これは最適化を行わずにclang 3.7clangで再現できるバグのようです。クラス外の定義を追加すると問題が修正されるため、これはodrの問題であることがわかります(ライブで参照してください)。

constexpr float Blob::a ;

では、静的な constexpr クラス メンバーを定義する必要があるのはいつでしょうか? これは、セクション9.4.2 [class.static.data]で説明されています (私のものは今後も強調されます)。

リテラル型の静的データ メンバーは、constexpr 指定子を使用してクラス定義で宣言できます。その場合、その宣言は、割り当て式であるすべての初期化子節が定数式であるブレースまたは等号初期化子を指定するものとします。[ 注: どちらの場合も、メンバーは定数式に現れる場合があります。--end note ]メンバーがプログラムで ODR 使用 (3.2)され、名前空間スコープ定義に初期化子が含まれていない場合、メンバーは名前空間スコープで定義されます。

ODR 使用の場合は定義が必要です。臭気使用ですか?いいえそうではありません。3.2 セクション[basic.def.odr]の元の C++11 の文言には、次のように書かれています。

式は、未評価のオペランド (第 5 節) またはその部分式でない限り、評価される可能性があります。名前が潜在的に評価される式として表示される変数は、それが定数式(5.19)に表示されるための要件を満たし、左辺値から右辺値への変換 (4.1) がすぐに適用されるオブジェクトでない限り、odr-usedです。

a両方の条件を満たす場合、これは定数式であり、左辺値から右辺値への変換がすぐに適用されます。欠陥レポート 712は、欠陥レポートであるため、C++11 に適用される文言を変更し、3.2現在は次のように述べています。

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

一致する潜在的な結果は次のようになります。

e が id-expression (5.1.1) の場合、セットには e のみが含まれます。

これは定数式であり、左辺値から右辺値への変換が適用されるため、odr は使用されません。

于 2015-02-11T19:22:42.857 に答える