Generally speaking C++ doesn't allow comparing iterators between different containers. For example:
int main() {
std::vector<int> v = {1, 2, 3};
std::vector<int> w = {4, 5, 6};
std::cout << v.end() == w.end() << std::endl; // undefined!
}
But is this true also for subspans created with std::span::subspan()
? For example:
int main() {
int a[4] = { 1, 2, 3, 4};
std::span<int> s(a);
std::span<int> t = s.subspan(1, 2);
std::cout << t.begin() - s.begin() << std::endl;
}
This prints 1
, which is expected, because internally iterators are probably just pointer to the underlying array. The question is: does the standard guarantee that this works correctly?
And if so, more generally, can I also compare iterators from any spans that come from the same contiguous object in memory? For example:
int main() {
int a[5] = { 1, 2, 3, 4, 5};
std::span<int> s(a);
std::cout << (s.subspan(1, 1).end() < s.subspan(3, 1).begin()) << std::endl;
}
I don't think the standard allows this.
According to the description of Cpp17ForwardIterator in [forward.iterators]:
The domain of
==
for forward iterators is that of iterators over the same underlying sequence.
This means that the equality and inequality operations of two iterators are only defined over the same underlying sequence.
In your example, the underlying sequences of the two iterators being compared are different, because they have different start points and different sizes, which makes comparisons no longer well-defined when one of the iterators is outside the bounds of the other sequence.
As mentioned in the comments, your example will trigger an assert in MSVC-STL's debug mode, which was explained by the maintainer in #1435. Similar issues are also discussed in the Cpp Core Guidelines, see #1157.