C++ Logo

std-proposals

Advanced search

Re: [std-proposals] `std::counted_sentinel`?

From: Hewill Kang <hewillk_at_[hidden]>
Date: Tue, 19 Dec 2023 00:29:07 +0800
>
> 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_at_[hidden]> 於
2023年12月18日 週一 下午1:22寫道:

> On Sun, Dec 17, 2023 at 11:35 PM Hewill Kang via Std-Proposals
> <std-proposals_at_[hidden]> 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_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-12-18 16:29:19