Boost logo

Boost :

Subject: Re: [boost] expected/result/etc
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2016-02-09 21:41:39


On Tue, Feb 9, 2016 at 3:41 PM, Gavin Lambert <gavinl_at_[hidden]> wrote:

> On 10/02/2016 09:04, Emil Dotchevski wrote:
>
>> The use of error codes in low level APIs is a fact of life, since most of
>> that code is written in C anyway. I wouldn't call it optimal in C++, I
>> personally convert error codes into exceptions at the earliest possible
>> opportunity. As for runtime overhead, like I said already, where it
>> matters
>> it can be easily deleted, by inlining; and, in such contexts you need to
>> inline with or without exception handling: I've never seen a case where I
>> could afford the overhead of a function call but could not afford the
>> exception handling overhead in the same function.
>>
>
> The overhead of exception-handling plumbing that is not actually exercised
> is typically minimal and not worth worrying about unless you're in one of
> those contexts where you begrudge every method call, as you've said.
>
> The overhead of a thrown exception is larger, particularly on those
> systems where throwing an exception also captures a stack trace (which is
> incredibly helpful for debugging, but sadly often quite expensive).
>

True, but I'm yet to encounter a case where I'd care about that overhead.
And I don't particularly care how that time compares to the amount of time
the successful path takes, since both of them typically vary significantly
from one platform to another. Assuming we're dealing with an exceptional
situation (something went wrong), that's not a problem.

Besides, I'd happily agree -- in the presence of profiler evidence -- that
if in a given use case exception handling overhead causes problems which
can not be alleviated by inlining a few functions, it shouldn't be used.
This is not because returning error codes is "better": in some cases we
also do need to resort to writing hand-crafted platform-specific assembly,
but we shouldn't argue that we can't use C++ in general because of overhead.

> The overhead of dealing with error return codes for uncommon failures is
> also fairly large, with the risk of ignoring them and ending up in weird
> states.
>
> The trick is to find the balance between them, with the complication that
> it may not be known at the library level which failures are exceptional and
> which are expected. As an example, I can imagine that most applications
> don't want a "delete file" method to throw an exception if the file is
> already absent -- but there might be some transactional systems in which
> that would be a serious problem, and checking for existence beforehand
> might not be sufficient as it would still be a race condition.
>

This reasoning is completely orthogonal to the error reporting design -- it
has to do with correctly defining the postconditions of the function, which
as you point out is domain-specific. Exceptions are used specifically to
enforce postconditions. If the correct postcondition of delete_file is "the
file does not exist", then it is incorrect to throw if the file was missing
to begin with.

> This sort of thing could be a good argument for "degrees of success",
> where eg. the above delete call returns success in both cases but can also
> indicate that the file was already missing and it did nothing. (Which is
> trivial in this case since it can be done with a simple bool return value,
> but you can probably imagine other cases where it might make sense to
> return both a T and a non-error status value of some kind.)

Assuming the correct postcondition for delete_file is "the file does not
exist", and assuming that knowing if the file existed is either important
or trivial for delete_file to detect, the correct interface of that
function is:

//Postconditions: the specified file does not exist.
//Returns: true if the file was actually deleted, false if it did not exist
//Throws: delete_file_error
bool delete_file( char const * name );

This is not "degrees of success", as the condition in which the file did
not exist is not an error.

Emil


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