|
Boost : |
Subject: Re: [boost] [review] Review of Outcome v2 (Fri-19-Jan to Sun-28-Jan, 2018)
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2018-02-02 01:29:26
On 1/02/2018 19:55, Emil Dotchevski wrote:
> This does not protect the user at all:
>
> std::unique_ptr<A> a=A::create();
> a->foo(); //undefined behavior
Sure, but you can always write daft code. If you are aware that it is
legal for A::create() to return nullptr (and you should be aware,
because it will be documented), then the above would be an obvious bug,
and you should replace it with:
if (auto a = A::create())
{
a->foo();
}
This is *much* more obviously safe than your suggested exception-enabled
code, where you have to have external knowledge (that it will throw on
failure and cannot ever return nullptr). And it's trivial to add logic
for the failure case in an else block, vs. the more wordy try-catch.
(Even if you don't know whether A::create() is supposed to be able to
return nullptr or not, it is usually more sensible to defensively write
the code as if it could, since it is a legal value of the return type,
regardless of whether exceptions are enabled or not.)
Granted, exceptions are better at telling you *why* it failed, which the
above can't. And exceptions are better at hiding the error-handling
paths for the cases where errors are expected to be exceptionally rare
(pun intended), which can make the "real" logic not get lost in a maze
of error-handling. Most people appreciate that -- but sometimes having
explicit error paths is useful too.
Nobody is forcing you to stop using exceptions, or even encouraging the
majority of applications to stop using them. Outcome just provides a
way to add back a little (or a lot, as needed) explanation to failure in
cases where someone has already decided they can't or don't want to use
exceptions for whatever reason -- especially when failure is expected,
not unusual (I think everybody agrees that exceptions-as-control-flow is
not good code design, right?).
> This is not an advantage over using exceptions, and besides it is only true
> in the simplest of cases. The problem is that Outcome requires users to fit
> any and all possible failures into a single error type, which is not always
> possible. In general, you can neither enumerate nor reason about all
> failures which may occur. Notably, the one Outcome feature that can deal
> with this problem is its ability to transport std::exception_ptr. :)
One error type per context. You can have completely different error
enumerations per method if you really want to, although it would
probably be more common to have one error domain per library, or just
use the closest approximation from a standard set, like POSIX errno. Or
use error_code, which allows relatively seamless interoperation with all
of these.
Exceptions are actually a relatively poor method for transporting errors
that need to be *reacted* to. (Not so much through any fault of
exceptions themselves, but rather through common usage thereof.)
In most code, the best you can do with them is catch them in some
central place and log them for some developer to look at later. Too
many methods just throw one of the standard types like
std::runtime_error without defining custom subclasses or adding anything
more programmatically useful beyond the text message -- which in itself
can be a problem for multi-lingual applications, especially where the
thread that generated the exception is running in a different language
context from the developer and/or user.
At least an error code is inherently an abstract thing that you know you
need to look up a translation for at the last moment when actually
presenting it to the user, or that logic can easily say "in this
context, I was expecting that and I know how to deal with it".
Sure, it's possible to add error codes and extra data fields to
exceptions and allow the message to be constructed later from these
pieces. And it's not possible to do this with error_code alone. But it
will be possible to do this with Outcome. (And most people don't do it
anyway, no matter the error transport.)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk