Boost logo

Boost :

From: Richard Hodges (hodges.r_at_[hidden])
Date: 2024-12-21 07:21:07


Sent from my iPad

> On 20 Dec 2024, at 20:37, Neil Groves via Boost <boost_at_[hidden]> wrote:
>
> 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; });

How is this better than

for(auto&& user : users)
  if(user == user_id)
    deactivate(user);

?

My thoughts on the pipeline code:
- It took a while to figure out what it was doing.
- you can’t easily place a breakpoint in it
- it’s only possible with a load of cryptic template expansion
- requires a deep knowledge of not only the language and template but also the helper library.

Whereas the procedural code is:
- absolutely obvious in its intent
- easily debuggable
- implemented using only the language and no template help at all
- trivially teachable

> 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
>
> _______________________________________________
> 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