const
overload of lazy_split_view::begin
should be constrained by const Pattern
Section: 25.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.
Modify 25.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; } }; […] }