Skip to content

<span>: checked iterators became too intolerant #1435

Description

@PragmaTwice

Describe the bug
Checked iterators controlled by _ITERATOR_DEBUG_LEVEL provide some safe guarantee, but these assertions became more and more intolerant for programming in normal styles.

Command-line test case

std::array<std::byte, 10> a{};
std::span<std::byte> s1 = a;
std::span<std::byte> s2 = s1.subspan(1);
std::cout << s2.begin() - s1.begin(); // assertion failed while _ITERATOR_DEBUG_LEVEL >= 1

Expected behavior
Both these two span s1 and s2 came from a, hence they share the same underlying sequence.
I think this design makes iterators of the same type pointing to the same element not equivalent. (may be an LWG issue?)
From a programmer’s point of view, the code snippet above is a common requirement, especially when parsing certain data.

STL version

Microsoft Visual Studio Community 2019
Version 16.7.7

Activity

  1. StephanTLavavej commented on Nov 8, 2020

    @StephanTLavavej
    Member

    I think this should be submitted as an LWG issue. We believed we were strictly enforcing the Standard's intent, but the Standardese doesn't appear to be crystal clear to me.

    WG21-N4868 22.7.3.7 [span.iterators]/2 says "All requirements on container iterators (22.2) apply to span::iterator as well." but it is not completely clear what "different spans" are, unlike different vectors. Certainly, spans that have the same data and size (i.e. are copies) are compatible for the purposes of iterator comparison/subtraction, etc., but what about overlapping spans or even disjoint spans? (e.g. getting a span to the first half and second half of a range).

    My preference would be for the Standard to say what we are currently enforcing (only same data and size are compatible), so if you want to subtract addresses, you need to do so with raw pointers. The span philosophy is to discourage unsafe code, and subtracting iterators to potentially different ranges is potentially unsafe. However, if the Standard clearly said that overlapping spans have compatible iterators, or even that span iterator operations are valid when the underlying pointer operations are valid, we would change our checks accordingly.

  2. miscco commented on Nov 8, 2020

    @miscco
    Contributor

    This is not possible as far as I know.

    The problem is that we cannot compare arbitrary pointers. Say we habe an array a and an array b, then comparing any pointer from a with any pointer from b is forbidden.

    So while the example alludes that it "could" work, the general case is impossible.

    Then there is also a problem with constexpr support. Yes this works for array, but not for vector (at least currently) and other user provided containers.

    So long story short. This is not something we could vor should support IMHO. If the user really wants to he can always fall back to pointers via to_address

  3. MikeGitb commented on Nov 8, 2020

    @MikeGitb

    Just want to mention that gsl::span has the same "problem" at least in the past. There you couldn't even compare two iterators from two spans referring exactly the same range (e.g. if they belonged to two copies of the same iterator).

    Back then that was a deliberate decision by the inventor, so I wouldn't at all be surprised, if that is also a by design limitation of std::span, even if I don't agree with it.

  4. frederick-vs-ja commented on Oct 3, 2023

    @frederick-vs-ja
    Contributor

    LWG-3989 has been filed for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    LWG issue neededA wording defect that should be submitted to LWG as a new issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions