|
Boost : |
Subject: Re: [boost] [outcome] To variant, or not to variant?
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-06-01 07:26:42
2017-05-31 19:06 GMT+02:00 Vicente J. Botet Escriba via Boost <
boost_at_[hidden]>:
> Le 31/05/2017 à 15:15, Niall Douglas via Boost a écrit :
>
>> On 31/05/2017 11:31, Vicente J. Botet Escriba via Boost wrote:
>>
>>> Does none_t mean success or failure?
>>> For what I see it means failure as it is not the result of value().
>>> In addition it default construct to none_t.
>>>
>>> The mental model for me is
>>> variant<optional<T>, error_code, exception_ptr>> m_storage;
>>>
>> Surely it is actually:
>>
>> variant<monostate, T, error_code, exception_ptr>
>>
>> std::monostate at the front of the typelist gives std::variant
>> default-construct-to-empty semantics.
>>
> optional<T> also give you that :)
>
>>
>> Perhaps this could even be exposed even more so that user code could
>>>> explicitly provide both a value and an error -- think "here's a value,
>>>> but it was truncated" or "here's the 5 values you asked for, but
>>>> there's more", both fairly common in system APIs. Or for things like
>>>> ambiguous matches where you still return the most likely candidate.
>>>> Or dictionary insertion (duplicate key, but here's the value that's
>>>> already there). Or many more such examples. (Though obviously in this
>>>> case value() couldn't call ensure(). But that should make some people
>>>> happy.)
>>>>
>>>> This corresponds to the status_value [1] model where you store the
>>> reason why you don't have a value or why you have it and an
>>> optional<value>. As described by L. Crowl in [2], there are use cases
>>> for status_value, expected and exceptions.
>>>
>> Personally speaking, I have not found Lawrence's status_value proposal
>> sufficiently value-adding over returning a std::pair to be worth
>> implementing. Also, the STL already uses std::pair throughout for status
>> returns, it's the convention, though I will agree to use it is mildly
>> clunky e.g. unordered_map::insert().first.
>>
> Things are changing in the standard. We want more explicit types.
> status_value is a very good class that responds to real cases.
>
>>
>> Now, that said, if expected<T, E> and status_value<Status, Value> could
>> be combined into a single object, that I can see significant value in.
>>
> Why and how do you want to combine them. One is a sum type the other a
> product type.
> These classes are useful on its own use cases.
>
>> It's something I've often pondered for Outcome as well because it could,
>> if done right, let me eliminate error_code_extended.
>>
>> The main thing which has stopped me is the potential confusion. For
>> example, right now we have result<T> which can be
>> empty|T|error_code_extended. If I instead made:
>>
>> template<class T, class Payload = void> class result;
>>
>> Now result could be (empty|T|std::error_code U Payload). But if this
>> review to date with 600+ emails has been complicated, imagine a review
>> of such a payload-carrying result object?
>>
>> std::error_code + payload is obvious. But, what does an empty state +
>> payload mean? I have no idea.
>>
>> Indeed, what does a T state + payload mean? I guess that is Lawrence's
>> status_value<> use case, but the problem is that the Payload type is
>> fixed between variant states of empty|T|std::error_code and that surely
>> is not particularly useful, you'd want different payload types with each
>> of T or std::error_code. That's why I didn't implement it.
>>
> You lost me.
>
>>
>> Still, I'd be interested in what people think. The other option is
>> empty|T|status_value<std::error_code, Payload>, that would make more
>> sense, but at the potential cost of bloating the stack significantly
>> which could surprise end users in a way error_code_extended can not.
>>
>> You lost me definitely.
>
> status_value is a product type because we need some additional information
> even when the operation succeeds. The status is there to convey this
> information, but conveys also the information explaining why the result is
> not there.
>
> status_value<S,T> could be seen as pair<variant<Sucsess, Failure>,
> optional<T>>
>
> There is an invariant Success <=> optional present and Failure <=>
> optional not present.
>
> You could as well see it as variant<pair<Sucsess, T>, Failure> or
> expected<pair<Sucsess, T>, Failure>
>
What the OP means is that status_value can bee seen as a "superset" of
expected. It can cover all cases `expected` covers plus more. Of course,
this "more" is not necessarily better or harmless.
Regards,
&rzej;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk