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

### 3599. The `const` overload of `lazy_split_view::begin` should be constrained by `const Pattern`

Section: 26.7.16.2 [range.lazy.split.view] Status: New Submitter: Hewill Kang Opened: 2021-09-23 Last modified: 2021-10-14

Priority: 3

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

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

View all issues with New status.

Discussion:

Consider the following code snippet:

>     #include <ranges>

>     int main() {
>       auto p = std::views::iota(0)
>              | std::views::take(1)
>              | std::views::reverse;
>       auto r = std::views::single(42)
>              | std::views::lazy_split(p);
>       auto f = r.front();
>     }

`r.front()` is ill-formed even if `r` is a `forward_range`.

This is because the `const` overload of `lazy_split_view::begin` is not constrained by the `const Pattern`, which makes it still well-formed in such cases. When the `const` overload of `view_interface<lazy_split_view<V, Pattern>>::front` is instantiated, the `subrange{parent_->pattern_}` inside `lazy_split_view::outer-iterator<true>::operator++()` will cause a hard error since `const Pattern` is not a `range`.

[2021-09-24; Daniel comments]

This issue is related to LWG 3592.

[2021-10-14; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4892.

1. Modify 26.7.16.2 [range.lazy.split.view], class template `lazy_split_view` synopsis, as indicated:

   > >     namespace std::ranges {

   > >       […]

   > >       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>> {
   > >       private:
   > >         […]
   > >       public:
   > >         […]

   > >         constexpr auto begin() {
   > >           […]
   > >         }

   > >         constexpr auto begin() const requires forward_range<V> && forward_range<const V> &&
   > >                                               forward_range<const Pattern>{
   > >           return outer-iterator<true>{*this, ranges::begin(base_)};
   > >         }

   > >         constexpr auto end() requires forward_range<V> && common_range<V> {
   > >           […]
   > >         }

   > >         constexpr auto end() const {
   > >           if constexpr (forward_range<V> && forward_range<const V> && common_range<const V> &&
   > >                         forward_range<const Pattern>)
   > >             return outer-iterator<true>{*this, ranges::end(base_)};
   > >           else
   > >             return default_sentinel;
   > >         }
   > >       };

   > >       […]

   > >     }