|
Boost : |
From: Neil Groves (neilgroves_at_[hidden])
Date: 2024-12-21 04:00:07
On Fri, 20 Dec 2024, 22:58 Christian Mazakas via Boost, <
boost_at_[hidden]> wrote:
> On Fri, Dec 20, 2024 at 11:37â¯AM Neil Groves <neilgroves_at_[hidden]> wrote:
>
> > As you know I've tried seeing how far I could get with some work in
> > Boost.Range. I appreciate this isn't the solution you are dreaming of.
> >
> ...
> >
> I wondered if reading this example line above if it didn't look quite as
> > horrific as perhaps you were imagining?
> >
> > One unfortunate aspect of the original snippet is the boost::optional
> > choice of the word "map" where we are also working with a concrete "map"
> > container.
> >
> > There is plenty of work to do if this is of interest to anyone. I would
> > want to ensure there was no performance overhead, and currently I'm not
> > entirely convinced that my initial implementation that uses the member
> > equal_range is optimal. This is an implementation detail, which I would
> > work through.
> >
> > The value_or ( or front_or ) functionality for non-multi containers can
> be
> > added in a similar manner, and be broadly usable for range algorithms.
> > ...
> > If this is of any interest to you I'll look at putting some of this into
> > the develop branch of Boost.Range. If it is not interesting I shall
> > continue on my branch and build a more compelling iteration that I shall
> > land later.
> >
> > I hope this helps
> >
>
>
> Fwiw, I don't mean to be a hater and I'm happy you're not discouraged.
>
I am discouraged by how long it took me to recognising the signs that no
outcome would have been satisfactory other than total unconditional
agreement with the original proposition.
The find operation often wants the power of the iterator, but then other
times a query like "at" that doesn't throw would be useful. I thought the
find, tolerating absence, was your motivating use-case.
> It's like I said, I don't actually have a strong opinion here either way.
>
> I'm with Andrey, I think the iterator API *is* the useful API. Typically,
> when I find something in a map, I'll either erase or do something else
> where reusing the iterator is a key part of everything.
>
I would not take away the iterator idiom. It has proven to be extremely
powerful.
> My whole thing was about what users actually wanted vs all the costs of
> everything else.
>
> In C++, we have basically unlimited power so we can honestly do basically
> whatever we want.
>
> I think most users just want `try_find() -> optional<T&>`, with
> `std::optional` and not Boost. Boost is okay as a polyfill, but users have
> told us ad nauseum that in 2024, they prefer STL versions.
>
This is a Boost mailing list. I assumed you wanted to see what we thought
and could achieve and use what was learned. If the users now only want std
( these users seem to change their requirements very frequently ), what was
it you wanted from the irrelevant boost developers?
By showing changes in Boost.Range I hoped to make Boost.Range more useful
and assumed similar changes could be made to std ranges. The header
includes for boost range are not huge and so far do not require optional of
either flavour.
I have shown that by changes to range it can be achieved. The std ranges
can do all that I have done in Boost.Range by way of example. I accept
there may be issues with the std range header overhead, but consider that
something fixable.
> Second, I think the burden on users to opt into the perfectly generic
> version is too much for the little we're actually doing.
>
The header overhead is hundreds of lines less than your proposal with
optional.
My bias is to reducing the duplications, fixing the abstractions to be
small and orthogonal and fixing the headers to have more and smaller files.
The excessive header include overhead is partly due to a failure to
decompose the problems. The include of optional adds more overhead than the
include of the range map adapter. My implementation shows it can be
implemented in just a few lines of code. Less overhead than including
optional. And my solution only requires including the range adapter if you
use it. Your solution requires every map header to include optional even if
the feature is not used.
My solution is more general, less intrusive, and has less header cost than
the original proposal. Even the target syntax was largely approximated.
My self assessment is that this works well for my understanding of the
expressed requirements. I was surprised this is not an attractive option
but fully accept it isn't what you want.
> For a user to now get the behavior they want, they'll have to depend on
> Boost.Range, include the Range headers and then setup their functional
> pipeline just to do something that could've been this:
>
> for (auto& user : users_map.try_find(user_id)) { user.status =
> deactivated; }
>
Yes for Boost.Range they need to include the relvant Boost.Range adaptor
header. A similar adapter could be added to the std. To use optional you
would have to include optional. The adapter header is considerably smaller
than the optional header but for some reason including a smaller file is
unacceptable overhead.
> To this end, the user doesn't have to include anything more than
> `<boost/unordered/unordered_flat_map.hpp>`, which they would already have.
>
> The cool thing about Boost is that we're supposed to innovate and that
> means trying new things. I'm not saying Range-ifying everything is bad and
>
It was always a range, the most relevant function is even called
equal_range. The map is already a range and the selected subset via a key
is naturally a range for single and multi associative containers.
What was done was not rangifying everything. It was continuing with ranges
avoiding option-ifying the solution.
The going in and out of optional is pointless additional overhead most of
the time introducing opportunity for error. You were right to choose the
optional::map member function in your final example as the safest solution.
This good choice made it clear that the optional was neither necessary nor
desirable for this specific use-case.
I'm happy you're giving serious efforts into making it happen.
>
> I'm just trying to give my opinion about the potential reception of such
> efforts. It's fine on paper but I'm not sure we have users clamoring for
> the feature to manifest in this way.
>
Having produced something that works, builds in less time, almost matching
your syntactic ideal, and provides solutions for other contexts I expected
users would be more happy with this solution. You clearly have unique
access and understanding of the users requesting the original change.
If std ranges header is too bloated it could be split in a similar manner
to Boost.Range. The include demonstrably need not be as high overhead as
optional, when implemented appropriately.
> I'd be happy to be proven wrong.
> - Christian
>
I shall park the branch, assess the changing landscape including Range V3
and see if anything useful can be contributed.
I regret the noise I have made on the list. I genuinely have little
understanding of what you want, fully accepting my part in my lack of
comprehension. I will bow out from trying to help with this request.
Perhaps another Boost developer will succeed in understanding the issues
and context better, yielding a more agreeable result.
I hope you get what you want and one day I will understand this all better.
The best thing I can do for you at the moment is get out of the way.
Regards,
Neil Groves
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk