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.
–Arthur