Boost logo

Boost :

Subject: Re: [boost] [outcome] To variant, or not to variant?
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-31 13:15:21


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.

>> 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.

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.
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.

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.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk