In [range.lazy.split.view], the synopsis of lazy_split_view (the original C++20 split_view before P2210) is defined as follows:
template<input_range V, forward_range Pattern>
requires view<V> && view<Pattern> &&
(forward_range<V> || tiny-range<Pattern>)
class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
private:
V base_ = V();
Pattern pattern_ = Pattern();
// ...
};
Unlike the redesigned split_view, it can split input_range. According to its constraints, we can find that when V is input_range, the Pattern must model tiny-range, where tiny-range is defined as follows:
template<auto> struct require-constant;
template<class R>
concept tiny-range =
sized_range<R> &&
requires { typename require-constant<remove_reference_t<R>::size()>; } &&
(remove_reference_t<R>::size() <= 1);
In order to ensure that the size of tiny-range is less than or equal to 1 at compile-time, we must obtain the size of R through its type, which also requires the size() function of R to be a constexpr static function.
And in the standard, there are indeed range type that model tiny-range such as empty_view and single_view (godbolt):
#include <ranges>
#include <sstream>
int main() {
auto ints = std::istringstream{"42"};
auto r = std::ranges::istream_view<int>(ints);
auto s1 = r | std::views::lazy_split(std::views::empty<int>);
auto s2 = r | std::views::lazy_split(std::views::single(0));
}
But in my opinion, when V is input_range, std::array<int, 1>, span<int, 1> or even int[1] can be valid Pattern types, because we can also directly extract their size from the type, but none of the three have a static size() function, which makes them unable to model tiny_range.
In addition, because of the existence of the following CTAD:
template<class R, class P>
lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;
When V is an input_range, the Pattern can never be a non-view range, because views::all_t will produce ref_view or owning_view, neither of which is tiny-range even Pattern itself may model tiny-range (godbolt):
#include <ranges>
#include <stream>
#include <array>
int main() {
auto ints = std::istringstream{"42"};
auto r = std::ranges::istream_view<int>(ints);
std::array p{42};
r | std::views::lazy_split(p); // ref_view<array<int, 1>> is not tiny-range
r | std::views::lazy_split(std::span{p}); // span<int, 1>> is not tiny-range
}
In summary, the definition of tiny-range seems to limit the type of Pattern range to a very small set when V is an input_range. What is the reason for such restriction in the standard?