variable constexpr no capturada

Dec 10 2020

El siguiente código no se compila en clang (lo hace en GCC):

struct A{
    int a;
};

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

El error de Clang es que la variable 'x' no se puede capturar implícitamente en una lambda sin especificar la captura predeterminada , pero pensé que las variables constexpr siempre se capturaban.

Si x es un int, el código compila:

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

Curiosamente, el siguiente código también se compila:

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

¿Es cierto clang? Si es así, ¿cuál es la justificación? Estoy usando -std = c ++ 17

--EDITAR--

La siguiente pregunta: ¿Puedo usar un valor constexpr en una lambda sin capturarlo? no está relacionado con este, como con clang11 ya no es un problema: de hecho, como se indicó anteriormente, si x es un int, clang11 compila.

Código de muestra también presente en https://godbolt.org/z/rxcYjz

Respuestas

2 DavisHerring Dec 25 2020 at 07:09

Cuando return x;en el primer ejemplo, usted tiene que invocar A's constructor de copia, que consiste en un enlace de referencia a x, y por lo tanto ODR-usa. Se puede argumentar que una copia trivial de un valor utilizable en expresiones constantes no debería constituir un uso odr más que return x.a;, pero no hay tal excepción en esa regla, por lo que Clang tiene razón al rechazarla.

Como cuestión práctica, por supuesto, puede crear cualquier constexprvariable staticpara evitar la necesidad de capturarla.