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?