constexpr Variable nicht erfasst

Dec 10 2020

Der folgende Code wird nicht in clang kompiliert (in GCC):

struct A{
    int a;
};

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

Clangs Fehler ist, dass die Variable 'x' nicht implizit in einem Lambda erfasst werden kann, ohne dass ein Erfassungsstandard angegeben wurde , aber ich dachte, dass constexpr-Variablen immer erfasst wurden.

Wenn x ein int ist, kompiliert der Code:

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

Interessanterweise wird auch der folgende Code kompiliert:

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

Ist Klirren richtig? Wenn ja, was ist die Begründung? Ich benutze -std = c ++ 17

--BEARBEITEN--

Die folgende Frage: Kann ich einen constexpr-Wert in einem Lambda verwenden, ohne ihn zu erfassen? ist nicht mit diesem verwandt, wie bei clang11 ist es kein Problem mehr: Wie oben angegeben, kompiliert clang11, wie oben angegeben, wenn x ein int ist.

Beispielcode auch vorhanden in https://godbolt.org/z/rxcYjz

Antworten

2 DavisHerring Dec 25 2020 at 07:09

Wenn Sie return x;im ersten Beispiel den AKopierkonstruktor aufrufen, müssen Sie einen Verweis darauf binden xund ihn daher von odr verwenden. Es kann argumentiert werden, dass eine triviale Kopie eines Werts, der in konstanten Ausdrücken verwendet werden kann, nicht mehr als eine odr-Verwendung darstellen sollte return x.a;, aber es gibt keine solche Ausnahme in dieser Regel, so dass Clang es richtig ist , sie abzulehnen.

In der Praxis können Sie natürlich jede constexprVariable festlegen static, um zu vermeiden, dass sie erfasst werden muss.