C++ Logo


Advanced search

Re: Yet another member function for std::map

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Mon, 02 Aug 2021 10:28:23 +0100

4) optional<T&> implies the existence of optional<T&&>. Given that operator* already preserves value category for optional<T>, this could be really convenient in generic context. Not unlike tuple and get/apply.

The Achilles' heel of optional<T&> seems to be assignment. I'm of the opinion that it simply shouldn't have assignment from arguments of type T, but I believe there is no perfect answer.


-------- Original Message --------
From: Andrey Semashev via Std-Proposals <std-proposals_at_[hidden]>
Sent: August 1, 2021 9:15:09 PM GMT+01:00
To: std-proposals_at_[hidden]
Cc: Andrey Semashev <andrey.semashev_at_[hidden]>
Subject: Re: [std-proposals] Yet another member function for std::map

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.

> Your optional<pointer_wrapper<T>> does not address problem 1. But it
> addresses problem 2 in an especially weird way that violates the
> semantics that optional<U> holds a U (or not). You would have
> optional<U> holds a U, except when U=pointer_wrapper<T> in which case it
> holds a T&? That makes it tedious to use for consumers in a different
> way, because you're breaking the semantics of optional. For instance,
> implementing map as a free function taking an optional<U> and a function
> object F would typically check is F is invocable<U&>, which is correct
> for optional as it exists today and would still be correct for
> optional<T&>, but that would no longer be correct for your
> specialization since you would end up with both false positives and
> false negatives (since the type that you're constraint checking with and
> the type that you're actually invoking the function with differ).
> Barry

Std-Proposals mailing list

Received on 2021-08-02 04:28:31