C++ Logo

std-proposals

Advanced search

Re: [std-proposals] contiguous_iterator is too restrictive in C++26 std::optional<T&>

From: Piotr Nycz <piotrwn1_at_[hidden]>
Date: Sat, 17 Aug 2024 18:11:31 +0200
> ----------------------------------------------------------------------
> On Fri, Aug 16, 2024 at 8:00?AM Piotr Nycz via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > Hi,
> >
> > I have a small request(bug fix? improvement) to existing (probably accepted already) proposals to C++26 about std::optional class.
> >
> > I am pretty sure (I tested it) that contiguous_iterator as specified in this paper Give std::optional Range Support is too restrictive as for next proposal - std::optional<T&>
> > In my opinion it should be just input_iterator.
> >
> > The main reason is that for input_iterator I wouldn't need to have T defined - it can still be forward declared - thus compilation time will not have to increase - nor I have to add any extra includes when changing from:
> >
> > struct Some;
> > void func(Some&);
> > std::optional<Some&> a = get();
> >
> > if (a) func(*a);
> >
> > to:
> >
> > ...
> > for (auto& v: a) func(v);
> Date: Fri, 16 Aug 2024 10:04:14 -0400
> From: Jason McKesson <jmckesson_at_[hidden]>>
> I would argue that you shouldn't do that at all; that's not really the
> point of allowing an `optional` to be a range. It obfuscates the clear
> meaning of the original code.
>

This is just simple example code. People on such forums always request
simple examples to illustrate the problem - then complain that for
such simple code no need to change anything...

> > The other reasons - who would care if the iterator type to 0-or-1 range is contiguous or not, then no need to complicate...
>
> A contiguous range is convertible to a pointer range or a span. Input
> ranges are not. There are many interfaces which require contiguous
> ranges. From a user-perspective, there is no reason why a rangified
> optional<T> should not be contiguous (and thus usable with code that
> requires contiguous ranges).
>

>From the user-perspective there is one important reason to have a less
restrictive category than contiguous - the one more possibility of
compilation time improvement. And I am referring here explicitly to
optional<T&> (optional to reference). With optional<Some&> I can
forward declared Some - and this "some" type can be quite complex. But
the implementation of contiguous range as proposed in the mentioned
paper requires this "Some&" type to be known at the point of usage.
So, I am proposing to relax this constraint - and proposing an even
simpler implementation of iterator.

I can accept the argument that converting to std::span would be
troublesome without optional being contiguous range. I can do
"std::span<Some> sp(&*opt, size_t(opt.has_value()));" in C++23 -- but
that looks weird...

But I doubt there are any ranges algorithm that can do reasonably
better for a range of 0-or-1 elements with contiguous range than any
other category. For one element range everything looks like a
contiguous range, for empty range it is even more true statement.

> Date: Fri, 16 Aug 2024 11:25:02 -0400
> From: "Arthur O'Dwyer" <arthur.j.odwyer_at_[hidden]>
> To: std-proposals_at_[hidden]
> Subject: Re: [std-proposals] contiguous_iterator is too restrictive in
> C++26 std::optional<T&>
>
> On Fri, Aug 16, 2024 at 10:04?AM Jason McKesson via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
> > On Fri, Aug 16, 2024 at 8:00?AM Piotr Nycz via Std-Proposals <
> > std-proposals_at_[hidden]> wrote:
> > >
> > > for (auto& v: a) func(v);
> >
> > I would argue that you shouldn't do that at all; that's not really the
> > point of allowing an `optional` to be a range. It obfuscates the clear
> > meaning of the original code.
> >
>
> Right. Now, I do think a lot of people *are* going to do exactly that ? I
> think a lot of WG21 members voted for the paper because they *want* to do
> exactly that ? but that still doesn't make it something that you *should*
> want to do. (Similarly, CTAD: people voted for it because they wanted to do
> it, but you *should* not do it.)
>
> > > In practice it is also easier to implement input iterator, not to
> mention less code to write
>
> Well, that's not true. In practice, the contiguous iterators returned from
> `optional::begin` and `optional::end` can be plain old `T*`:
> T *begin() { return &payload_; }
> T *end() { return &payload_ + 1; }
> Strangely Beman.Optional26
> <https://github.com/beman-project/Optional26/blob/main/include/Beman/Optional26/optional.hpp>
> fails to do this; they *do* pay all the extra LoC for a custom iterator
> class type.
> But, on the third hand, every library vendor implementing this paper will
> already have a custom contiguous iterator type, which they use for e.g.
> vector::iterator ? libc++ calls it `__wrap_iter<T*>`. So in practice,
> library vendors will just do
> using iterator = __wrap_iter<T*>;
> iterator begin() { return iterator(&payload_); }
> iterator end() { return iterator(&payload_ + 1); }
> which is still no additional LoC. In fact it's *fewer* LoC than your idea
> of writing a custom input-iterator class type just for this purpose.
>
> ?Arthur
> -------------- next part --------------
> HTML attachment scrubbed and removed
>
> ------------------------------
>
> Message: 4
> Date: Fri, 16 Aug 2024 18:00:25 +0100
> From: L?n?rd Szolnoki <cpp_at_[hidden]>
> To: std-proposals_at_[hidden]
> Subject: Re: [std-proposals] contiguous_iterator is too restrictive in
> C++26 std::optional<T&>
> Message-ID: <1B6C8321-F613-4AD7-9AA5-6510656CAC04_at_[hidden]>
> Content-Type: text/plain; charset="utf-8"
>
> Hi,
>
> I think it's possible to implement a contiguous iterator in the shape of struct { T* ptr; bool is_end; }; and still satisfy the semantic constraints.
>
> The only operation that would require a complete type is `to_address` , which you don't use in your examples.
>
> It's still not necessarily a good idea though.
>

In std::optional<T&> I bet it will be implemented with "T* ptr;" - so
do I need to use std::to_address to get pointer from pointer? If I
need to use it - then - well C++ is not going in a good direction...

BR,
Piotr

Received on 2024-08-17 16:11:44