variabile constexpr non acquisita

Dec 10 2020

Il codice seguente non si compila in clang (lo fa in GCC):

struct A{
    int a;
};

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

L'errore di Clang è che la variabile "x" non può essere catturata in modo implicito in un lambda senza che sia specificato un valore predefinito di acquisizione , ma ho pensato che le variabili constexpr fossero sempre catturate.

Se x è un int, il codice compila:

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

È interessante notare che viene compilato anche il codice seguente:

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

Il clang è giusto? In caso affermativo, qual è la logica? Sto usando -std = c ++ 17

--MODIFICARE--

La seguente domanda: posso usare un valore constexpr in un lambda senza catturarlo? non è correlato a questo, come con clang11 non è più un problema: infatti, come detto sopra, se x è un int, clang11 compila.

Codice di esempio presente anche in https://godbolt.org/z/rxcYjz

Risposte

2 DavisHerring Dec 25 2020 at 07:09

Quando return x;nel primo esempio, devi invocare Ail costruttore di copia di, che implica l'associazione di un riferimento a xe quindi odr-lo utilizza. Si può argomentare che una copia banale di un valore utilizzabile in espressioni costanti non dovrebbe costituire un odr-use più di return x.a;, ma non c'è un'eccezione del genere in quella regola, quindi Clang ha ragione a rifiutarla.

In pratica, puoi ovviamente creare qualsiasi constexprvariabile staticper evitare qualsiasi necessità di catturarla.