C++ Logo

std-proposals

Advanced search

Re: P0323 std::expected - void value type?

From: Emile Cormier <emile.cormier.jr_at_[hidden]>
Date: Mon, 5 Oct 2020 12:41:46 -0300
Thanks, Arthur. Thinking of expected as a "wrapper" around a return type
makes more sense to me now than thinking of it as a "container of one or
error".

If C/C++ had been designed with void being an empty monostate value type, I
guess we wouldn't have all this trouble of treating void as a special case
in generic programming. Libraries wouldn't have needed to invent their own
"nothing" types like nullopt_t or monostate_t.

On Sun, Oct 4, 2020 at 11:27 PM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:

> On Sun, Oct 4, 2020 at 5:21 PM Emile Cormier via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi Everyone. This is my first time posting to this group, so please be
>> gentle. :-) [...]
>> I am questioning the rationale of allowing void as a value type for
>> std::expected. As I understand it, expected is supposed to be a "vocabulary
>> type" similar to std::optional, or std::variant, yet the latter two don't
>> permit void as one of their contained types (as far as I know).
>>
>
> Right, but std::future/std::promise do.
> The idea behind future<void> is that we want to be able to write
> auto async(auto f) -> std::future<decltype(f())>;
> without worrying about some special case when f() is void, or when f()
> returns a reference type. We want it to *just work* with any return-able
> type.
>
> Similarly, expected<T,E> is at least arguably supposed to be used as a
> return type:
> auto probably_but_not_certainly(auto f) ->
> std::expected<decltype(f()), E>;
> So it makes sense for it to support all return-able types.
>
> "But what about optional<T>?" you say, rightfully.
> auto maybe(auto f) -> std::optional<decltype(f)>; // not generic
> You can't use this `maybe` on callables that return void, nor on callables
> that return references. Why not? Well, definitely an artifact of the
> standardization process. I would say that std::optional was trying to serve
> two masters. On the one hand it's trying to be a generic utility type, but
> it's also looking up to its big brother std::tuple, which *itself *was
> serving two masters — std::make_tuple/std::forward_as_tuple on the one hand
> and std::tie on the other. So it became unclear whether std::optional<U&>
> should have copy semantics like std::reference_wrapper<U>, or
> assign-through semantics like std::tuple<U&>. JeanHeyd Meneide has a blog
> post from January 2020 on the subject:
> https://thephd.github.io/to-bind-and-loose-a-reference-optional
>
> HTH,
> Arthur
>

Received on 2020-10-05 10:42:03