Does span propagate const?

c++, c++20, constants, std-span

Solution

Propagating const for a type like `span` doesn't actually make much sense, since it cannot protect you from anything anyway.

Consider:

void foo(std::span<int> const& s) {
    // let's say we want this to be ill-formed
    // that is, s[0] gives a int const& which
    // wouldn't be assignable
    s[0] = 42;

    // now, consider what this does
    std::span<int> t = s;

    // and this
    t[0] = 42;
}

Even if `s[0]` gave an `int const&`, `t[0]` surely gives an `int&`. And `t` refers to the exactly same elements as `s`. It's a copy after all, and `span` doesn't own its elements - it's a reference type. Even if `s[0] = 42` failed, `std::span(s)[0] = 42` would succeed. This restriction wouldn't do anyone any good.

The difference with the regular containers (e.g. `vector`) is that the copies here still refer to the same elements, whereas copying a `vector` would give you entirely new elements.

The way to have `span` refer to immutable elements isn't to make the `span` itself `const`, it's to make the underlying elements themselves `const`. That is: `span<T const>`, not `span<T> const`.

Problem

The standard containers propagate const. That is, their elements are automatically const if the containers themselves are const. For example: ``` const std::vector vec{3, 1, 4, 1, 5, 9, 2, 6}; ranges::fill(vec, 314); // impossible const std::list lst{2, 7, 1, 8, 2, 8, 1, 8}; ranges::fill(lst, 272); // impossible ``` Builtin arrays also propagate const: ``` const int arr[] {1, 4, 1, 4, 2, 1, 3, 5}; ranges::fill(arr, 141); // impossible ``` However, I noticed that `std::span` (presumably) does not propagate const. Minimal Reproducible Example: ``` #include <algorithm> #include <cassert> #include <span> namespace ranges = std::ranges; int main() { int arr[] {1, 7, 3, 2, 0, 5, 0, 8}; const std::span spn{arr}; ranges::fill(spn, 173); // this compiles assert(ranges::count(arr, 173) == 8); // passes } ``` Why does this code work fine? Why does `std::span` treat const differently than the standard containers?

Original source