C++ Logo

std-proposals

Advanced search

Re: Yet another member function for std::map

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Mon, 2 Aug 2021 07:59:50 +0100
On Sun, 1 Aug 2021 at 21:15, Andrey Semashev via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 8/1/21 10:52 PM, Barry Revzin via Std-Proposals wrote:
> >
> >
> > On Sun, Aug 1, 2021 at 2:41 AM Fabio Alemagna <falemagn_at_[hidden]
> > <mailto:falemagn_at_[hidden]>> wrote:
> >
> >
> >
> > Il giorno gio 29 lug 2021 alle ore 02:30 Barry Revzin via
> > Std-Proposals <std-proposals_at_[hidden]
> > <mailto:std-proposals_at_[hidden]>> ha scritto:
> >
> >
> > What would you do if value_at returned a T*? You can't do
> > value_or() on a T*, because pointers have very few operations
> > you can do on them (and nearly all of those would be straight up
> > invalid in this use-case - which does not make for a great API!)
> > you'd either push for some language feature that does that or
> > you'd write some non-member function that handles this case.
> > Which would be fine for value_or(), but not for any number of
> > other operations that work for optional but not for pointers.
> > What if you wanted the size of the span there, or 0?
> >
> > With optional, these things just compose straightforwardly, so:
> > m.value_at(p).transform(ranges::size).value_or(0)
> >
> > How do you do that with a pointer?
> >
> > Note that neither of these examples work with
> > optional<reference_wrapper<T>> either.
> >
> >
> > It seems to me you do need a pointer, because they carry an
> > intrinsic "optionality" semantics with themselves, yet bare pointers
> > lack the functionalities std::optional has, such as the value_or()
> > method and possibly others. As already stated one can't have
> > std::optional<T&> and std::optional<std::reference_wrapper<T>> is a
> > substitute of it.
> >
> > But I believe we can have the best of both worlds: we could wrap a
> > pointer into a special type that std::optional would be specialized
> > over, so that you can actually do things like
> >
> > m.value_at(p).value_or(...);
> >
> > As in the below example:
> >
> > int main() {
> > test_class test("hello");
> >
> > std::cout << test.value_at("hello").value_or("not found") <<
> > std::endl;
> > std::cout << test.value_at("unexisting").value_or("not found")
> > << std::endl;
> >
> > return 0;
> > }
> >
> > Which would produce this output:
> >
> > hello
> > not found
> >
> > I've built a working example on godbolt. Have a look:
> > https://godbolt.org/z/6K7ahb3v4 <https://godbolt.org/z/6K7ahb3v4>
> >
> > Regards,
> > Fabio
> >
> >
> > The reason optional<T&> is a vastly superior solution to
> > optional<reference_wrapper<T>> is because:
> >
> > 1) Given a U, you want to be able to write optional<U>. The former lets
> > you do that, and the latter requires you to write
> > optional<some_metafunction<U>> - which is very tedious for producers.
> > 2) optional<T&> holds a T&, but optional<reference_wrapper<T>> holds a
> > reference_wrapper<T> - those have very different API surfaces, the
> > former being much easier to use - unless you do more metaprogramming -
> > which is very tedious for consumers.
>
> 3) optional<T&> can be optimized to store T* inside while
> optional<reference_wrapper<T>> cannot.
>

Well, given that the same library provides both, actually it can - you'd
just need to make optional<reference_wrapper<T>> a friend of
reference_wrapper<T> so that it can put the latter into a hidden singular
state.

Received on 2021-08-02 02:00:14