Czy rozpiętość może być constexpr?

11

Wszystkie konstruktory std :: span są zadeklarowane jako constexpr, jednak nie wydaje się, aby którykolwiek z nich działał w kontekście constexpr. Odznaczenie któregokolwiek z poniższych constexpr spowoduje błąd kompilacji.

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

Czy w rzeczywistości jest możliwe utworzenie typu rozpiętości constexpr, ponieważ wydaje się, że konstruktorów nigdy nie można ocenić w czasie kompilacji, gdy muszą zainicjować wskaźnik lub odwołanie?

Andreas Loanjoe
źródło
Odkomentuj constexprs nie usuwaj ich.
Andreas Loanjoe,
Inicjujesz przedział czasu wykonywania Chciałem zainicjować przedział constexpr
Andreas Loanjoe,
Doh Nie jestem pewien, dlaczego to zrobiłem. Nevermind
NathanOliver
dziwne, nie rozumiem, dlaczego byłoby to konieczne, tak czy inaczej rozpiętość żyje tylko w zasięgu lokalnym ...
Andreas Loanjoe,
Ściśle powiązane: stackoverflow.com/q/57545503/2069064
Barry

Odpowiedzi:

13

Nie można używać zmiennych lokalnych o funkcji niestatycznej w takim wyrażeniu stałym. Potrzebujesz stabilności adresu i jest to osiągane tylko przez obiekty statyczne. Modyfikacja kodu na

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

lub

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

Pozwala utworzyć constexpr std::span.

NathanOliver
źródło
5
Zakres nie jest problemem. Czas przechowywania wynosi. Statyczny lokalny powinien działać.
eerorika
Działa również, jeśli wszystkie są lokalnymi obiektami constexprfunkcji w ramach funkcji (bez wyraźnego określenia static). Czy takie obiekty mają domyślny czas przechowywania statycznego, czy to coś innego?
n314159,
@ n314159 Nie jestem pewien, czy jest to dozwolone, czy też wpadłeś w przerażenie: jeśli żadna specjalizacja funkcji constexpr nie jest podstawowym stałym wyrażeniem, funkcja jest źle sformułowana, brak wymaganej diagnostycznej klauzuli. [expr.const] / 10 dopuszcza tylko zmienne statyczne.
NathanOliver,
@ n314159: Nie jestem pewien, co dokładnie mówisz, działa (lub „działa”), ale uważaj na różnicę między użyciem czegoś jako stałego wyrażenia w funkcji (constexpr lub no) a użyciem czegoś do skonstruowania stałej wyrażenie za pomocą funkcji constexpr.
Davis Herring
Możesz powiedzieć, że wartości niestatyczne (stałe) mogą być używane w wyrażeniach stałych, ale nie w ich adresach .
Davis Herring