On Wed, Oct 25, 2023 at 10:04 AM Hewill Kang via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
But it would be nice
to have automatic conversion between std::span<T>::iterator convertible
to std::span<T const>::iterator.

In C++23, you can just use span<T>::const_iterator.

I assume OP's code is something like this:

    void test(std::span<int> s, std::span<const int> cs) {
        if (s.begin() == cs.begin()) { ... }  // non-portable
        if (s.cbegin() == cs.begin()) { ... }  // still non-portable, IIUC
    }

OP, IMHO LWG 3989 is closely related to your problem. The question there is whether we can ask e.g. `if (s.end() + 1 == cs.begin())`. At least MSVC and libc++ say "no, you cannot portably ask that at all; that's a bounds-check violation."
In OP's case also, I think there's a plausible argument to be made that `s` and `cs` are different span objects, and iterators into one span shouldn't be allowed to compare with iterators into the other, any more than you're allowed to do that with iterators-into-vectors or iterators-into-std::arrays.

The portable solution to both problems is to drop down into raw-pointer-land:

    void test(std::span<int> s, std::span<const int> cs) {
        if (s.data() == cs.data()) { ... }  // OK
        if (std::to_address(s.begin()) == std::to_address(cs.begin())) { ... }  // OK
    }

I tend to agree with OP that this is a bad situation. I wish span iterators were just pointers. But I don't think that's ever likely to happen (in the mainstream library vendors, at least), so you've just got to work around it in the (hopefully rare) cases where it matters.

Related reading:
https://quuxplusone.github.io/blog/2022/03/03/why-isnt-vector-iterator-just-t-star/

–Arthur