L'envergure peut-elle être constexpr?

11

Tous les constructeurs de std :: span sont déclarés constexpr, mais je n'arrive pas à faire fonctionner l'un d'eux dans un contexte constexpr. La suppression de la mise en commentaire de l'un des constexpr ci-dessous entraînera une erreur de compilation.

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

Est-il en fait possible de créer un type span constexpr, car il semble que les constructeurs ne puissent jamais être évalués au moment de la compilation lorsqu'ils doivent initialiser un pointeur ou une référence?

Andreas Loanjoe
la source
Décommentez les constexprs ne les supprimez pas.
Andreas Loanjoe
Vous initialisez un intervalle d'exécution que je voulais initialiser un intervalle constexpr
Andreas Loanjoe
Doh. Je ne sais pas pourquoi j'ai fait ça. nevermind
NathanOliver
bizarre, je ne vois pas pourquoi cela serait nécessaire la durée de vie ne vit de toute façon qu'à l'intérieur de la portée locale ...
Andreas Loanjoe
Étroitement liés: stackoverflow.com/q/57545503/2069064
Barry

Réponses:

13

Vous ne pouvez pas utiliser de variables locales de fonction non statique dans une expression constante comme celle-ci. Vous avez besoin de la stabilité des adresses, ce qui n'est possible qu'avec des objets statiques. Modifier le code en

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

Vous permet de créer un fichier constexpr std::span.

NathanOliver
la source
5
La portée n'est pas le problème. La durée de stockage est. Le local statique devrait fonctionner.
eerorika
Cela fonctionne également si tous sont des objets locaux de fonction dans une constexprfonction (sans explicite static). Ces objets ont-ils une durée de stockage statique par défaut ou est-ce différent?
n314159
@ n314159 Je ne sais pas si cela est autorisé ou si vous êtes tombé dans le redouté: si aucune spécialisation d'une fonction constexpr n'est une expression constante de base, la fonction est mal formée, aucune clause de diagnostic requise. [expr.const] / 10 n'autorise que les variables statiques.
NathanOliver
@ n314159: Je ne sais pas exactement ce que vous dites fonctionne (ou "fonctionne"), mais faites attention à la différence entre utiliser quelque chose comme expression constante dans une fonction (constexpr ou non) et utiliser quelque chose pour construire une constante expression via une fonction constexpr.
Davis Herring
Vous voudrez peut-être dire que des valeurs non statiques (constantes) peuvent être utilisées dans des expressions constantes, mais pas dans leurs adresses .
Davis Herring