3

[range.lazy.split.view]中, ( P2210之前lazy_split_view的原始C++20 )的概要定义如下:split_view

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();
  // ...
};

与重新设计不同的是split_view,它可以拆分input_range。根据其约束,我们可以发现when Vis input_rangePatternmust model tiny-range,其中tiny-range定义如下:

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);

为了保证在编译时tiny-range的大小小于等于,我们必须通过它的类型来获取大小,这也要求函数是函数。1 Rsize()Rconstexpr static

而且在标准中,确实有范围类型,tiny-range例如empty_viewsingle_viewgodbolt):

#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));
}

但在我看来,when Vis input_range, std::array<int, 1>,span<int, 1>甚至int[1]可以是有效Pattern类型,因为我们也可以直接从类型中提取它们的大小,但是这三个都没有static size()函数,导致无法建模tiny_range

另外,由于存在以下CTAD:

template<class R, class P>
lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;

V是时input_rangePattern永远不能是非view范围,因为views::all_t会产生ref_viewor owning_view,这两者都不是tiny-range甚至Pattern它自己都可以建模tiny-range天螺栓):

#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
}

总之, 的定义tiny-range似乎将范围的类型限制Pattern为一个非常的集合 when Vis an input_range。标准中这样限制的原因是什么?

4

0 回答 0