4108. lazy_split_view should be sized_range when pattern is empty tiny-range

Section: 25.7.16.2 [range.lazy.split.view], 25.7.17.2 [range.split.view] Status: SG9 Submitter: Hewill Kang Opened: 2024-05-23 Last modified: 2024-08-02

Priority: 4

View other active issues in [range.lazy.split.view].

View all other issues in [range.lazy.split.view].

View all issues with SG9 status.

Discussion:

When the pattern range is empty, lazy_split_view will split each element into individual subranges, which means its size is equal to the size of the underlying range.

Since we already have a tiny-range that can determine whether the range is empty by its type, it seems valuable to provide a size for lazy_split_view in this case, given that we already specifically checked for it by Pattern::size() == 0 in inner-iterator::operator++().

[2024-08-02; Reflector poll]

Set priority to 4 after reflector poll. Set Status to SG9. "Design change". "tiny-range should accept span<T, 0|1> or ref_view<array<T, 0|1>>, see related paper P1419."

Proposed resolution:

This wording is relative to N4981.

  1. Modify 25.7.16.2 [range.lazy.split.view] as indicated:

    namespace std::ranges {
      template<auto> struct require-constant;                        // exposition only
    
      template<class R>
      concept tiny-range =                                           // exposition only
         sized_range<R> &&
         requires { typename require-constant<remove_reference_t<R>::size()>; } &&
         (remove_reference_t<R>::size() <= 1);
      
      template<input_range V, forward_range Pattern>
        requires view<V> && view<Pattern> &&
                 indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
                 (forward_range<V> || tiny-range<Pattern>)
      class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
        […]
        constexpr auto size()
          requires sized_range<V> &&
                   tiny-range<Pattern> && (Pattern::size() == 0) {
          return ranges::size(base_);
        }
    
        constexpr auto size() const
          requires sized_range<const V> &&
                   tiny-range<Pattern> && (Pattern::size() == 0) {
          return ranges::size(base_);
        }
      };
      […]
    }
    
  2. Modify 25.7.17.2 [range.split.view] as indicated:

    namespace std::ranges {
      template<forward_range V, forward_range Pattern>
        requires view<V> && view<Pattern> &&
                 indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
      class split_view : public view_interface<split_view<V, Pattern>> {
        […]
        constexpr auto size()
          requires sized_range<V> &&
                   tiny-range<Pattern> && (Pattern::size() == 0) {
          return ranges::size(base_);
        }
    
        constexpr auto size() const
          requires sized_range<const V> &&
                   tiny-range<Pattern> && (Pattern::size() == 0) {
          return ranges::size(base_);
        }
      };
      […]
    }