Puede abarcar ser constexpr?

11

Todos los constructores de std :: span se declaran constexpr, sin embargo, parece que no puedo hacer que ninguno de ellos funcione en un contexto constexpr. Descomentar cualquiera de los constexpr a continuación dará como resultado un error de compilación.

#include <array>
#include <span>

int main()
{
    constexpr int carray[3] = { 0, 1, 2 };
    constexpr std::array<int, 3> array{ 0, 1, 2 };
    using S = std::span<const int, 3>;

    /*constexpr*/ S span1{ array.data(), 3 };
    /*constexpr*/ S span2{array.begin(), array.end()};
    /*constexpr*/ S span3{carray};
    /*constexpr*/ S span4{array};
}

De hecho, ¿es posible crear un tipo de intervalo constexpr, ya que parece que los constructores nunca pueden evaluarse en tiempo de compilación cuando tienen que inicializar un puntero o referencia?

Andreas Loanjoe
fuente
Descomente los constexprs no los elimine.
Andreas Loanjoe el
Está iniciando un período de tiempo de ejecución que quise inicializar un período de tiempo de constexpr
Andreas Loanjoe
Doh No estoy seguro de por qué hice eso. no importa
NathanOliver
raro, no veo por qué eso sería necesario el lapso sólo se vive dentro del ámbito local de todos modos ...
Andreas Loanjoe
Muy relacionado: stackoverflow.com/q/57545503/2069064
Barry el

Respuestas:

13

No puede usar variables locales de funciones no estáticas en una expresión constante como esa. Necesita estabilidad de dirección y eso solo se logra mediante objetos estáticos. Modificando el código a

constexpr std::array<int, 3> array{ 0, 1, 2 };
constexpr int carray[3] = { 0, 1, 2 };

int main()
{
    using S = std::span<const int, 3>;

    constexpr S span1{ array.data(), 3 };
    constexpr S span2{array.begin(), array.end()};
    constexpr S span3{carray};
    constexpr S span4{array};
}

o

int main()
{
    static constexpr std::array<int, 3> array{ 0, 1, 2 };
    static constexpr int carray[3] = { 0, 1, 2 };
    using S = std::span<const int, 3>;

    constexpr S span1{ array.data(), 3 };
    constexpr S span2{array.begin(), array.end()};
    constexpr S span3{carray};
    constexpr S span4{array};
}

Le permite crear un constexpr std::span.

NathanOliver
fuente
55
El alcance no es el problema. La duración del almacenamiento es. El local estático debería funcionar.
eerorika
También funciona si todos son objetos locales de función dentro de una constexprfunción (sin explícito static). ¿Estos objetos tienen una duración predeterminada de almacenamiento estático o es algo diferente?
n314159
@ n314159 No estoy seguro de si eso está permitido o si ha caído en el temido: si ninguna especialización de una función constexpr es una expresión constante central, la función está mal formada, no se requiere una cláusula de diagnóstico. [expr.const] / 10 solo permite variables estáticas.
NathanOliver
@ n314159: No estoy seguro exactamente de lo que estás diciendo que funciona (o "funciona"), pero ten cuidado con la diferencia entre usar algo como una expresión constante en una función (constexpr o no) y usar algo para construir una constante expresión a través de una función constexpr.
Davis Herring
Es posible que desee decir que los valores no estáticos (constantes) se pueden usar en expresiones constantes, pero no sus direcciones .
Davis Herring