Boost logo

Boost :

Subject: Re: [boost] Outcome/expected/etc/etc/etc
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-06-05 17:59:46


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

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