Boost logo

Boost :

Subject: Re: [boost] Outcome/expected/etc/etc/etc
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-06-06 08:24:08


2017-06-05 19:59 GMT+02:00 Niall Douglas via Boost <boost_at_[hidden]>:

> > I see this as a promising direction because it would allow you to store
> > both an error and an exception, as per the other thread. Then you can
> > fully represent a Filesystem function with an outcome return value,
> > because you'll be able to store the error_code return in error() and the
> > filesystem_error exception in exception().
> >
> > The actual behavior of Outcome won't change that much, because if you
> > only look at its observable state as told by the accessors, logically
> > it's not a variant, because both has_error and has_exception report true
> > at the same time. In fact has_error == has_exception if I'm not mistaken?
>
> Currently has_error() = true if and only there is an error stored.
> has_exception() = true if error or exception stored.
>
> If one is removing the variant storage and gaining .has_failure(), I
> think .has_exception() would simply report true if there is an exception
> in there.
>
>
> I do feel considerable concern with your idea of using the exception_ptr
> as a payload for the error code. I appreciate the use case for the
> Filesystem TS, but I feel the fact that the Filesystem TS returns more
> information via the exception throw mechanism than via the error_code
> mechanism to be an awful mistake. Some other mechanism should have been
> chosen to make both of equal information returning value instead of
> splitting the two and making the error code returning overloads inferior
> like that. After all, the latter are the natural fit for a Filesystem
> library. The former are inappropriately heavyweight.
>
> What I could live with though is this synopsis:
>
> template<class T, class P = shared_ptr<void>, class EC = error_code,
> class E = exception_ptr> class outcome
> {
> T _value;
> EC _error;
> union
> {
> P _payload;
> E _exception;
> };
> };
>
> I personally really wish that shared_ptr could be constructible from an
> exception_ptr as they surely are implemented the same way on any
> standard library implementation I could think of, but at least the above
> correctly lets payload be any type-erased shared_ptr, which is the
> correct and appropriate type for returning type-erased payload unlike
> exception_ptr.
>
> The question now becomes this: surely the Filesystem TS is cleaner if
> when returning an errored outcome it supplied a shared_ptr<pair<path,
> path>> instead of the exception_ptr to the filesystem_error that would
> have been thrown? Advantages:
>
> 1. I would also be fairly sure, without having benchmarked it, that
> make_shared<pair<path, path>>(path1, path2) will be many times faster
> than make_exception_ptr(filesystem_error(path1, path, ec)) on most
> standard library implementations.
>
> 2. make_exception_ptr(filesystem_error(path1, path, ec)) will return a
> null pointer if C++ exceptions are disabled on at least libstdc++, and
> thus your proposal would be a problem for those users running with
> exceptions off.
>
> What do you think?
>

I will not address your question directly; but let me offer a remark.

It was my understanding that `error_code_extended`, along with its ring
buffer usage, was provided to address exactly this problem: provide
additional payload to `std::error_code`. The current exercise with adapting
the Filesystem TS can be considered a test of the usefulness of
`error_code_extended`.

Some questions arise that i will surely ask in the second review of
Boost.Outcome (I hope we will have one):

1. Can `result` be used to successfully replace error handling in
Filesystem TS?
2. If I carry arbitrary payload with a `result` do I need the ring buffer
for anything?

Regards,
&rzej;


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