3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor

Section: 25.7.27.2 [range.adjacent.view], 25.7.28.2 [range.adjacent.transform.view], 25.7.30.2 [range.slide.view] Status: C++23 Submitter: Hewill Kang Opened: 2023-01-06 Last modified: 2023-11-22

Priority: Not Prioritized

View all issues with C++23 status.

Discussion:

Like most range adaptors, these three views accept a single range and store it as a member variable. However, they do not provide a base() member function for accessing the underlying range, which seems like an oversight.

[2023-02-01; Reflector poll]

Set status to Tentatively Ready after seven votes in favour during reflector poll.

[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4917.

  1. Modify 25.7.27.2 [range.adjacent.view] as indicated:

    namespace std::ranges {
      template<forward_range V, size_t N>
        requires view<V> && (N > 0)
      class adjacent_view : public view_interface<adjacent_view<V, N>> {
        V base_ = V();                      // exposition only
        […]
      public:
        adjacent_view() requires default_initializable<V> = default;
        constexpr explicit adjacent_view(V base);
    
        constexpr V base() const & requires copy_constructible<V> { return base_; }
        constexpr V base() && { return std::move(base_); }
        […]
      };
    }
    
  2. Modify 25.7.28.2 [range.adjacent.transform.view] as indicated:

    namespace std::ranges {
      template<forward_range V, move_constructible F, size_t N>
        requires view<V> && (N > 0) && is_object_v<F> &&
                 regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
                 can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
      class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
        movable-box<F> fun_;                        // exposition only
        adjacent_view<V, N> inner_;                 // exposition only
    
        using InnerView = adjacent_view<V, N>;      // exposition only
        […]
      public:
        adjacent_transform_view() = default;
        constexpr explicit adjacent_transform_view(V base, F fun);
    
        constexpr V base() const & requires copy_constructible<InnerView> { return inner_.base(); }
        constexpr V base() && { return std::move(inner_).base(); }
        […]
      };
    }
    
  3. Modify 25.7.30.2 [range.slide.view] as indicated:

    namespace std::ranges {
      […]
      template<forward_range V>
        requires view<V>
      class slide_view : public view_interface<slide_view<V>> {
        V base_;                            // exposition only
        range_difference_t<V> n_;           // exposition only
        […]
      public:
        constexpr explicit slide_view(V base, range_difference_t<V> n);
    
        constexpr V base() const & requires copy_constructible<V> { return base_; }
        constexpr V base() && { return std::move(base_); }
        […]
      };
      […]
    }