Boost logo

Boost :

From: Neil Groves (neilgroves_at_[hidden])
Date: 2024-12-20 19:36:51


On Thu, 19 Dec 2024 at 15:30, Christian Mazakas via Boost <
boost_at_[hidden]> wrote:

> The case against a free function gets a lot stronger once you remember that
> optional in C++ still supports unchecked accesses with trivial syntax and
> that
> the most ergonomic and safe way to actually use it is via something like
> this:
>
> users.find(user_id).map([](auto& user) { user.status = deactivated;
> return user; });
>
>
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 have working on a private branch (without new member functions in any
associative container):

users | mapped_values(user_id) | invoke([](user_type& user) { user.status =
deactivated; });

To me, this looks remarkably similar to your example.

This works for std::map, std::multimap, std::unordered_map and
std::unordered_multimap. I find this more readable than the original. Of
course, this is for one very specific example and I lack support for many
of the functions that boost::optional has that one may likely wish for when
using a container that has at most 1 mapped_value per key.

mapped_values(key) is a Boost.Range adaptor similar to the
existing "map_values" except that it takes a key parameter and applies
equal_range to the source range before extracting the mapped_type. I did
also find the map adaptors in Boost.Range to be unnecessarily fussy about
const-ness propagation. I had to fix this on my branch to make any
substantial progress.

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.

Were this a free function, a user wouldn't be able to create this nice
> fluent interface
> that users, by and large, seem to actually like.
>
>
For the left-to-right syntax I noticed that there has been a neat looking
proposal
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2011r0.html

I'm hoping the left-to-right solution will appear by one or more of
the active proposals while we make progress coping with the ways we have.

> - Christian
>
>
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,

Neil Groves


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