Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2024-09-15 17:55:06


Hi Steve,
Thanks for weighing in.

niedz., 15 wrz 2024 o 16:42 Steve Downey via Boost <boost_at_[hidden]>
napisał(a):

> The core motivation is not having yet another optional-like in the standard
> library.

Understood. However, there is a trade-off here: additional optional-like
type versus additional member functions in std::optional.

> Ranges needs a 0-or-1 range as a primitive for where the filter
> algorithm isn't quite the right answer, in particular for range
> comprehension desugaring which comes up fairly often by hand.
>

I am not well familiar with ranges, so I must admit that upon reading the
phrase "range comprehension desugaring" I bailed out. Is there a place that
describes the term?
However, I understood that in order to effectively compose ranges one needs
the additional component, which can either be implemented as a stand alone
ranges component or through adding member functions to `optional`.

> Having a range type like empty or single, without a bunch of the implicit
> conversion operations from the underlying type, was my preference, however
> adding the range ops to optional<T> was a reasonable fallback.
>

Indeed, I would also think that if this is only needed to compose ranges,
it should be added as a <ranges>-component: view, adapter.

And optional not being a container was always a suspect position,
> especially after the addition of other fixed size or limited size
> containers. Making it a full Cpp17 Container is probably over the top, and
> might have confused existing code, but adding the range interface is
> minimal.
>

In retrospect, I think I agree with Tony Van Eerd's observation that it was
a design mistake to combine two models in `boost::optional`, and by
extension in `std::optional`:
1. That optional<T> is a T with an additional state. hence the conversions
and comparisons with `T` and `none`/`nullopt`.
2. That optional<T> is a container holding zero or one element of `T` hence
the interface for querying for being empty and for accessing the element.

But now that we have this confusion, I am not sure if extending one of
these interfaces further is the right way to go.

I can think of a couple of reasons why adding a range interface to optional
is not desired.
1. A general design principle that a class should have a minimal interface
required to manage its invariant. Anything else, if needed, should be free
functions operating on the class interface. The Standard Library components
do not necessarily follow it (std::string being the best (worst) example).
2. Given that we have standard concepts that detect the range interface,
`std::ranges::range` it is reasonable to assume that programmers use it in
their code, also for controlling the overload resolution. Suddenly adding
the range interface to optional is likely to break their code. (While any
change whatsoever could theoretically break code, the current problem is
more likely, because we are talking about the standardized concept.)
3. Increasing (thus complicating) the class interface without motivating
usages is a bad trade-off.

The usages for the interop with ranges were given, but it looks like there
are no other usages not involving ranges.
The usage with the for-loop indeed seems like a hack rather than a
technique that I would comfortably endorse.

Regards,
&rzej;

> On the other hand, once we have std::optional<T&> and possibly
> optional<T&&>, boost's optional should probably be avoided in codebases
> using C++26 or later.
>
> On Sat, Sep 14, 2024 at 7:59 AM Thomas Fowlery via Boost <
> boost_at_[hidden]> wrote:
>
> > Every feature should be well motivated by a real use case or a set of use
> > cases. I don't find any of the examples in this proposal motivating. In
> > fact, this feature seems to encourage bad code, judging by the examples:
> > - using transform(f) | join with an optional-returning function f,
> instead
> > of using a simple filter(predicate)
> > - materializing optionals when not really necessary (incurs extra
> > moves/copies)
> > - abusing the range-for loop for unwrapping optionals
> >
> > Best regards,
> > Thomas
> >
> > _______________________________________________
> > Unsubscribe & other changes:
> > http://lists.boost.org/mailman/listinfo.cgi/boost
> >
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk