该
sized_range
概念对范围进行了细化,要求范围内的元素数量可以在摊销的 常数时间内使用来确定ranges::size
。template<class T> concept sized_range = range<T> && requires(T& t) { ranges::size(t); };
该标准规定,保证在恒定时间内获得 的大小。考虑以下:ranges::sized_range
auto r1 = std::views::iota(0)
| std::views::filter([](int x){ return x % 2 == 0; })
| std::views::take(1'000'000);
r1
显然不是sized_range
,因为不可能在常数时间内得到它的大小,这也意味着我们ranges::size
用来评估它的大小也是病态的。
但我偶然发现,如果我们应用views::reverse
它,新的范围r2
突然变成了 a sized_range
,我们可以直接使用godboltranges::size
来正确获取它的大小:
auto r2 = r1 | views::reverse;
static_assert(!ranges::sized_range<decltype(r1)>);
static_assert( ranges::sized_range<decltype(r2)>);
std::cout << std::ranges::size(r2) << "\n"; // print 500'000
但是,很明显新范围r2
不是 a sized_range
,因为我们永远无法在恒定时间内得到它的大小,这似乎违反了标准所说的。
为什么可以views::reverse
将非sized_range
变成a sized_range
?显然,这种转换不会对原始范围的大小产生任何影响。这是标准缺陷还是库错误?