
My 2c... Almost all the asio client code I have written in the past 4 years uses handlers like this: async_xxx(xxx, [self = this->shared_from_this()](auto&& ec) { if (ec) { self->xxx_error(ec); } else { self->please_carry_on(); } }); Because it seemed logically obvious that ec would be true if it contained an error. I did once notice that when writing my own boost::system category that a zero error code broke this, so made a mental note to avoid zero error codes in custom error schemes (e.g. rpc_error, database_error, message_bus_error etc.) So for my part, although I loathe the idea of changing interfaces, this interface seems broken and probably could do with being changed. Perhaps there should be a category of errors which is std::success and another std::success_with_warning? In this way, NT error codes could be propagated more accurately. Re outcome, I was a sceptic to being with (why would be wrap a variant<X, error_code>?) but now I see that it's preferable. Ideally there should be no system_error indicating success at all. That would ensure more robust logical handling of errors in all cases. I eagerly await the release of boost.outcome. I plan to retro-fit it into all my custom asio services. I am sure it will expose a number of subtle bugs. R On 15 January 2018 at 04:54, Gavin Lambert via Boost <boost@lists.boost.org> wrote:
On 14/01/2018 18:02, Peter Dimov wrote:
`f` should not need to know what errors are being returned by `do_f1`, `do_f2`, `do_f3`, in order to check whether the calls succeeded; the whole point of using error_code is that errors from different domains can be handled in a generic manner.
This is similar to exceptions; `f` needs not know what callees can throw. Today, `do_f1` is implemented with backend A, so it throws A-flavored exceptions; tomorrow, it switches to backend B and throws B-flavored exceptions. The logic in `f` doesn't change.
In the same way, whether `do_f1` returns error codes of category A or category B should not matter for the logic in `f`. There must exist a generic way to test for failure. If !ec is not it, well, then !ec shouldn't be used and we need something that is and should be.
I think Christopher's assertion works in a world where error_codes are never blindly propagated upwards; regardless of whether library X uses library A or library B under the hood, it must only return standard errors or library X errors to its external callers, never library A or B errors. (It's up to the library itself when to do the conversion, but it usually makes the most sense to do it as soon as possible.)
I think the general consensus from the Outcome discussion was that this is not the desired practice and that error_codes are indeed supposed to be propagated unmodified for the most part.
I haven't quite worked out yet where I stand on that; I think I'd prefer if the error codes were converted but it was still possible to obtain a "history" of an error, somewhat like nested exceptions. But I also recognise that that could have significant performance drawbacks.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost