Boost logo

Boost :

Subject: Re: [boost] Noexcept
From: charleyb123 . (charleyb123_at_[hidden])
Date: 2017-06-13 22:07:22


>
> > Emil Dotchevski wrote:
> >
> >> If error codes are treated as "the error", then the error domain is
> >> limited to a single function. Consider these two functions:
> >>
> >> int f1(....); //returns 0 on success, 1-f1_error1, 2-f1_error2
> >> int f2(....); //returns 0 on success, 1-f2_error1, 2-f2_error2
> >>
> >> If f2 calls f1, if the error is communicated by an error code, f2 _must_
> >> translate the error condition from the domain of f1 errors, to the
> domain
> >> of f2 errors. And this must be done at every level, which introduces
> many
> >> points in the code where subtle errors may occur, and that is in error
> >> handling code which is very difficult to test and debug.
>

Peter Dimov replied:

> > That's exactly the problem std::error_code solves, as it's a (code,
> > domain) pair, so there's no need to translate.
>

Emil Dotchevski responded:

> That presumes that ENOENT represents the same _error_ when returned from
> two different functions. Generally, it does not. The correct strategy in
> C++ is to throw different types to indicate different errors, even when
> both end up carrying the same ENOENT.
>
> So it is critical to decouple the error code (std or otherwise) from _what_
> went wrong, and if you don't, you're butchering the ability to write
> error-neutral functions, which in practice means translating error codes
> from one domain to another, at every level, which is prone to errors.
>

Agree with your concern that an 'ENOENT' value may semantically mean
different things in different contexts (or not, depending on a specific
cross-domain mapping).

However, the 'std::error_code' implementation is intended to type-erase
those semantically-different meanings into the same object-type, but to
permit that "difference-checking" that would otherwise be performed with
different types, such as your example to throw two types to semantically
represent two different domains of errors.

class f1_domain : public std::error_category { ... };
class f2_domain : public std::error_category { ... };

std::error_code f1(...) { ...; return make_error_code(ENOENT,
get_f1_domain()); }
std::error_code f2(...) { ...; return make_error_code(ENOENT,
get_f2_domain()); }

{
  ...
  if(f1() == f2()) // ...can be true-or-false...
  {
    ...
  }
}

The "type-erasure" implementation within 'std::error_code' is provided by
the cross-domain mapping implemented in 'f1_domain' and/or 'f2_domain' (by
overriding virtual functions from 'std::error_category').

So, agree with your assertion that throwing different types will
disambiguate; but the 'std::error_code' attempts to similarly keep that
different-domain distinction, but through type-erasure (provided through
'std::error_category').


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