I think you've misunderstood how `counted_iterator` works. It doesn't
keep track of how many elements you've iterated over. It's an iterator
that has a maximum count for how far into the sequence it is.

You are right, I completely misunderstood the meaning of member n saved by counted_iterator. If the original range models sized_range, I think I could do what the above example does by passing its size to the counted_iterator, e.g.

auto l = std::list{1, 2, 0, 3, 5, 6, 7, 9, 10, 0, 11};
auto s = std::ranges::subrange(std::counted_iterator(l.begin(), l.size()), 
                               std::default_sentinel);

However, if the original range is not a sized_range, is there a neat way in the standard to still do this without beforehand calculating its size using liner-time ranges::distance?

 
Hewill

Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> 於 2023年12月18日 週一 下午1:22寫道:
On Sun, Dec 17, 2023 at 11:35 PM Hewill Kang via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
>
> Hello C++ experts,
>
> I wonder why the standard has std::move_sentinel but not std::counted_sentinel, because in my opinion the latter is super valuable in certain situations.

`move_sentinel` is required because `move_iterator` is an
input_iterator regardless of the underlying iterator category.

> Suppose we have a non-sized range:
>
>  auto l = std::list{1, 2, 0, 3, 42, 42, 5, 6, 7, 9, 10, 42, 0, 11};
>  auto r = l | std::views::filter([](int x) { return x != 42; });
>
> And we want to apply views::split or views::chunk_by to it to split it into subranges (https://godbolt.org/z/sKh3zM1Wf):
>
> auto split = r | std::views::split(0);
> for (auto subrange : split)
>   std::println("{} (size: {})", subrange, std::ranges::distance(subrange));
> auto chunk = r | std::views::chunk_by(std::less{});
> for (auto subrange : chunk)
>   std::println("{} (size: {})", subrange, std::ranges::distance(subrange));
>
> Unfortunately, these subranges are not sized_range even if we have iterated through them from beginning to end, since they just contain two iterators of the original range which cannot be subtracted.
>
> In order to get their sizes, I have to recalculate their sizes using ranges::distance, which makes it necessary to iterate over them again.
>
> However, if we introduce a std::counted_sentinel corresponding to std::counted_iterator for comparison with the former's underlying iterator, for example:

I think you've misunderstood how `counted_iterator` works. It doesn't
keep track of how many elements you've iterated over. It's an iterator
that has a maximum count for how far into the sequence it is.
Incrementing past the point where the iterator count is 0 is UB, just
as with any iterator.

That is, you create a `counted_iterator` by giving it an iterator
*and* the number of elements forward that it can be incremented.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals