variável constexpr não capturada

Dec 10 2020

O código a seguir não é compilado no clang (ele é compilado no GCC):

struct A{
    int a;
};

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

O erro do Clang é a variável 'x' que não pode ser capturada implicitamente em um lambda sem o padrão de captura especificado , mas pensei que as variáveis ​​constexpr sempre eram capturadas.

Se x for um int, o código compila:

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

Curiosamente, o código a seguir também compila:

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

O clang está certo? Em caso afirmativo, qual é o motivo? Estou usando -std = c ++ 17

--EDITAR--

A seguinte pergunta: Posso usar um valor constexpr em um lambda sem capturá-lo? não está relacionado a este, como com o clang11, não é mais um problema: na verdade, como afirmado acima, se x for um int, o clang11 compila.

Código de amostra também presente em https://godbolt.org/z/rxcYjz

Respostas

2 DavisHerring Dec 25 2020 at 07:09

Quando return x;no primeiro exemplo, você tem que chamar A's construtor de cópia, que envolve a ligação de uma referência ao xe assim ODR usos-it. Pode-se argumentar que uma cópia trivial de um valor utilizável em expressões constantes não deve constituir um uso de odr mais do que return x.a;, mas não há tal exceção nessa regra, então o Clang está correto em rejeitá-la.

Como questão prática, você pode criar qualquer constexprvariável staticpara evitar qualquer necessidade de capturá-la.