O span pode ser constexpr?


11

Todos os construtores de std :: span são declarados constexpr, no entanto, não consigo fazer com que nenhum deles funcione em um contexto constexpr. Descomentar qualquer um dos constexpr abaixo resultará em um erro de compilação.

#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 fato possível criar um tipo de extensão constexpr, pois parece que os construtores nunca podem ser avaliados em tempo de compilação quando precisam inicializar um ponteiro ou referência?


Remova o comentário dos constexprs não os remova.
— Andreas Loanjoe 20/11/19

Você está inicializando um tempo de execução tempo de eu quis inicializar uma extensão constexpr
— Andreas Loanjoe

Doh. Não sei por que fiz isso. Nevermind
— NathanOliver

estranho, não
— entendo

Intimamente relacionados: stackoverflow.com/q/57545503/2069064
— Barry

Respostas:


13

Você não pode usar variáveis ​​locais de função não estática em uma expressão constante como essa. Você precisa de estabilidade de endereço e isso só é alcançado por objetos estáticos. Modificando o código para

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};
}

ou

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};
}

Permite criar um constexpr std::span.


5
Escopo não é o problema. A duração do armazenamento é. Local estático deve funcionar.
— eerorika

Também funciona se todos forem objetos locais de uma constexprfunção (sem explícito static). Esses objetos têm duração de armazenamento estático padrão ou isso é algo diferente?
— N314159

@ n314159 Não tenho certeza se isso é permitido ou se você se interessou pelo tema: se nenhuma especialização de uma função constexpr for uma expressão constante do núcleo, a função está mal formada, nenhuma cláusula de diagnóstico necessário. [expr.const] / 10 permite apenas variáveis ​​estáticas.
— NathanOliver

@ n314159: Não sei exatamente o que você está dizendo que funciona (ou “funciona”), mas tenha cuidado com a diferença entre usar algo como expressão constante em uma função (constexpr ou não) e usar algo para construir uma constante expressão através de uma função constexpr.
— Davis Herring

Você pode querer dizer que os não-estático (constante) valores podem ser usados em expressões constantes, mas não seus endereços .
— Davis Herring
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.