12

All the constructors of std::span are declared constexpr, however I can't seem to get any of them to work in a constexpr context. Uncommenting any of the constexpr below will result in a compilation error.

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

Is it in fact possible to create a constexpr span type, since it seems like constructors can never be evaluated at compile time when they have to initialize a pointer or reference?

Barry
  • 286,269
  • 29
  • 621
  • 977
Andreas Loanjoe
  • 2,205
  • 10
  • 26

1 Answers1

16

You can't use non-static function local variables in a constant expression like that. You need address stability and that is only achieved by static objects. Modifying the code to

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

or

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

Allows you to create a constexpr std::span.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 5
    Scope is not the problem. Storage duration is. Static local should work. – eerorika Nov 20 '19 at 19:48
  • 1
    It also works if all are function local objects within a `constexpr` function (without explicit `static`). Do such objects have default static storage duration or is this something different? – n314159 Nov 20 '19 at 19:57
  • @n314159 I'm not sure if that is allowed or if you've fallen into the dreaded: if no specialization of a constexpr function is a core constant expression the function is ill-formed, no diagnostic required clause. [\[expr.const\]/10](https://timsong-cpp.github.io/cppwp/expr.const#10) only allows static variables. – NathanOliver Nov 20 '19 at 20:06
  • @n314159: I’m not sure exactly what you’re saying works (or “works”), but be careful of the difference between using something as a constant expression **in** a function (constexpr or no) and using something to **construct** a constant expression *via* a constexpr function. – Davis Herring Nov 21 '19 at 01:51
  • You might want to say that non-static (constant) *values* can be used in constant expressions, but not their *addresses*. – Davis Herring Nov 21 '19 at 03:34