2017-06-05 19:59 GMT+02:00 Niall Douglas via Boost
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 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
> 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
>(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;