This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3320. `span::cbegin/cend` methods produce different results than `std::[ranges::]cbegin/cend`

Section: 22.7.3.7 [span.iterators] Status: C++20 Submitter: Poland Opened: 2019-11-06 Last modified: 2021-02-25

Priority: 0

View all issues with C++20 status.

Discussion:

Addresses PL 247

`span<T>` provides a `const`-qualified `begin()` method and `cbegin()` method that produces a different result if `T` is not `const`-qualifed:

1. `begin()` produces mutable iterator over `T` (as if `T*`)

2. `cbegin()` produces `const` iterator over `T` (as if `T const*`)

As consequence for the object `s` of type `span<T>`, the call to the `std::cbegin(s)/std::ranges::cbegin(s)` produces different result than `s.cbegin()`.

Proposed change:

Change `span<T>` members `cbegin()/cend()/crbegin()/crend()/const_iterator` to be equivalent to `begin()/end()/rbegin()/rend()/iterator` respectively.

Tomasz Kamiński:

Per LEWG discussion in Belfast these methods and related typedefs should be removed.

[2019-11 Status to Ready during Wednesday night issue processing in Belfast.]

Proposed resolution:

This wording is relative to N4835.

1. Modify 22.7.3.1 [span.overview], class template `span` synopsis, as indicated:

   >     namespace std {
   >       template<class ElementType, size_t Extent = dynamic_extent>
   >       class span {
   >       public:
   >         // constants and types
   >         using element_type = ElementType;
   >         using value_type = remove_cv_t<ElementType>;
   >         using index_type = size_t;
   >         using difference_type = ptrdiff_t;
   >         using pointer = element_type*;
   >         using const_pointer = const element_type*;
   >         using reference = element_type&;
   >         using const_reference = const element_type&;
   >         using iterator = implementation-defined; // see 22.7.3.7 [span.iterators]
   >         using const_iterator = implementation-defined;
   >         using reverse_iterator = std::reverse_iterator<iterator>;
   >         using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   >         static constexpr index_type extent = Extent;

   >         […]
   >         // 22.7.3.7 [span.iterators], iterator support
   >         constexpr iterator begin() const noexcept;
   >         constexpr iterator end() const noexcept;
   >         constexpr const_iterator cbegin() const noexcept;
   >         constexpr const_iterator cend() const noexcept;
   >         constexpr reverse_iterator rbegin() const noexcept;
   >         constexpr reverse_iterator rend() const noexcept;
   >         constexpr const_reverse_iterator crbegin() const noexcept;
   >         constexpr const_reverse_iterator crend() const noexcept;
   >         friend constexpr iterator begin(span s) noexcept { return s.begin(); }
   >         friend constexpr iterator end(span s) noexcept { return s.end(); }
   >         […]
   >       };
   >     […]
   >     }

2. Modify 22.7.3.7 [span.iterators] as indicated:

   >     using iterator = implementation-defined;
   >     using const_iterator = implementation-defined;

   > > -1- The types models `contiguous_iterator` (23.3.4.14 [iterator.concept.contiguous]), meets the Cpp17RandomAccessIterator requirements (23.3.5.7 [random.access.iterators]), and meets the requirements for constexpr iterators (23.3.1 [iterator.requirements.general]). All requirements on container iterators (22.2 [container.requirements]) apply to `span::iterator` and `span::const_iterator` as well.

   > […]

   >     constexpr const_iterator cbegin() const noexcept;

   > > -6- Returns: A constant iterator referring to the first element in the span. If `empty()` is `true`, then it returns the same value as `cend()`.

   >     constexpr const_iterator cend() const noexcept;

   > > -7- Returns: A constant iterator which is the past-the-end value.

   >     constexpr const_reverse_iterator crbegin() const noexcept;

   > > -8- Effects: Equivalent to: `return const_reverse_iterator(cend());`

   >     constexpr const_reverse_iterator crend() const noexcept;

   > > -9- Effects: Equivalent to: `return const_reverse_iterator(cbegin());`