|
Boost : |
From: Neil Groves (neilgroves_at_[hidden])
Date: 2024-12-17 16:47:34
On Tue, 17 Dec 2024 at 16:20, Alexander Grund via Boost <
boost_at_[hidden]> wrote:
> > Working with ranges is an interesting idea, and comparisons to
> > std::ranges::find might encounter obstacles. I presume that the OP was
> > talking about returning an optional value given the key. This presumes
> > an associative container.
> Why limit this to associative containers? A generic version can search a
> std::vector as well as a std::set or boost::unordered_map
> You just need to dispatch to either container.find or fallback to std::find
>
I'm just prototyping something to explain my mental model clearly. There is
a little more to it than just container.find or std::find because we have
std::map<K,V> where we probably want to return the an appropriate reference
to the mapped_type when found (V& or const V&), and the mapped_type of a
set (also V, of course) but requires different implementation. In other
words, for std::map we would need to return it->second rather than *it upon
a successful lookup.
> > I am not too familiar with ranges, is there
> > an "associative range" concept? I do like the default value idea
> > though, thanks for that :)
>
We can get what we want by using "if constexpr" and "requires" or by
defining new concepts. We need to obtain the return value differently for
map and set, since the expectation, I assume, is that we return the
appropriate reference to the mapped_type, rather than the value_type.
> Having the optional return type you get the default for free:
> find(...).value_or()
> I'm not too sure about supporting ranges: The hypothetical find function
> would return an optional reference.
>
I see no reason to force it to always return an optional reference, or
anything optional. That seems to prematurely restrict the implementation.
Consider sentinel values for the return, especially containers with
non-null pointers, often we can return nullptr to indicate the item is not
found. The proposed solution works for this common case, and many others
besides, and still supports optional should one want to represent the
default value in this manner.
> So we have the footgun of getting dangling references already when
> someones does `find(build_map(), key)`
> We can avoid that by deleting the overload for rvalues but i guess for
> ranges we might not be able to easily detect an underlying temporary.
>
Is there a new lifetime issue given that std::ranges::find already exists
and works. Our additional layer can take the default by universal reference
and forward as the result? I shall post some code a little later, possibly
tomorrow. Then we can debate the alternatives a little more concretely.
Neil Groves
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk