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?

Andreas Loanjoe
fonte
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.

NathanOliver
fonte
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