constexpr変数がキャプチャされていません

Dec 10 2020

次のコードはclangでコンパイルされません(GCCでコンパイルされます)。

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Clangのエラーは変数 'x'であり、capture-defaultが指定されていないラムダで暗黙的にキャプチャすることはできませんが、constexpr変数は常にキャプチャされると思いました。

xがintの場合、コードは次のようにコンパイルされます。

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

興味深いことに、次のコードもコンパイルされます。

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

clangは正しいですか?もしそうなら、その理由は何ですか?私は-std = c ++ 17を使用しています

-編集-

次の質問:ラムダでconstexpr値をキャプチャせずに使用できますか?clang11と同様に、これとは関係ありません。実際、上記のように、xがintの場合、clang11はコンパイルされます。

サンプルコードは https://godbolt.org/z/rxcYjz

回答

2 DavisHerring Dec 25 2020 at 07:09

あなたは、ときにreturn x;最初の例では、あなたが呼び出す必要がありAの結合関係コピーコンストラクタ、参照にしx、それをので、ODR-用途を。定数式で使用できる値の些細なコピーはodr-useを構成するべきではないという議論をすることができますがreturn x.a;、そのルールにはそのような例外はないので、Clangはそれを拒否するのが正しいです。

実際問題として、もちろん、それをキャプチャする必要性を回避するために任意のconstexpr変数staticを作成することができます。