Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2024-12-21 13:24:42


Neil Groves wrote:
> On Sat, 21 Dec 2024 at 12:11, Peter Dimov via Boost <boost_at_[hidden]
> <mailto:boost_at_[hidden]> > wrote:
>
>
> That's why I'm always defining a helper function `lookup` that returns a
> pointer, which allows me to write this instead:
>
> if( auto p = lookup( map, key ) )
> {
> // do something with *p
> }
>
> If there's a built-in way to obtain an optional<mapped_type&> instead
> of an iterator, I can use that instead of `lookup`, without changing the
> syntax.
>
>
>
> What I tried to do was provide that with map.equal_range(key) |
> mapped_value | invoke(fn). And then tidy the syntax, but I accept that wasn't
> an outstanding success! I collapsed the map.equal_range and mapped_value
> into one step and then we had map | mapped_values(key) | invoke([](...) {})
>
> In the end what I had for you paraphrasing you snippet above would be:
>
> map | mapped_values(key) | invoke([&](auto&& p) {
> // do something with p
> };

That's nice enough. I would probably have called the first adaptor
`values_for_key` instead of `mapped_values`. We can also collapse
the two into `invoke_for_key`.

This is only part of the story though. First, you need to specify what's the
result of `| invoke`, can I chain additional adaptors after it, and if so,
what range do they see.

Second, my example allows for an `else` clause:

  if( auto p = lookup( map, key ) )
  {
    // do something with *p
  }
  else
  {
    // handle the case when `key` isn't in `map`
  }

Third, in my example, you can `return` from the branches, whereas
in yours, `return` would return from the lambda. (`break`, `continue`
pose similar problems.)

E.g.

  for(auto key: keys )
  {
    if( auto p = lookup( map, key ) ) return *p;
  }


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